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 with_options: Vec<SqlOption>,
1488 operation: AlterSecretOperation,
1489 },
1490 AlterFragment {
1492 fragment_ids: Vec<u32>,
1493 operation: AlterFragmentOperation,
1494 },
1495 AlterDefaultPrivileges {
1498 target_users: Option<Vec<Ident>>,
1499 schema_names: Option<Vec<ObjectName>>,
1500 operation: DefaultPrivilegeOperation,
1501 },
1502 Describe {
1504 name: ObjectName,
1506 kind: DescribeKind,
1507 },
1508 DescribeFragment {
1510 fragment_id: u32,
1511 },
1512 ShowObjects {
1514 object: ShowObject,
1515 filter: Option<ShowStatementFilter>,
1516 },
1517 ShowCreateObject {
1519 create_type: ShowCreateType,
1521 name: ObjectName,
1523 },
1524 ShowTransactionIsolationLevel,
1525 CancelJobs(JobIdents),
1527 Kill(String),
1530 Drop(DropStatement),
1532 DropFunction {
1534 if_exists: bool,
1535 func_desc: Vec<FunctionDesc>,
1537 option: Option<ReferentialAction>,
1539 },
1540 DropAggregate {
1542 if_exists: bool,
1543 func_desc: Vec<FunctionDesc>,
1545 option: Option<ReferentialAction>,
1547 },
1548 SetVariable {
1554 local: bool,
1555 variable: Ident,
1556 value: SetVariableValue,
1557 },
1558 ShowVariable {
1562 variable: Vec<Ident>,
1563 },
1564 StartTransaction {
1566 modes: Vec<TransactionMode>,
1567 },
1568 Begin {
1570 modes: Vec<TransactionMode>,
1571 },
1572 Abort,
1574 SetTransaction {
1576 modes: Vec<TransactionMode>,
1577 snapshot: Option<Value>,
1578 session: bool,
1579 },
1580 SetTimeZone {
1582 local: bool,
1583 value: SetTimeZoneValue,
1584 },
1585 Comment {
1589 object_type: CommentObject,
1590 object_name: ObjectName,
1591 comment: Option<String>,
1592 },
1593 Commit {
1595 chain: bool,
1596 },
1597 Rollback {
1599 chain: bool,
1600 },
1601 CreateSchema {
1603 schema_name: ObjectName,
1604 if_not_exists: bool,
1605 owner: Option<ObjectName>,
1606 },
1607 CreateDatabase {
1609 db_name: ObjectName,
1610 if_not_exists: bool,
1611 owner: Option<ObjectName>,
1612 resource_group: Option<SetVariableValue>,
1613 barrier_interval_ms: Option<u32>,
1614 checkpoint_frequency: Option<u64>,
1615 },
1616 Grant {
1618 privileges: Privileges,
1619 objects: GrantObjects,
1620 grantees: Vec<Ident>,
1621 with_grant_option: bool,
1622 granted_by: Option<Ident>,
1623 },
1624 Revoke {
1626 privileges: Privileges,
1627 objects: GrantObjects,
1628 grantees: Vec<Ident>,
1629 granted_by: Option<Ident>,
1630 revoke_grant_option: bool,
1631 cascade: bool,
1632 },
1633 Deallocate {
1637 name: Option<Ident>,
1638 prepare: bool,
1639 },
1640 Execute {
1644 name: Ident,
1645 parameters: Vec<Expr>,
1646 },
1647 Prepare {
1651 name: Ident,
1652 data_types: Vec<DataType>,
1653 statement: Box<Statement>,
1654 },
1655 Explain {
1657 analyze: bool,
1659 statement: Box<Statement>,
1661 options: ExplainOptions,
1663 },
1664 ExplainAnalyzeStreamJob {
1669 target: AnalyzeTarget,
1670 duration_secs: Option<u64>,
1671 },
1672 CreateUser(CreateUserStatement),
1674 AlterUser(AlterUserStatement),
1676 AlterSystem {
1678 param: Ident,
1679 value: SetVariableValue,
1680 },
1681 Flush,
1685 Wait,
1688 Recover,
1690 Use {
1694 db_name: ObjectName,
1695 },
1696 Vacuum {
1700 object_name: ObjectName,
1701 full: bool,
1702 },
1703}
1704
1705#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1706pub enum DescribeKind {
1707 Plain,
1709
1710 Fragments,
1712}
1713
1714impl fmt::Display for Statement {
1715 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1720 let sql = self
1722 .try_to_string()
1723 .expect("normalized SQL should be parsable");
1724 f.write_str(&sql)
1725 }
1726}
1727
1728impl Statement {
1729 pub fn try_to_string(&self) -> Result<String, ParserError> {
1733 let sql = self.to_string_unchecked();
1734
1735 if matches!(
1737 self,
1738 Statement::CreateTable { .. } | Statement::CreateSource { .. }
1739 ) {
1740 let _ = Parser::parse_sql(&sql)?;
1741 }
1742 Ok(sql)
1743 }
1744
1745 pub fn to_string_unchecked(&self) -> String {
1751 let mut buf = String::new();
1752 self.fmt_unchecked(&mut buf).unwrap();
1753 buf
1754 }
1755
1756 #[allow(clippy::cognitive_complexity)]
1763 fn fmt_unchecked(&self, mut f: impl std::fmt::Write) -> fmt::Result {
1764 match self {
1765 Statement::Explain {
1766 analyze,
1767 statement,
1768 options,
1769 } => {
1770 write!(f, "EXPLAIN ")?;
1771
1772 if *analyze {
1773 write!(f, "ANALYZE ")?;
1774 }
1775 write!(f, "{}", options)?;
1776
1777 statement.fmt_unchecked(f)
1778 }
1779 Statement::ExplainAnalyzeStreamJob {
1780 target,
1781 duration_secs,
1782 } => {
1783 write!(f, "EXPLAIN ANALYZE {}", target)?;
1784 if let Some(duration_secs) = duration_secs {
1785 write!(f, " (DURATION_SECS {})", duration_secs)?;
1786 }
1787 Ok(())
1788 }
1789 Statement::Query(s) => write!(f, "{}", s),
1790 Statement::Truncate { table_name } => {
1791 write!(f, "TRUNCATE TABLE {}", table_name)?;
1792 Ok(())
1793 }
1794 Statement::Refresh { table_name } => {
1795 write!(f, "REFRESH TABLE {}", table_name)?;
1796 Ok(())
1797 }
1798 Statement::Analyze { table_name } => {
1799 write!(f, "ANALYZE TABLE {}", table_name)?;
1800 Ok(())
1801 }
1802 Statement::Describe { name, kind } => {
1803 write!(f, "DESCRIBE {}", name)?;
1804 match kind {
1805 DescribeKind::Plain => {}
1806
1807 DescribeKind::Fragments => {
1808 write!(f, " FRAGMENTS")?;
1809 }
1810 }
1811 Ok(())
1812 }
1813 Statement::DescribeFragment { fragment_id } => {
1814 write!(f, "DESCRIBE FRAGMENT {}", fragment_id)?;
1815 Ok(())
1816 }
1817 Statement::ShowObjects {
1818 object: show_object,
1819 filter,
1820 } => {
1821 write!(f, "SHOW {}", show_object)?;
1822 if let Some(filter) = filter {
1823 write!(f, " {}", filter)?;
1824 }
1825 Ok(())
1826 }
1827 Statement::ShowCreateObject {
1828 create_type: show_type,
1829 name,
1830 } => {
1831 write!(f, "SHOW CREATE {} {}", show_type, name)?;
1832 Ok(())
1833 }
1834 Statement::ShowTransactionIsolationLevel => {
1835 write!(f, "SHOW TRANSACTION ISOLATION LEVEL")?;
1836 Ok(())
1837 }
1838 Statement::Insert {
1839 table_name,
1840 columns,
1841 source,
1842 returning,
1843 } => {
1844 write!(f, "INSERT INTO {table_name} ", table_name = table_name,)?;
1845 if !columns.is_empty() {
1846 write!(f, "({}) ", display_comma_separated(columns))?;
1847 }
1848 write!(f, "{}", source)?;
1849 if !returning.is_empty() {
1850 write!(f, " RETURNING ({})", display_comma_separated(returning))?;
1851 }
1852 Ok(())
1853 }
1854 Statement::Copy { entity, target } => {
1855 write!(f, "COPY ",)?;
1856 match entity {
1857 CopyEntity::Query(query) => {
1858 write!(f, "({})", query)?;
1859 }
1860 CopyEntity::Table {
1861 table_name,
1862 columns,
1863 } => {
1864 write!(f, "{}", table_name)?;
1865 if !columns.is_empty() {
1866 write!(f, " ({})", display_comma_separated(columns))?;
1867 }
1868 }
1869 }
1870
1871 match target {
1872 CopyTarget::Stdin { values } => {
1873 write!(f, " FROM STDIN; ")?;
1874 if !values.is_empty() {
1875 writeln!(f)?;
1876 let mut delim = "";
1877 for v in values {
1878 write!(f, "{}", delim)?;
1879 delim = "\t";
1880 if let Some(v) = v {
1881 write!(f, "{}", v)?;
1882 } else {
1883 write!(f, "\\N")?;
1884 }
1885 }
1886 }
1887 write!(f, "\n\\.")
1888 }
1889 CopyTarget::Stdout => {
1890 write!(f, " TO STDOUT")
1891 }
1892 }
1893 }
1894 Statement::Update {
1895 table_name,
1896 assignments,
1897 selection,
1898 returning,
1899 } => {
1900 write!(f, "UPDATE {}", table_name)?;
1901 if !assignments.is_empty() {
1902 write!(f, " SET {}", display_comma_separated(assignments))?;
1903 }
1904 if let Some(selection) = selection {
1905 write!(f, " WHERE {}", selection)?;
1906 }
1907 if !returning.is_empty() {
1908 write!(f, " RETURNING ({})", display_comma_separated(returning))?;
1909 }
1910 Ok(())
1911 }
1912 Statement::Delete {
1913 table_name,
1914 selection,
1915 returning,
1916 } => {
1917 write!(f, "DELETE FROM {}", table_name)?;
1918 if let Some(selection) = selection {
1919 write!(f, " WHERE {}", selection)?;
1920 }
1921 if !returning.is_empty() {
1922 write!(f, " RETURNING {}", display_comma_separated(returning))?;
1923 }
1924 Ok(())
1925 }
1926 Statement::CreateDatabase {
1927 db_name,
1928 if_not_exists,
1929 owner,
1930 resource_group,
1931 barrier_interval_ms,
1932 checkpoint_frequency,
1933 } => {
1934 write!(f, "CREATE DATABASE")?;
1935 if *if_not_exists {
1936 write!(f, " IF NOT EXISTS")?;
1937 }
1938 write!(f, " {}", db_name)?;
1939 if let Some(owner) = owner {
1940 write!(f, " WITH OWNER = {}", owner)?;
1941 }
1942 if let Some(resource_group) = resource_group {
1943 write!(f, " RESOURCE_GROUP = {}", resource_group)?;
1944 }
1945 if let Some(barrier_interval_ms) = barrier_interval_ms {
1946 write!(f, " BARRIER_INTERVAL_MS = {}", barrier_interval_ms)?;
1947 }
1948 if let Some(checkpoint_frequency) = checkpoint_frequency {
1949 write!(f, " CHECKPOINT_FREQUENCY = {}", checkpoint_frequency)?;
1950 }
1951
1952 Ok(())
1953 }
1954 Statement::CreateFunction {
1955 or_replace,
1956 temporary,
1957 if_not_exists,
1958 name,
1959 args,
1960 returns,
1961 params,
1962 with_options,
1963 } => {
1964 write!(
1965 f,
1966 "CREATE {or_replace}{temp}FUNCTION {if_not_exists}{name}",
1967 temp = if *temporary { "TEMPORARY " } else { "" },
1968 or_replace = if *or_replace { "OR REPLACE " } else { "" },
1969 if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
1970 )?;
1971 if let Some(args) = args {
1972 write!(f, "({})", display_comma_separated(args))?;
1973 }
1974 if let Some(return_type) = returns {
1975 write!(f, " {}", return_type)?;
1976 }
1977 write!(f, "{params}")?;
1978 write!(f, "{with_options}")?;
1979 Ok(())
1980 }
1981 Statement::CreateAggregate {
1982 or_replace,
1983 if_not_exists,
1984 name,
1985 args,
1986 returns,
1987 append_only,
1988 params,
1989 } => {
1990 write!(
1991 f,
1992 "CREATE {or_replace}AGGREGATE {if_not_exists}{name}",
1993 or_replace = if *or_replace { "OR REPLACE " } else { "" },
1994 if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
1995 )?;
1996 write!(f, "({})", display_comma_separated(args))?;
1997 write!(f, " RETURNS {}", returns)?;
1998 if *append_only {
1999 write!(f, " APPEND ONLY")?;
2000 }
2001 write!(f, "{params}")?;
2002 Ok(())
2003 }
2004 Statement::CreateView {
2005 name,
2006 or_replace,
2007 if_not_exists,
2008 columns,
2009 query,
2010 materialized,
2011 with_options,
2012 emit_mode,
2013 } => {
2014 write!(
2015 f,
2016 "CREATE {or_replace}{materialized}VIEW {if_not_exists}{name}",
2017 or_replace = if *or_replace { "OR REPLACE " } else { "" },
2018 materialized = if *materialized { "MATERIALIZED " } else { "" },
2019 if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2020 name = name
2021 )?;
2022 if !with_options.is_empty() {
2023 write!(f, " WITH ({})", display_comma_separated(with_options))?;
2024 }
2025 if !columns.is_empty() {
2026 write!(f, " ({})", display_comma_separated(columns))?;
2027 }
2028 write!(f, " AS {}", query)?;
2029 if let Some(emit_mode) = emit_mode {
2030 write!(f, " EMIT {}", emit_mode)?;
2031 }
2032 Ok(())
2033 }
2034 Statement::CreateTable {
2035 name,
2036 columns,
2037 wildcard_idx,
2038 constraints,
2039 with_options,
2040 or_replace,
2041 if_not_exists,
2042 temporary,
2043 format_encode,
2044 source_watermarks,
2045 append_only,
2046 on_conflict,
2047 with_version_columns,
2048 query,
2049 cdc_table_info,
2050 include_column_options,
2051 webhook_info,
2052 engine,
2053 } => {
2054 write!(
2062 f,
2063 "CREATE {or_replace}{temporary}TABLE {if_not_exists}{name}",
2064 or_replace = if *or_replace { "OR REPLACE " } else { "" },
2065 if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2066 temporary = if *temporary { "TEMPORARY " } else { "" },
2067 name = name,
2068 )?;
2069 if !columns.is_empty() || !constraints.is_empty() {
2070 write!(
2071 f,
2072 " {}",
2073 fmt_create_items(columns, constraints, source_watermarks, *wildcard_idx)?
2074 )?;
2075 } else if query.is_none() {
2076 write!(f, " ()")?;
2078 }
2079 if *append_only {
2080 write!(f, " APPEND ONLY")?;
2081 }
2082
2083 if let Some(on_conflict_behavior) = on_conflict {
2084 write!(f, " ON CONFLICT {}", on_conflict_behavior)?;
2085 }
2086 if !with_version_columns.is_empty() {
2087 write!(
2088 f,
2089 " WITH VERSION COLUMN({})",
2090 display_comma_separated(with_version_columns)
2091 )?;
2092 }
2093 if !include_column_options.is_empty() {
2094 write!(f, " {}", display_separated(include_column_options, " "))?;
2095 }
2096 if !with_options.is_empty() {
2097 write!(f, " WITH ({})", display_comma_separated(with_options))?;
2098 }
2099 if let Some(format_encode) = format_encode {
2100 write!(f, " {}", format_encode)?;
2101 }
2102 if let Some(query) = query {
2103 write!(f, " AS {}", query)?;
2104 }
2105 if let Some(info) = cdc_table_info {
2106 write!(f, " FROM {}", info.source_name)?;
2107 write!(f, " TABLE '{}'", info.external_table_name)?;
2108 }
2109 if let Some(info) = webhook_info
2110 && let Some(signature_expr) = &info.signature_expr
2111 {
2112 if let Some(secret) = &info.secret_ref {
2113 write!(f, " VALIDATE SECRET {}", secret.secret_name)?;
2114 } else {
2115 write!(f, " VALIDATE")?;
2116 }
2117 write!(f, " AS {}", signature_expr)?;
2118 }
2119 match engine {
2120 Engine::Hummock => {}
2121 Engine::Iceberg => {
2122 write!(f, " ENGINE = {}", engine)?;
2123 }
2124 }
2125 Ok(())
2126 }
2127 Statement::CreateIndex {
2128 name,
2129 table_name,
2130 columns,
2131 method,
2132 include,
2133 distributed_by,
2134 unique,
2135 if_not_exists,
2136 with_properties,
2137 } => write!(
2138 f,
2139 "CREATE {unique}INDEX {if_not_exists}{name} ON {table_name}{method}({columns}){include}{distributed_by}{with_properties}",
2140 unique = if *unique { "UNIQUE " } else { "" },
2141 if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2142 name = name,
2143 table_name = table_name,
2144 method = if let Some(method) = method {
2145 format!(" USING {} ", method)
2146 } else {
2147 "".to_owned()
2148 },
2149 columns = display_comma_separated(columns),
2150 include = if include.is_empty() {
2151 "".to_owned()
2152 } else {
2153 format!(" INCLUDE({})", display_separated(include, ","))
2154 },
2155 distributed_by = if distributed_by.is_empty() {
2156 "".to_owned()
2157 } else {
2158 format!(
2159 " DISTRIBUTED BY({})",
2160 display_separated(distributed_by, ",")
2161 )
2162 },
2163 with_properties = if !with_properties.0.is_empty() {
2164 format!(" {}", with_properties)
2165 } else {
2166 "".to_owned()
2167 },
2168 ),
2169 Statement::CreateSource { stmt } => write!(f, "CREATE SOURCE {}", stmt,),
2170 Statement::CreateSink { stmt } => write!(f, "CREATE SINK {}", stmt,),
2171 Statement::CreateSubscription { stmt } => write!(f, "CREATE SUBSCRIPTION {}", stmt,),
2172 Statement::CreateConnection { stmt } => write!(f, "CREATE CONNECTION {}", stmt,),
2173 Statement::DeclareCursor { stmt } => write!(f, "DECLARE {}", stmt,),
2174 Statement::FetchCursor { stmt } => write!(f, "FETCH {}", stmt),
2175 Statement::CloseCursor { stmt } => write!(f, "CLOSE {}", stmt),
2176 Statement::CreateSecret { stmt } => write!(f, "CREATE SECRET {}", stmt),
2177 Statement::AlterDatabase { name, operation } => {
2178 write!(f, "ALTER DATABASE {} {}", name, operation)
2179 }
2180 Statement::AlterSchema { name, operation } => {
2181 write!(f, "ALTER SCHEMA {} {}", name, operation)
2182 }
2183 Statement::AlterTable { name, operation } => {
2184 write!(f, "ALTER TABLE {} {}", name, operation)
2185 }
2186 Statement::AlterIndex { name, operation } => {
2187 write!(f, "ALTER INDEX {} {}", name, operation)
2188 }
2189 Statement::AlterView {
2190 materialized,
2191 name,
2192 operation,
2193 } => {
2194 write!(
2195 f,
2196 "ALTER {}VIEW {} {}",
2197 if *materialized { "MATERIALIZED " } else { "" },
2198 name,
2199 operation
2200 )
2201 }
2202 Statement::AlterSink { name, operation } => {
2203 write!(f, "ALTER SINK {} {}", name, operation)
2204 }
2205 Statement::AlterSubscription { name, operation } => {
2206 write!(f, "ALTER SUBSCRIPTION {} {}", name, operation)
2207 }
2208 Statement::AlterSource { name, operation } => {
2209 write!(f, "ALTER SOURCE {} {}", name, operation)
2210 }
2211 Statement::AlterFunction {
2212 name,
2213 args,
2214 operation,
2215 } => {
2216 write!(f, "ALTER FUNCTION {}", name)?;
2217 if let Some(args) = args {
2218 write!(f, "({})", display_comma_separated(args))?;
2219 }
2220 write!(f, " {}", operation)
2221 }
2222 Statement::AlterConnection { name, operation } => {
2223 write!(f, "ALTER CONNECTION {} {}", name, operation)
2224 }
2225 Statement::AlterSecret {
2226 name,
2227 with_options,
2228 operation,
2229 } => {
2230 write!(f, "ALTER SECRET {}", name)?;
2231 if !with_options.is_empty() {
2232 write!(f, " WITH ({})", display_comma_separated(with_options))?;
2233 }
2234 write!(f, " {}", operation)
2235 }
2236 Statement::Discard(t) => write!(f, "DISCARD {}", t),
2237 Statement::Drop(stmt) => write!(f, "DROP {}", stmt),
2238 Statement::DropFunction {
2239 if_exists,
2240 func_desc,
2241 option,
2242 } => {
2243 write!(
2244 f,
2245 "DROP FUNCTION{} {}",
2246 if *if_exists { " IF EXISTS" } else { "" },
2247 display_comma_separated(func_desc),
2248 )?;
2249 if let Some(op) = option {
2250 write!(f, " {}", op)?;
2251 }
2252 Ok(())
2253 }
2254 Statement::DropAggregate {
2255 if_exists,
2256 func_desc,
2257 option,
2258 } => {
2259 write!(
2260 f,
2261 "DROP AGGREGATE{} {}",
2262 if *if_exists { " IF EXISTS" } else { "" },
2263 display_comma_separated(func_desc),
2264 )?;
2265 if let Some(op) = option {
2266 write!(f, " {}", op)?;
2267 }
2268 Ok(())
2269 }
2270 Statement::SetVariable {
2271 local,
2272 variable,
2273 value,
2274 } => {
2275 f.write_str("SET ")?;
2276 if *local {
2277 f.write_str("LOCAL ")?;
2278 }
2279 write!(f, "{name} = {value}", name = variable,)
2280 }
2281 Statement::ShowVariable { variable } => {
2282 write!(f, "SHOW")?;
2283 if !variable.is_empty() {
2284 write!(f, " {}", display_separated(variable, " "))?;
2285 }
2286 Ok(())
2287 }
2288 Statement::StartTransaction { modes } => {
2289 write!(f, "START TRANSACTION")?;
2290 if !modes.is_empty() {
2291 write!(f, " {}", display_comma_separated(modes))?;
2292 }
2293 Ok(())
2294 }
2295 Statement::Abort => {
2296 write!(f, "ABORT")?;
2297 Ok(())
2298 }
2299 Statement::SetTransaction {
2300 modes,
2301 snapshot,
2302 session,
2303 } => {
2304 if *session {
2305 write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
2306 } else {
2307 write!(f, "SET TRANSACTION")?;
2308 }
2309 if !modes.is_empty() {
2310 write!(f, " {}", display_comma_separated(modes))?;
2311 }
2312 if let Some(snapshot_id) = snapshot {
2313 write!(f, " SNAPSHOT {}", snapshot_id)?;
2314 }
2315 Ok(())
2316 }
2317 Statement::SetTimeZone { local, value } => {
2318 write!(f, "SET")?;
2319 if *local {
2320 write!(f, " LOCAL")?;
2321 }
2322 write!(f, " TIME ZONE {}", value)?;
2323 Ok(())
2324 }
2325 Statement::Commit { chain } => {
2326 write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" },)
2327 }
2328 Statement::Rollback { chain } => {
2329 write!(f, "ROLLBACK{}", if *chain { " AND CHAIN" } else { "" },)
2330 }
2331 Statement::CreateSchema {
2332 schema_name,
2333 if_not_exists,
2334 owner,
2335 } => {
2336 write!(
2337 f,
2338 "CREATE SCHEMA {if_not_exists}{name}",
2339 if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
2340 name = schema_name
2341 )?;
2342 if let Some(user) = owner {
2343 write!(f, " AUTHORIZATION {}", user)?;
2344 }
2345 Ok(())
2346 }
2347 Statement::Grant {
2348 privileges,
2349 objects,
2350 grantees,
2351 with_grant_option,
2352 granted_by,
2353 } => {
2354 write!(f, "GRANT {} ", privileges)?;
2355 write!(f, "ON {} ", objects)?;
2356 write!(f, "TO {}", display_comma_separated(grantees))?;
2357 if *with_grant_option {
2358 write!(f, " WITH GRANT OPTION")?;
2359 }
2360 if let Some(grantor) = granted_by {
2361 write!(f, " GRANTED BY {}", grantor)?;
2362 }
2363 Ok(())
2364 }
2365 Statement::Revoke {
2366 privileges,
2367 objects,
2368 grantees,
2369 granted_by,
2370 revoke_grant_option,
2371 cascade,
2372 } => {
2373 write!(
2374 f,
2375 "REVOKE {}{} ",
2376 if *revoke_grant_option {
2377 "GRANT OPTION FOR "
2378 } else {
2379 ""
2380 },
2381 privileges
2382 )?;
2383 write!(f, "ON {} ", objects)?;
2384 write!(f, "FROM {}", display_comma_separated(grantees))?;
2385 if let Some(grantor) = granted_by {
2386 write!(f, " GRANTED BY {}", grantor)?;
2387 }
2388 write!(f, " {}", if *cascade { "CASCADE" } else { "RESTRICT" })?;
2389 Ok(())
2390 }
2391 Statement::Deallocate { name, prepare } => {
2392 if let Some(name) = name {
2393 write!(
2394 f,
2395 "DEALLOCATE {prepare}{name}",
2396 prepare = if *prepare { "PREPARE " } else { "" },
2397 name = name,
2398 )
2399 } else {
2400 write!(
2401 f,
2402 "DEALLOCATE {prepare}ALL",
2403 prepare = if *prepare { "PREPARE " } else { "" },
2404 )
2405 }
2406 }
2407 Statement::Execute { name, parameters } => {
2408 write!(f, "EXECUTE {}", name)?;
2409 if !parameters.is_empty() {
2410 write!(f, "({})", display_comma_separated(parameters))?;
2411 }
2412 Ok(())
2413 }
2414 Statement::Prepare {
2415 name,
2416 data_types,
2417 statement,
2418 } => {
2419 write!(f, "PREPARE {} ", name)?;
2420 if !data_types.is_empty() {
2421 write!(f, "({}) ", display_comma_separated(data_types))?;
2422 }
2423 write!(f, "AS ")?;
2424 statement.fmt_unchecked(f)
2425 }
2426 Statement::Comment {
2427 object_type,
2428 object_name,
2429 comment,
2430 } => {
2431 write!(f, "COMMENT ON {} {} IS ", object_type, object_name)?;
2432 if let Some(c) = comment {
2433 write!(f, "'{}'", c)
2434 } else {
2435 write!(f, "NULL")
2436 }
2437 }
2438 Statement::CreateUser(statement) => {
2439 write!(f, "CREATE USER {}", statement)
2440 }
2441 Statement::AlterUser(statement) => {
2442 write!(f, "ALTER USER {}", statement)
2443 }
2444 Statement::AlterSystem { param, value } => {
2445 f.write_str("ALTER SYSTEM SET ")?;
2446 write!(f, "{param} = {value}",)
2447 }
2448 Statement::Flush => {
2449 write!(f, "FLUSH")
2450 }
2451 Statement::Wait => {
2452 write!(f, "WAIT")
2453 }
2454 Statement::Begin { modes } => {
2455 write!(f, "BEGIN")?;
2456 if !modes.is_empty() {
2457 write!(f, " {}", display_comma_separated(modes))?;
2458 }
2459 Ok(())
2460 }
2461 Statement::CancelJobs(jobs) => {
2462 write!(f, "CANCEL JOBS {}", display_comma_separated(&jobs.0))?;
2463 Ok(())
2464 }
2465 Statement::Kill(worker_process_id) => {
2466 write!(f, "KILL '{}'", worker_process_id)?;
2467 Ok(())
2468 }
2469 Statement::Recover => {
2470 write!(f, "RECOVER")?;
2471 Ok(())
2472 }
2473 Statement::Use { db_name } => {
2474 write!(f, "USE {}", db_name)?;
2475 Ok(())
2476 }
2477 Statement::Vacuum { object_name, full } => {
2478 if *full {
2479 write!(f, "VACUUM FULL {}", object_name)?;
2480 } else {
2481 write!(f, "VACUUM {}", object_name)?;
2482 }
2483 Ok(())
2484 }
2485 Statement::AlterFragment {
2486 fragment_ids,
2487 operation,
2488 } => {
2489 write!(
2490 f,
2491 "ALTER FRAGMENT {} {}",
2492 display_comma_separated(fragment_ids),
2493 operation
2494 )
2495 }
2496 Statement::AlterDefaultPrivileges {
2497 target_users,
2498 schema_names,
2499 operation,
2500 } => {
2501 write!(f, "ALTER DEFAULT PRIVILEGES")?;
2502 if let Some(target_users) = target_users {
2503 write!(f, " FOR {}", display_comma_separated(target_users))?;
2504 }
2505 if let Some(schema_names) = schema_names {
2506 write!(f, " IN SCHEMA {}", display_comma_separated(schema_names))?;
2507 }
2508 write!(f, " {}", operation)
2509 }
2510 }
2511 }
2512
2513 pub fn is_create(&self) -> bool {
2514 matches!(
2515 self,
2516 Statement::CreateTable { .. }
2517 | Statement::CreateView { .. }
2518 | Statement::CreateSource { .. }
2519 | Statement::CreateSink { .. }
2520 | Statement::CreateSubscription { .. }
2521 | Statement::CreateConnection { .. }
2522 | Statement::CreateSecret { .. }
2523 | Statement::CreateUser { .. }
2524 | Statement::CreateDatabase { .. }
2525 | Statement::CreateFunction { .. }
2526 | Statement::CreateAggregate { .. }
2527 | Statement::CreateIndex { .. }
2528 | Statement::CreateSchema { .. }
2529 )
2530 }
2531}
2532
2533impl Display for IncludeOptionItem {
2534 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2535 let Self {
2536 column_type,
2537 inner_field,
2538 header_inner_expect_type,
2539 column_alias,
2540 } = self;
2541 write!(f, "INCLUDE {}", column_type)?;
2542 if let Some(inner_field) = inner_field {
2543 write!(f, " '{}'", value::escape_single_quote_string(inner_field))?;
2544 if let Some(expected_type) = header_inner_expect_type {
2545 write!(f, " {}", expected_type)?;
2546 }
2547 }
2548 if let Some(alias) = column_alias {
2549 write!(f, " AS {}", alias)?;
2550 }
2551 Ok(())
2552 }
2553}
2554
2555#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2556#[non_exhaustive]
2557pub enum OnInsert {
2558 DuplicateKeyUpdate(Vec<Assignment>),
2560}
2561
2562impl fmt::Display for OnInsert {
2563 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2564 match self {
2565 Self::DuplicateKeyUpdate(expr) => write!(
2566 f,
2567 " ON DUPLICATE KEY UPDATE {}",
2568 display_comma_separated(expr)
2569 ),
2570 }
2571 }
2572}
2573
2574#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2576pub enum Privileges {
2577 All {
2579 with_privileges_keyword: bool,
2581 },
2582 Actions(Vec<Action>),
2584}
2585
2586impl fmt::Display for Privileges {
2587 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2588 match self {
2589 Privileges::All {
2590 with_privileges_keyword,
2591 } => {
2592 write!(
2593 f,
2594 "ALL{}",
2595 if *with_privileges_keyword {
2596 " PRIVILEGES"
2597 } else {
2598 ""
2599 }
2600 )
2601 }
2602 Privileges::Actions(actions) => {
2603 write!(f, "{}", display_comma_separated(actions))
2604 }
2605 }
2606 }
2607}
2608
2609#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2611pub enum Action {
2612 Connect,
2613 Create,
2614 Delete,
2615 Execute,
2616 Insert { columns: Option<Vec<Ident>> },
2617 References { columns: Option<Vec<Ident>> },
2618 Select { columns: Option<Vec<Ident>> },
2619 Temporary,
2620 Trigger,
2621 Truncate,
2622 Update { columns: Option<Vec<Ident>> },
2623 Usage,
2624}
2625
2626impl fmt::Display for Action {
2627 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2628 match self {
2629 Action::Connect => f.write_str("CONNECT")?,
2630 Action::Create => f.write_str("CREATE")?,
2631 Action::Delete => f.write_str("DELETE")?,
2632 Action::Execute => f.write_str("EXECUTE")?,
2633 Action::Insert { .. } => f.write_str("INSERT")?,
2634 Action::References { .. } => f.write_str("REFERENCES")?,
2635 Action::Select { .. } => f.write_str("SELECT")?,
2636 Action::Temporary => f.write_str("TEMPORARY")?,
2637 Action::Trigger => f.write_str("TRIGGER")?,
2638 Action::Truncate => f.write_str("TRUNCATE")?,
2639 Action::Update { .. } => f.write_str("UPDATE")?,
2640 Action::Usage => f.write_str("USAGE")?,
2641 };
2642 match self {
2643 Action::Insert { columns }
2644 | Action::References { columns }
2645 | Action::Select { columns }
2646 | Action::Update { columns } => {
2647 if let Some(columns) = columns {
2648 write!(f, " ({})", display_comma_separated(columns))?;
2649 }
2650 }
2651 _ => (),
2652 };
2653 Ok(())
2654 }
2655}
2656
2657#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2659pub enum GrantObjects {
2660 AllSequencesInSchema { schemas: Vec<ObjectName> },
2662 AllTablesInSchema { schemas: Vec<ObjectName> },
2664 AllSourcesInSchema { schemas: Vec<ObjectName> },
2666 AllSinksInSchema { schemas: Vec<ObjectName> },
2668 AllMviewsInSchema { schemas: Vec<ObjectName> },
2670 AllViewsInSchema { schemas: Vec<ObjectName> },
2672 AllFunctionsInSchema { schemas: Vec<ObjectName> },
2674 AllSecretsInSchema { schemas: Vec<ObjectName> },
2676 AllSubscriptionsInSchema { schemas: Vec<ObjectName> },
2678 AllConnectionsInSchema { schemas: Vec<ObjectName> },
2680 Databases(Vec<ObjectName>),
2682 Schemas(Vec<ObjectName>),
2684 Sources(Vec<ObjectName>),
2686 Mviews(Vec<ObjectName>),
2688 Sequences(Vec<ObjectName>),
2690 Tables(Vec<ObjectName>),
2692 Sinks(Vec<ObjectName>),
2694 Views(Vec<ObjectName>),
2696 Connections(Vec<ObjectName>),
2698 Subscriptions(Vec<ObjectName>),
2700 Functions(Vec<FunctionDesc>),
2702 Secrets(Vec<ObjectName>),
2704}
2705
2706impl fmt::Display for GrantObjects {
2707 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2708 match self {
2709 GrantObjects::Sequences(sequences) => {
2710 write!(f, "SEQUENCE {}", display_comma_separated(sequences))
2711 }
2712 GrantObjects::Schemas(schemas) => {
2713 write!(f, "SCHEMA {}", display_comma_separated(schemas))
2714 }
2715 GrantObjects::Tables(tables) => {
2716 write!(f, "{}", display_comma_separated(tables))
2717 }
2718 GrantObjects::AllSequencesInSchema { schemas } => {
2719 write!(
2720 f,
2721 "ALL SEQUENCES IN SCHEMA {}",
2722 display_comma_separated(schemas)
2723 )
2724 }
2725 GrantObjects::AllTablesInSchema { schemas } => {
2726 write!(
2727 f,
2728 "ALL TABLES IN SCHEMA {}",
2729 display_comma_separated(schemas)
2730 )
2731 }
2732 GrantObjects::AllSourcesInSchema { schemas } => {
2733 write!(
2734 f,
2735 "ALL SOURCES IN SCHEMA {}",
2736 display_comma_separated(schemas)
2737 )
2738 }
2739 GrantObjects::AllMviewsInSchema { schemas } => {
2740 write!(
2741 f,
2742 "ALL MATERIALIZED VIEWS IN SCHEMA {}",
2743 display_comma_separated(schemas)
2744 )
2745 }
2746 GrantObjects::AllSinksInSchema { schemas } => {
2747 write!(
2748 f,
2749 "ALL SINKS IN SCHEMA {}",
2750 display_comma_separated(schemas)
2751 )
2752 }
2753 GrantObjects::AllViewsInSchema { schemas } => {
2754 write!(
2755 f,
2756 "ALL VIEWS IN SCHEMA {}",
2757 display_comma_separated(schemas)
2758 )
2759 }
2760 GrantObjects::AllFunctionsInSchema { schemas } => {
2761 write!(
2762 f,
2763 "ALL FUNCTIONS IN SCHEMA {}",
2764 display_comma_separated(schemas)
2765 )
2766 }
2767 GrantObjects::AllSecretsInSchema { schemas } => {
2768 write!(
2769 f,
2770 "ALL SECRETS IN SCHEMA {}",
2771 display_comma_separated(schemas)
2772 )
2773 }
2774 GrantObjects::AllSubscriptionsInSchema { schemas } => {
2775 write!(
2776 f,
2777 "ALL SUBSCRIPTIONS IN SCHEMA {}",
2778 display_comma_separated(schemas)
2779 )
2780 }
2781 GrantObjects::AllConnectionsInSchema { schemas } => {
2782 write!(
2783 f,
2784 "ALL CONNECTIONS IN SCHEMA {}",
2785 display_comma_separated(schemas)
2786 )
2787 }
2788 GrantObjects::Databases(databases) => {
2789 write!(f, "DATABASE {}", display_comma_separated(databases))
2790 }
2791 GrantObjects::Sources(sources) => {
2792 write!(f, "SOURCE {}", display_comma_separated(sources))
2793 }
2794 GrantObjects::Mviews(mviews) => {
2795 write!(f, "MATERIALIZED VIEW {}", display_comma_separated(mviews))
2796 }
2797 GrantObjects::Sinks(sinks) => {
2798 write!(f, "SINK {}", display_comma_separated(sinks))
2799 }
2800 GrantObjects::Views(views) => {
2801 write!(f, "VIEW {}", display_comma_separated(views))
2802 }
2803 GrantObjects::Connections(connections) => {
2804 write!(f, "CONNECTION {}", display_comma_separated(connections))
2805 }
2806 GrantObjects::Subscriptions(subscriptions) => {
2807 write!(f, "SUBSCRIPTION {}", display_comma_separated(subscriptions))
2808 }
2809 GrantObjects::Functions(func_descs) => {
2810 write!(f, "FUNCTION {}", display_comma_separated(func_descs))
2811 }
2812 GrantObjects::Secrets(secrets) => {
2813 write!(f, "SECRET {}", display_comma_separated(secrets))
2814 }
2815 }
2816 }
2817}
2818
2819#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2820pub enum PrivilegeObjectType {
2821 Tables,
2822 Sources,
2823 Sinks,
2824 Mviews,
2825 Views,
2826 Functions,
2827 Connections,
2828 Secrets,
2829 Subscriptions,
2830 Schemas,
2831}
2832
2833impl fmt::Display for PrivilegeObjectType {
2834 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2835 match self {
2836 PrivilegeObjectType::Tables => f.write_str("TABLES")?,
2837 PrivilegeObjectType::Sources => f.write_str("SOURCES")?,
2838 PrivilegeObjectType::Sinks => f.write_str("SINKS")?,
2839 PrivilegeObjectType::Mviews => f.write_str("MATERIALIZED VIEWS")?,
2840 PrivilegeObjectType::Views => f.write_str("VIEWS")?,
2841 PrivilegeObjectType::Functions => f.write_str("FUNCTIONS")?,
2842 PrivilegeObjectType::Connections => f.write_str("CONNECTIONS")?,
2843 PrivilegeObjectType::Secrets => f.write_str("SECRETS")?,
2844 PrivilegeObjectType::Subscriptions => f.write_str("SUBSCRIPTIONS")?,
2845 PrivilegeObjectType::Schemas => f.write_str("SCHEMAS")?,
2846 };
2847 Ok(())
2848 }
2849}
2850
2851#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2852pub enum DefaultPrivilegeOperation {
2853 Grant {
2854 privileges: Privileges,
2855 object_type: PrivilegeObjectType,
2856 grantees: Vec<Ident>,
2857 with_grant_option: bool,
2858 },
2859 Revoke {
2860 privileges: Privileges,
2861 object_type: PrivilegeObjectType,
2862 grantees: Vec<Ident>,
2863 revoke_grant_option: bool,
2864 cascade: bool,
2865 },
2866}
2867
2868impl fmt::Display for DefaultPrivilegeOperation {
2869 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2870 match self {
2871 DefaultPrivilegeOperation::Grant {
2872 privileges,
2873 object_type,
2874 grantees,
2875 with_grant_option,
2876 } => {
2877 write!(
2878 f,
2879 "GRANT {} ON {} TO {}",
2880 privileges,
2881 object_type,
2882 display_comma_separated(grantees)
2883 )?;
2884 if *with_grant_option {
2885 write!(f, " WITH GRANT OPTION")?;
2886 }
2887 }
2888 DefaultPrivilegeOperation::Revoke {
2889 privileges,
2890 object_type,
2891 grantees,
2892 revoke_grant_option,
2893 cascade,
2894 } => {
2895 write!(f, "REVOKE")?;
2896 if *revoke_grant_option {
2897 write!(f, " GRANT OPTION FOR")?;
2898 }
2899 write!(
2900 f,
2901 " {} ON {} FROM {}",
2902 privileges,
2903 object_type,
2904 display_comma_separated(grantees)
2905 )?;
2906 write!(f, " {}", if *cascade { "CASCADE" } else { "RESTRICT" })?;
2907 }
2908 }
2909 Ok(())
2910 }
2911}
2912
2913impl DefaultPrivilegeOperation {
2914 pub fn for_schemas(&self) -> bool {
2915 match &self {
2916 DefaultPrivilegeOperation::Grant { object_type, .. } => {
2917 object_type == &PrivilegeObjectType::Schemas
2918 }
2919 DefaultPrivilegeOperation::Revoke { object_type, .. } => {
2920 object_type == &PrivilegeObjectType::Schemas
2921 }
2922 }
2923 }
2924}
2925
2926#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2927pub enum AssignmentValue {
2928 Expr(Expr),
2930 Default,
2932}
2933
2934impl fmt::Display for AssignmentValue {
2935 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2936 match self {
2937 AssignmentValue::Expr(expr) => write!(f, "{}", expr),
2938 AssignmentValue::Default => f.write_str("DEFAULT"),
2939 }
2940 }
2941}
2942
2943#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2945pub struct Assignment {
2946 pub id: Vec<Ident>,
2947 pub value: AssignmentValue,
2948}
2949
2950impl fmt::Display for Assignment {
2951 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2952 write!(f, "{} = {}", display_separated(&self.id, "."), self.value)
2953 }
2954}
2955
2956#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2957pub enum FunctionArgExpr {
2958 Expr(Expr),
2959 ExprQualifiedWildcard(Expr, Vec<Ident>),
2963 QualifiedWildcard(ObjectName, Option<Vec<Expr>>),
2966 Wildcard(Option<Vec<Expr>>),
2968}
2969
2970impl fmt::Display for FunctionArgExpr {
2971 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2972 match self {
2973 FunctionArgExpr::Expr(expr) => write!(f, "{}", expr),
2974 FunctionArgExpr::ExprQualifiedWildcard(expr, prefix) => {
2975 write!(
2976 f,
2977 "({}){}.*",
2978 expr,
2979 prefix
2980 .iter()
2981 .format_with("", |i, f| f(&format_args!(".{i}")))
2982 )
2983 }
2984 FunctionArgExpr::QualifiedWildcard(prefix, except) => match except {
2985 Some(exprs) => write!(
2986 f,
2987 "{}.* EXCEPT ({})",
2988 prefix,
2989 exprs
2990 .iter()
2991 .map(|v| v.to_string())
2992 .collect::<Vec<String>>()
2993 .as_slice()
2994 .join(", ")
2995 ),
2996 None => write!(f, "{}.*", prefix),
2997 },
2998
2999 FunctionArgExpr::Wildcard(except) => match except {
3000 Some(exprs) => write!(
3001 f,
3002 "* EXCEPT ({})",
3003 exprs
3004 .iter()
3005 .map(|v| v.to_string())
3006 .collect::<Vec<String>>()
3007 .as_slice()
3008 .join(", ")
3009 ),
3010 None => f.write_str("*"),
3011 },
3012 }
3013 }
3014}
3015
3016#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3017pub enum FunctionArg {
3018 Named { name: Ident, arg: FunctionArgExpr },
3019 Unnamed(FunctionArgExpr),
3020}
3021
3022impl FunctionArg {
3023 pub fn get_expr(&self) -> FunctionArgExpr {
3024 match self {
3025 FunctionArg::Named { name: _, arg } => arg.clone(),
3026 FunctionArg::Unnamed(arg) => arg.clone(),
3027 }
3028 }
3029}
3030
3031impl fmt::Display for FunctionArg {
3032 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3033 match self {
3034 FunctionArg::Named { name, arg } => write!(f, "{} => {}", name, arg),
3035 FunctionArg::Unnamed(unnamed_arg) => write!(f, "{}", unnamed_arg),
3036 }
3037 }
3038}
3039
3040#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3043pub struct FunctionArgList {
3044 pub distinct: bool,
3046 pub args: Vec<FunctionArg>,
3047 pub variadic: bool,
3049 pub order_by: Vec<OrderByExpr>,
3051 pub ignore_nulls: bool,
3053}
3054
3055impl fmt::Display for FunctionArgList {
3056 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3057 write!(f, "(")?;
3058 if self.distinct {
3059 write!(f, "DISTINCT ")?;
3060 }
3061 if self.variadic {
3062 for arg in &self.args[0..self.args.len() - 1] {
3063 write!(f, "{}, ", arg)?;
3064 }
3065 write!(f, "VARIADIC {}", self.args.last().unwrap())?;
3066 } else {
3067 write!(f, "{}", display_comma_separated(&self.args))?;
3068 }
3069 if !self.order_by.is_empty() {
3070 write!(f, " ORDER BY {}", display_comma_separated(&self.order_by))?;
3071 }
3072 if self.ignore_nulls {
3073 write!(f, " IGNORE NULLS")?;
3074 }
3075 write!(f, ")")?;
3076 Ok(())
3077 }
3078}
3079
3080impl FunctionArgList {
3081 pub fn empty() -> Self {
3082 Self {
3083 distinct: false,
3084 args: vec![],
3085 variadic: false,
3086 order_by: vec![],
3087 ignore_nulls: false,
3088 }
3089 }
3090
3091 pub fn args_only(args: Vec<FunctionArg>) -> Self {
3092 Self {
3093 distinct: false,
3094 args,
3095 variadic: false,
3096 order_by: vec![],
3097 ignore_nulls: false,
3098 }
3099 }
3100
3101 pub fn is_args_only(&self) -> bool {
3102 !self.distinct && !self.variadic && self.order_by.is_empty() && !self.ignore_nulls
3103 }
3104
3105 pub fn for_agg(distinct: bool, args: Vec<FunctionArg>, order_by: Vec<OrderByExpr>) -> Self {
3106 Self {
3107 distinct,
3108 args,
3109 variadic: false,
3110 order_by,
3111 ignore_nulls: false,
3112 }
3113 }
3114}
3115
3116#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3118pub struct Function {
3119 pub scalar_as_agg: bool,
3121 pub name: ObjectName,
3123 pub arg_list: FunctionArgList,
3125 pub within_group: Option<Box<OrderByExpr>>,
3128 pub filter: Option<Box<Expr>>,
3130 pub over: Option<Window>,
3132}
3133
3134impl Function {
3135 pub fn no_arg(name: ObjectName) -> Self {
3136 Self {
3137 scalar_as_agg: false,
3138 name,
3139 arg_list: FunctionArgList::empty(),
3140 within_group: None,
3141 filter: None,
3142 over: None,
3143 }
3144 }
3145}
3146
3147impl fmt::Display for Function {
3148 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3149 if self.scalar_as_agg {
3150 write!(f, "AGGREGATE:")?;
3151 }
3152 write!(f, "{}{}", self.name, self.arg_list)?;
3153 if let Some(within_group) = &self.within_group {
3154 write!(f, " WITHIN GROUP (ORDER BY {})", within_group)?;
3155 }
3156 if let Some(filter) = &self.filter {
3157 write!(f, " FILTER (WHERE {})", filter)?;
3158 }
3159 if let Some(o) = &self.over {
3160 write!(f, " OVER {}", o)?;
3161 }
3162 Ok(())
3163 }
3164}
3165
3166#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3167pub enum ObjectType {
3168 Table,
3169 View,
3170 MaterializedView,
3171 Index,
3172 Schema,
3173 Source,
3174 Sink,
3175 Database,
3176 User,
3177 Connection,
3178 Secret,
3179 Subscription,
3180}
3181
3182impl fmt::Display for ObjectType {
3183 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3184 f.write_str(match self {
3185 ObjectType::Table => "TABLE",
3186 ObjectType::View => "VIEW",
3187 ObjectType::MaterializedView => "MATERIALIZED VIEW",
3188 ObjectType::Index => "INDEX",
3189 ObjectType::Schema => "SCHEMA",
3190 ObjectType::Source => "SOURCE",
3191 ObjectType::Sink => "SINK",
3192 ObjectType::Database => "DATABASE",
3193 ObjectType::User => "USER",
3194 ObjectType::Secret => "SECRET",
3195 ObjectType::Connection => "CONNECTION",
3196 ObjectType::Subscription => "SUBSCRIPTION",
3197 })
3198 }
3199}
3200
3201impl ParseTo for ObjectType {
3202 fn parse_to(parser: &mut Parser<'_>) -> ModalResult<Self> {
3203 let object_type = if parser.parse_keyword(Keyword::TABLE) {
3204 ObjectType::Table
3205 } else if parser.parse_keyword(Keyword::VIEW) {
3206 ObjectType::View
3207 } else if parser.parse_keywords(&[Keyword::MATERIALIZED, Keyword::VIEW]) {
3208 ObjectType::MaterializedView
3209 } else if parser.parse_keyword(Keyword::SOURCE) {
3210 ObjectType::Source
3211 } else if parser.parse_keyword(Keyword::SINK) {
3212 ObjectType::Sink
3213 } else if parser.parse_keyword(Keyword::INDEX) {
3214 ObjectType::Index
3215 } else if parser.parse_keyword(Keyword::SCHEMA) {
3216 ObjectType::Schema
3217 } else if parser.parse_keyword(Keyword::DATABASE) {
3218 ObjectType::Database
3219 } else if parser.parse_keyword(Keyword::USER) {
3220 ObjectType::User
3221 } else if parser.parse_keyword(Keyword::CONNECTION) {
3222 ObjectType::Connection
3223 } else if parser.parse_keyword(Keyword::SECRET) {
3224 ObjectType::Secret
3225 } else if parser.parse_keyword(Keyword::SUBSCRIPTION) {
3226 ObjectType::Subscription
3227 } else {
3228 return parser.expected(
3229 "TABLE, VIEW, INDEX, MATERIALIZED VIEW, SOURCE, SINK, SUBSCRIPTION, SCHEMA, DATABASE, USER, SECRET or CONNECTION after DROP",
3230 );
3231 };
3232 Ok(object_type)
3233 }
3234}
3235
3236#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3237pub struct SqlOption {
3238 pub name: ObjectName,
3239 pub value: SqlOptionValue,
3240}
3241
3242impl fmt::Display for SqlOption {
3243 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3244 let should_redact = REDACT_SQL_OPTION_KEYWORDS
3245 .try_with(|keywords| {
3246 let sql_option_name = self.name.real_value().to_lowercase();
3247 keywords.iter().any(|k| sql_option_name.contains(k))
3248 })
3249 .unwrap_or(false);
3250 if should_redact {
3251 write!(f, "{} = [REDACTED]", self.name)
3252 } else {
3253 write!(f, "{} = {}", self.name, self.value)
3254 }
3255 }
3256}
3257
3258impl TryFrom<(&String, &String)> for SqlOption {
3259 type Error = ParserError;
3260
3261 fn try_from((name, value): (&String, &String)) -> Result<Self, Self::Error> {
3262 let name_parts: Vec<&str> = name.split('.').collect();
3266 let object_name = ObjectName(name_parts.into_iter().map(Ident::from_real_value).collect());
3267
3268 let query = format!("{} = {}", object_name, value);
3269 let mut tokenizer = Tokenizer::new(query.as_str());
3270 let tokens = tokenizer.tokenize_with_location()?;
3271 let mut parser = Parser(&tokens);
3272 parser
3273 .parse_sql_option()
3274 .map_err(|e| ParserError::ParserError(e.to_string()))
3275 }
3276}
3277
3278#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3279pub enum SqlOptionValue {
3280 Value(Value),
3281 SecretRef(SecretRefValue),
3282 ConnectionRef(ConnectionRefValue),
3283 BackfillOrder(BackfillOrderStrategy),
3284}
3285
3286impl SqlOptionValue {
3287 pub const fn null() -> Self {
3289 Self::Value(Value::Null)
3290 }
3291}
3292
3293impl fmt::Display for SqlOptionValue {
3294 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3295 match self {
3296 SqlOptionValue::Value(value) => write!(f, "{}", value),
3297 SqlOptionValue::SecretRef(secret_ref) => write!(f, "secret {}", secret_ref),
3298 SqlOptionValue::ConnectionRef(connection_ref) => {
3299 write!(f, "{}", connection_ref)
3300 }
3301 SqlOptionValue::BackfillOrder(order) => {
3302 write!(f, "{}", order)
3303 }
3304 }
3305 }
3306}
3307
3308impl From<Value> for SqlOptionValue {
3309 fn from(value: Value) -> Self {
3310 SqlOptionValue::Value(value)
3311 }
3312}
3313
3314#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3315pub enum EmitMode {
3316 Immediately,
3317 OnWindowClose,
3318}
3319
3320impl fmt::Display for EmitMode {
3321 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3322 f.write_str(match self {
3323 EmitMode::Immediately => "IMMEDIATELY",
3324 EmitMode::OnWindowClose => "ON WINDOW CLOSE",
3325 })
3326 }
3327}
3328
3329#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
3330pub enum OnConflict {
3331 UpdateFull,
3332 Nothing,
3333 UpdateIfNotNull,
3334}
3335
3336impl fmt::Display for OnConflict {
3337 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3338 f.write_str(match self {
3339 OnConflict::UpdateFull => "DO UPDATE FULL",
3340 OnConflict::Nothing => "DO NOTHING",
3341 OnConflict::UpdateIfNotNull => "DO UPDATE IF NOT NULL",
3342 })
3343 }
3344}
3345
3346#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3347pub enum Engine {
3348 Hummock,
3349 Iceberg,
3350}
3351
3352impl fmt::Display for crate::ast::Engine {
3353 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3354 f.write_str(match self {
3355 crate::ast::Engine::Hummock => "HUMMOCK",
3356 crate::ast::Engine::Iceberg => "ICEBERG",
3357 })
3358 }
3359}
3360
3361#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3362pub enum SetTimeZoneValue {
3363 Ident(Ident),
3364 Literal(Value),
3365 Local,
3366 Default,
3367}
3368
3369impl fmt::Display for SetTimeZoneValue {
3370 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3371 match self {
3372 SetTimeZoneValue::Ident(ident) => write!(f, "{}", ident),
3373 SetTimeZoneValue::Literal(value) => write!(f, "{}", value),
3374 SetTimeZoneValue::Local => f.write_str("LOCAL"),
3375 SetTimeZoneValue::Default => f.write_str("DEFAULT"),
3376 }
3377 }
3378}
3379
3380#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3381pub enum TransactionMode {
3382 AccessMode(TransactionAccessMode),
3383 IsolationLevel(TransactionIsolationLevel),
3384}
3385
3386impl fmt::Display for TransactionMode {
3387 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3388 use TransactionMode::*;
3389 match self {
3390 AccessMode(access_mode) => write!(f, "{}", access_mode),
3391 IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {}", iso_level),
3392 }
3393 }
3394}
3395
3396#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3397pub enum TransactionAccessMode {
3398 ReadOnly,
3399 ReadWrite,
3400}
3401
3402impl fmt::Display for TransactionAccessMode {
3403 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3404 use TransactionAccessMode::*;
3405 f.write_str(match self {
3406 ReadOnly => "READ ONLY",
3407 ReadWrite => "READ WRITE",
3408 })
3409 }
3410}
3411
3412#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3413pub enum TransactionIsolationLevel {
3414 ReadUncommitted,
3415 ReadCommitted,
3416 RepeatableRead,
3417 Serializable,
3418}
3419
3420impl fmt::Display for TransactionIsolationLevel {
3421 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3422 use TransactionIsolationLevel::*;
3423 f.write_str(match self {
3424 ReadUncommitted => "READ UNCOMMITTED",
3425 ReadCommitted => "READ COMMITTED",
3426 RepeatableRead => "REPEATABLE READ",
3427 Serializable => "SERIALIZABLE",
3428 })
3429 }
3430}
3431
3432#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3433pub enum ShowStatementFilter {
3434 Like(String),
3435 ILike(String),
3436 Where(Expr),
3437}
3438
3439impl fmt::Display for ShowStatementFilter {
3440 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3441 use ShowStatementFilter::*;
3442 match self {
3443 Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
3444 ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
3445 Where(expr) => write!(f, "WHERE {}", expr),
3446 }
3447 }
3448}
3449
3450#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3452pub enum DropFunctionOption {
3453 Restrict,
3454 Cascade,
3455}
3456
3457impl fmt::Display for DropFunctionOption {
3458 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3459 match self {
3460 DropFunctionOption::Restrict => write!(f, "RESTRICT "),
3461 DropFunctionOption::Cascade => write!(f, "CASCADE "),
3462 }
3463 }
3464}
3465
3466#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3468pub struct FunctionDesc {
3469 pub name: ObjectName,
3470 pub args: Option<Vec<OperateFunctionArg>>,
3471}
3472
3473impl fmt::Display for FunctionDesc {
3474 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3475 write!(f, "{}", self.name)?;
3476 if let Some(args) = &self.args {
3477 write!(f, "({})", display_comma_separated(args))?;
3478 }
3479 Ok(())
3480 }
3481}
3482
3483#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3485pub struct OperateFunctionArg {
3486 pub mode: Option<ArgMode>,
3487 pub name: Option<Ident>,
3488 pub data_type: DataType,
3489 pub default_expr: Option<Expr>,
3490}
3491
3492impl OperateFunctionArg {
3493 pub fn unnamed(data_type: DataType) -> Self {
3495 Self {
3496 mode: None,
3497 name: None,
3498 data_type,
3499 default_expr: None,
3500 }
3501 }
3502
3503 pub fn with_name(name: &str, data_type: DataType) -> Self {
3505 Self {
3506 mode: None,
3507 name: Some(name.into()),
3508 data_type,
3509 default_expr: None,
3510 }
3511 }
3512}
3513
3514impl fmt::Display for OperateFunctionArg {
3515 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3516 if let Some(mode) = &self.mode {
3517 write!(f, "{} ", mode)?;
3518 }
3519 if let Some(name) = &self.name {
3520 write!(f, "{} ", name)?;
3521 }
3522 write!(f, "{}", self.data_type)?;
3523 if let Some(default_expr) = &self.default_expr {
3524 write!(f, " = {}", default_expr)?;
3525 }
3526 Ok(())
3527 }
3528}
3529
3530#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3532pub enum ArgMode {
3533 In,
3534 Out,
3535 InOut,
3536}
3537
3538impl fmt::Display for ArgMode {
3539 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3540 match self {
3541 ArgMode::In => write!(f, "IN"),
3542 ArgMode::Out => write!(f, "OUT"),
3543 ArgMode::InOut => write!(f, "INOUT"),
3544 }
3545 }
3546}
3547
3548#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3550pub enum FunctionBehavior {
3551 Immutable,
3552 Stable,
3553 Volatile,
3554}
3555
3556impl fmt::Display for FunctionBehavior {
3557 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3558 match self {
3559 FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
3560 FunctionBehavior::Stable => write!(f, "STABLE"),
3561 FunctionBehavior::Volatile => write!(f, "VOLATILE"),
3562 }
3563 }
3564}
3565
3566#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3567pub enum FunctionDefinition {
3568 Identifier(String),
3569 SingleQuotedDef(String),
3570 DoubleDollarDef(String),
3571}
3572
3573impl fmt::Display for FunctionDefinition {
3574 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3575 match self {
3576 FunctionDefinition::Identifier(s) => write!(f, "{s}")?,
3577 FunctionDefinition::SingleQuotedDef(s) => write!(f, "'{s}'")?,
3578 FunctionDefinition::DoubleDollarDef(s) => write!(f, "$${s}$$")?,
3579 }
3580 Ok(())
3581 }
3582}
3583
3584impl FunctionDefinition {
3585 pub fn as_str(&self) -> &str {
3587 match self {
3588 FunctionDefinition::Identifier(s) => s,
3589 FunctionDefinition::SingleQuotedDef(s) => s,
3590 FunctionDefinition::DoubleDollarDef(s) => s,
3591 }
3592 }
3593
3594 pub fn into_string(self) -> String {
3596 match self {
3597 FunctionDefinition::Identifier(s) => s,
3598 FunctionDefinition::SingleQuotedDef(s) => s,
3599 FunctionDefinition::DoubleDollarDef(s) => s,
3600 }
3601 }
3602}
3603
3604#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3606pub enum CreateFunctionReturns {
3607 Value(DataType),
3609 Table(Vec<TableColumnDef>),
3611}
3612
3613impl fmt::Display for CreateFunctionReturns {
3614 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3615 match self {
3616 Self::Value(data_type) => write!(f, "RETURNS {}", data_type),
3617 Self::Table(columns) => {
3618 write!(f, "RETURNS TABLE ({})", display_comma_separated(columns))
3619 }
3620 }
3621 }
3622}
3623
3624#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3626pub struct TableColumnDef {
3627 pub name: Ident,
3628 pub data_type: DataType,
3629}
3630
3631impl fmt::Display for TableColumnDef {
3632 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3633 write!(f, "{} {}", self.name, self.data_type)
3634 }
3635}
3636
3637#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
3642pub struct CreateFunctionBody {
3643 pub language: Option<Ident>,
3645 pub runtime: Option<Ident>,
3647
3648 pub behavior: Option<FunctionBehavior>,
3650 pub as_: Option<FunctionDefinition>,
3654 pub return_: Option<Expr>,
3656 pub using: Option<CreateFunctionUsing>,
3658}
3659
3660impl fmt::Display for CreateFunctionBody {
3661 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3662 if let Some(language) = &self.language {
3663 write!(f, " LANGUAGE {language}")?;
3664 }
3665 if let Some(runtime) = &self.runtime {
3666 write!(f, " RUNTIME {runtime}")?;
3667 }
3668 if let Some(behavior) = &self.behavior {
3669 write!(f, " {behavior}")?;
3670 }
3671 if let Some(definition) = &self.as_ {
3672 write!(f, " AS {definition}")?;
3673 }
3674 if let Some(expr) = &self.return_ {
3675 write!(f, " RETURN {expr}")?;
3676 }
3677 if let Some(using) = &self.using {
3678 write!(f, " {using}")?;
3679 }
3680 Ok(())
3681 }
3682}
3683
3684#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
3685pub struct CreateFunctionWithOptions {
3686 pub always_retry_on_network_error: Option<bool>,
3688 pub r#async: Option<bool>,
3690 pub batch: Option<bool>,
3692}
3693
3694impl TryFrom<Vec<SqlOption>> for CreateFunctionWithOptions {
3696 type Error = StrError;
3697
3698 fn try_from(with_options: Vec<SqlOption>) -> Result<Self, Self::Error> {
3699 let mut options = Self::default();
3700 for option in with_options {
3701 match option.name.to_string().to_lowercase().as_str() {
3702 "always_retry_on_network_error" => {
3703 options.always_retry_on_network_error = Some(matches!(
3704 option.value,
3705 SqlOptionValue::Value(Value::Boolean(true))
3706 ));
3707 }
3708 "async" => {
3709 options.r#async = Some(matches!(
3710 option.value,
3711 SqlOptionValue::Value(Value::Boolean(true))
3712 ))
3713 }
3714 "batch" => {
3715 options.batch = Some(matches!(
3716 option.value,
3717 SqlOptionValue::Value(Value::Boolean(true))
3718 ))
3719 }
3720 _ => {
3721 return Err(StrError(format!("unknown option: {}", option.name)));
3722 }
3723 }
3724 }
3725 Ok(options)
3726 }
3727}
3728
3729impl Display for CreateFunctionWithOptions {
3730 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3731 if self == &Self::default() {
3732 return Ok(());
3733 }
3734 let mut options = vec![];
3735 if let Some(v) = self.always_retry_on_network_error {
3736 options.push(format!("always_retry_on_network_error = {}", v));
3737 }
3738 if let Some(v) = self.r#async {
3739 options.push(format!("async = {}", v));
3740 }
3741 if let Some(v) = self.batch {
3742 options.push(format!("batch = {}", v));
3743 }
3744 write!(f, " WITH ( {} )", display_comma_separated(&options))
3745 }
3746}
3747
3748#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
3749pub enum CreateFunctionUsing {
3750 Link(String),
3751 Base64(String),
3752}
3753
3754impl fmt::Display for CreateFunctionUsing {
3755 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3756 write!(f, "USING ")?;
3757 match self {
3758 CreateFunctionUsing::Link(uri) => write!(f, "LINK '{uri}'"),
3759 CreateFunctionUsing::Base64(s) => {
3760 write!(f, "BASE64 '{s}'")
3761 }
3762 }
3763 }
3764}
3765
3766#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3767pub struct ConfigParam {
3768 pub param: Ident,
3769 pub value: SetVariableValue,
3770}
3771
3772impl fmt::Display for ConfigParam {
3773 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3774 write!(f, "SET {} = {}", self.param, self.value)
3775 }
3776}
3777
3778#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3779pub enum SetVariableValue {
3780 Single(SetVariableValueSingle),
3781 List(Vec<SetVariableValueSingle>),
3782 Default,
3783}
3784
3785impl From<SetVariableValueSingle> for SetVariableValue {
3786 fn from(value: SetVariableValueSingle) -> Self {
3787 SetVariableValue::Single(value)
3788 }
3789}
3790
3791impl fmt::Display for SetVariableValue {
3792 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3793 use SetVariableValue::*;
3794 match self {
3795 Single(val) => write!(f, "{}", val),
3796 List(list) => write!(f, "{}", display_comma_separated(list),),
3797 Default => write!(f, "DEFAULT"),
3798 }
3799 }
3800}
3801
3802#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3803pub enum SetVariableValueSingle {
3804 Ident(Ident),
3805 Literal(Value),
3806}
3807
3808impl SetVariableValueSingle {
3809 pub fn to_string_unquoted(&self) -> String {
3810 match self {
3811 Self::Literal(Value::SingleQuotedString(s))
3812 | Self::Literal(Value::DoubleQuotedString(s)) => s.clone(),
3813 _ => self.to_string(),
3814 }
3815 }
3816}
3817
3818impl fmt::Display for SetVariableValueSingle {
3819 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3820 use SetVariableValueSingle::*;
3821 match self {
3822 Ident(ident) => write!(f, "{}", ident),
3823 Literal(literal) => write!(f, "{}", literal),
3824 }
3825 }
3826}
3827
3828#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3829pub enum AsOf {
3830 ProcessTime,
3831 ProcessTimeWithInterval((String, DateTimeField)),
3833 TimestampNum(i64),
3835 TimestampString(String),
3836 VersionNum(i64),
3837 VersionString(String),
3838}
3839
3840impl fmt::Display for AsOf {
3841 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3842 use AsOf::*;
3843 match self {
3844 ProcessTime => write!(f, " FOR SYSTEM_TIME AS OF PROCTIME()"),
3845 ProcessTimeWithInterval((value, leading_field)) => write!(
3846 f,
3847 " FOR SYSTEM_TIME AS OF NOW() - '{}' {}",
3848 value, leading_field
3849 ),
3850 TimestampNum(ts) => write!(f, " FOR SYSTEM_TIME AS OF {}", ts),
3851 TimestampString(ts) => write!(f, " FOR SYSTEM_TIME AS OF '{}'", ts),
3852 VersionNum(v) => write!(f, " FOR SYSTEM_VERSION AS OF {}", v),
3853 VersionString(v) => write!(f, " FOR SYSTEM_VERSION AS OF '{}'", v),
3854 }
3855 }
3856}
3857
3858#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3859pub enum DiscardType {
3860 All,
3861}
3862
3863impl fmt::Display for DiscardType {
3864 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3865 use DiscardType::*;
3866 match self {
3867 All => write!(f, "ALL"),
3868 }
3869 }
3870}
3871
3872#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
3875pub enum BackfillOrderStrategy {
3876 #[default]
3877 Default,
3878 None,
3879 Auto,
3880 Fixed(Vec<(ObjectName, ObjectName)>),
3881}
3882
3883impl fmt::Display for BackfillOrderStrategy {
3884 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3885 use BackfillOrderStrategy::*;
3886 match self {
3887 Default => write!(f, "DEFAULT"),
3888 None => write!(f, "NONE"),
3889 Auto => write!(f, "AUTO"),
3890 Fixed(map) => {
3891 let mut parts = vec![];
3892 for (start, end) in map {
3893 parts.push(format!("{} -> {}", start, end));
3894 }
3895 write!(f, "FIXED({})", display_comma_separated(&parts))
3896 }
3897 }
3898 }
3899}
3900
3901impl Statement {
3902 pub fn to_redacted_string(&self, keywords: RedactSqlOptionKeywordsRef) -> String {
3903 REDACT_SQL_OPTION_KEYWORDS.sync_scope(keywords, || self.to_string_unchecked())
3904 }
3905
3906 pub fn default_create_table(name: ObjectName) -> Self {
3908 Self::CreateTable {
3909 name,
3910 or_replace: false,
3911 temporary: false,
3912 if_not_exists: false,
3913 columns: Vec::new(),
3914 wildcard_idx: None,
3915 constraints: Vec::new(),
3916 with_options: Vec::new(),
3917 format_encode: None,
3918 source_watermarks: Vec::new(),
3919 append_only: false,
3920 on_conflict: None,
3921 with_version_columns: Vec::new(),
3922 query: None,
3923 cdc_table_info: None,
3924 include_column_options: Vec::new(),
3925 webhook_info: None,
3926 engine: Engine::Hummock,
3927 }
3928 }
3929}
3930
3931#[cfg(test)]
3932mod tests {
3933 use super::*;
3934
3935 #[test]
3936 fn test_grouping_sets_display() {
3937 let grouping_sets = Expr::GroupingSets(vec![
3939 vec![Expr::Identifier(Ident::new_unchecked("a"))],
3940 vec![Expr::Identifier(Ident::new_unchecked("b"))],
3941 ]);
3942 assert_eq!("GROUPING SETS ((a), (b))", format!("{}", grouping_sets));
3943
3944 let grouping_sets = Expr::GroupingSets(vec![vec![
3946 Expr::Identifier(Ident::new_unchecked("a")),
3947 Expr::Identifier(Ident::new_unchecked("b")),
3948 ]]);
3949 assert_eq!("GROUPING SETS ((a, b))", format!("{}", grouping_sets));
3950
3951 let grouping_sets = Expr::GroupingSets(vec![
3953 vec![
3954 Expr::Identifier(Ident::new_unchecked("a")),
3955 Expr::Identifier(Ident::new_unchecked("b")),
3956 ],
3957 vec![
3958 Expr::Identifier(Ident::new_unchecked("c")),
3959 Expr::Identifier(Ident::new_unchecked("d")),
3960 ],
3961 ]);
3962 assert_eq!(
3963 "GROUPING SETS ((a, b), (c, d))",
3964 format!("{}", grouping_sets)
3965 );
3966 }
3967
3968 #[test]
3969 fn test_rollup_display() {
3970 let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new_unchecked("a"))]]);
3971 assert_eq!("ROLLUP (a)", format!("{}", rollup));
3972
3973 let rollup = Expr::Rollup(vec![vec![
3974 Expr::Identifier(Ident::new_unchecked("a")),
3975 Expr::Identifier(Ident::new_unchecked("b")),
3976 ]]);
3977 assert_eq!("ROLLUP ((a, b))", format!("{}", rollup));
3978
3979 let rollup = Expr::Rollup(vec![
3980 vec![Expr::Identifier(Ident::new_unchecked("a"))],
3981 vec![Expr::Identifier(Ident::new_unchecked("b"))],
3982 ]);
3983 assert_eq!("ROLLUP (a, b)", format!("{}", rollup));
3984
3985 let rollup = Expr::Rollup(vec![
3986 vec![Expr::Identifier(Ident::new_unchecked("a"))],
3987 vec![
3988 Expr::Identifier(Ident::new_unchecked("b")),
3989 Expr::Identifier(Ident::new_unchecked("c")),
3990 ],
3991 vec![Expr::Identifier(Ident::new_unchecked("d"))],
3992 ]);
3993 assert_eq!("ROLLUP (a, (b, c), d)", format!("{}", rollup));
3994 }
3995
3996 #[test]
3997 fn test_cube_display() {
3998 let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new_unchecked("a"))]]);
3999 assert_eq!("CUBE (a)", format!("{}", cube));
4000
4001 let cube = Expr::Cube(vec![vec![
4002 Expr::Identifier(Ident::new_unchecked("a")),
4003 Expr::Identifier(Ident::new_unchecked("b")),
4004 ]]);
4005 assert_eq!("CUBE ((a, b))", format!("{}", cube));
4006
4007 let cube = Expr::Cube(vec![
4008 vec![Expr::Identifier(Ident::new_unchecked("a"))],
4009 vec![Expr::Identifier(Ident::new_unchecked("b"))],
4010 ]);
4011 assert_eq!("CUBE (a, b)", format!("{}", cube));
4012
4013 let cube = Expr::Cube(vec![
4014 vec![Expr::Identifier(Ident::new_unchecked("a"))],
4015 vec![
4016 Expr::Identifier(Ident::new_unchecked("b")),
4017 Expr::Identifier(Ident::new_unchecked("c")),
4018 ],
4019 vec![Expr::Identifier(Ident::new_unchecked("d"))],
4020 ]);
4021 assert_eq!("CUBE (a, (b, c), d)", format!("{}", cube));
4022 }
4023
4024 #[test]
4025 fn test_array_index_display() {
4026 let array_index = Expr::Index {
4027 obj: Box::new(Expr::Identifier(Ident::new_unchecked("v1"))),
4028 index: Box::new(Expr::Value(Value::Number("1".into()))),
4029 };
4030 assert_eq!("v1[1]", format!("{}", array_index));
4031
4032 let array_index2 = Expr::Index {
4033 obj: Box::new(array_index),
4034 index: Box::new(Expr::Value(Value::Number("1".into()))),
4035 };
4036 assert_eq!("v1[1][1]", format!("{}", array_index2));
4037 }
4038
4039 #[test]
4040 fn test_nested_op_display() {
4042 let binary_op = Expr::BinaryOp {
4043 left: Box::new(Expr::Value(Value::Boolean(true))),
4044 op: BinaryOperator::Or,
4045 right: Box::new(Expr::IsNotFalse(Box::new(Expr::Value(Value::Boolean(
4046 true,
4047 ))))),
4048 };
4049 assert_eq!("true OR true IS NOT FALSE", format!("{}", binary_op));
4050
4051 let unary_op = Expr::UnaryOp {
4052 op: UnaryOperator::Not,
4053 expr: Box::new(Expr::IsNotFalse(Box::new(Expr::Value(Value::Boolean(
4054 true,
4055 ))))),
4056 };
4057 assert_eq!("NOT true IS NOT FALSE", format!("{}", unary_op));
4058 }
4059
4060 #[test]
4061 fn test_create_function_display() {
4062 let create_function = Statement::CreateFunction {
4063 or_replace: false,
4064 temporary: false,
4065 if_not_exists: false,
4066 name: ObjectName(vec![Ident::new_unchecked("foo")]),
4067 args: Some(vec![OperateFunctionArg::unnamed(DataType::Int)]),
4068 returns: Some(CreateFunctionReturns::Value(DataType::Int)),
4069 params: CreateFunctionBody {
4070 language: Some(Ident::new_unchecked("python")),
4071 runtime: None,
4072 behavior: Some(FunctionBehavior::Immutable),
4073 as_: Some(FunctionDefinition::SingleQuotedDef("SELECT 1".to_owned())),
4074 return_: None,
4075 using: None,
4076 },
4077 with_options: CreateFunctionWithOptions {
4078 always_retry_on_network_error: None,
4079 r#async: None,
4080 batch: None,
4081 },
4082 };
4083 assert_eq!(
4084 "CREATE FUNCTION foo(INT) RETURNS INT LANGUAGE python IMMUTABLE AS 'SELECT 1'",
4085 format!("{}", create_function)
4086 );
4087 let create_function = Statement::CreateFunction {
4088 or_replace: false,
4089 temporary: false,
4090 if_not_exists: false,
4091 name: ObjectName(vec![Ident::new_unchecked("foo")]),
4092 args: Some(vec![OperateFunctionArg::unnamed(DataType::Int)]),
4093 returns: Some(CreateFunctionReturns::Value(DataType::Int)),
4094 params: CreateFunctionBody {
4095 language: Some(Ident::new_unchecked("python")),
4096 runtime: None,
4097 behavior: Some(FunctionBehavior::Immutable),
4098 as_: Some(FunctionDefinition::SingleQuotedDef("SELECT 1".to_owned())),
4099 return_: None,
4100 using: None,
4101 },
4102 with_options: CreateFunctionWithOptions {
4103 always_retry_on_network_error: Some(true),
4104 r#async: None,
4105 batch: None,
4106 },
4107 };
4108 assert_eq!(
4109 "CREATE FUNCTION foo(INT) RETURNS INT LANGUAGE python IMMUTABLE AS 'SELECT 1' WITH ( always_retry_on_network_error = true )",
4110 format!("{}", create_function)
4111 );
4112 }
4113}