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