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