1use crate::expressions::*;
59use crate::generator::Generator;
60use crate::parser::Parser;
61
62fn is_safe_identifier_name(name: &str) -> bool {
63 if name.is_empty() {
64 return false;
65 }
66
67 let mut chars = name.chars();
68 let Some(first) = chars.next() else {
69 return false;
70 };
71
72 if !(first == '_' || first.is_ascii_alphabetic()) {
73 return false;
74 }
75
76 chars.all(|c| c == '_' || c.is_ascii_alphanumeric())
77}
78
79fn builder_identifier(name: &str) -> Identifier {
80 if name == "*" || is_safe_identifier_name(name) {
81 Identifier::new(name)
82 } else {
83 Identifier::quoted(name)
84 }
85}
86
87fn builder_table_ref(name: &str) -> TableRef {
88 let parts: Vec<&str> = name.split('.').collect();
89
90 match parts.len() {
91 3 => {
92 let mut t = TableRef::new(parts[2]);
93 t.name = builder_identifier(parts[2]);
94 t.schema = Some(builder_identifier(parts[1]));
95 t.catalog = Some(builder_identifier(parts[0]));
96 t
97 }
98 2 => {
99 let mut t = TableRef::new(parts[1]);
100 t.name = builder_identifier(parts[1]);
101 t.schema = Some(builder_identifier(parts[0]));
102 t
103 }
104 _ => {
105 let first = parts.first().copied().unwrap_or("");
106 let mut t = TableRef::new(first);
107 t.name = builder_identifier(first);
108 t
109 }
110 }
111}
112
113pub fn col(name: &str) -> Expr {
137 let parts: Vec<&str> = name.split('.').collect();
138 if parts.len() >= 3 && parts.iter().all(|part| !part.is_empty()) {
139 let mut expr = Expression::boxed_column(Column {
140 name: builder_identifier(parts[1]),
141 table: Some(builder_identifier(parts[0])),
142 join_mark: false,
143 trailing_comments: Vec::new(),
144 span: None,
145 inferred_type: None,
146 });
147
148 for field in &parts[2..] {
149 expr = Expression::Dot(Box::new(DotAccess {
150 this: expr,
151 field: builder_identifier(field),
152 }));
153 }
154
155 return Expr(expr);
156 }
157
158 if let Some((table, column)) = name.rsplit_once('.') {
159 Expr(Expression::boxed_column(Column {
160 name: builder_identifier(column),
161 table: Some(builder_identifier(table)),
162 join_mark: false,
163 trailing_comments: Vec::new(),
164 span: None,
165 inferred_type: None,
166 }))
167 } else {
168 Expr(Expression::boxed_column(Column {
169 name: builder_identifier(name),
170 table: None,
171 join_mark: false,
172 trailing_comments: Vec::new(),
173 span: None,
174 inferred_type: None,
175 }))
176 }
177}
178
179pub fn lit<V: IntoLiteral>(value: V) -> Expr {
195 value.into_literal()
196}
197
198pub fn star() -> Expr {
200 Expr(Expression::star())
201}
202
203pub fn null() -> Expr {
205 Expr(Expression::Null(Null))
206}
207
208pub fn boolean(value: bool) -> Expr {
210 Expr(Expression::Boolean(BooleanLiteral { value }))
211}
212
213pub fn table(name: &str) -> Expr {
230 Expr(Expression::Table(Box::new(builder_table_ref(name))))
231}
232
233pub fn func(name: &str, args: impl IntoIterator<Item = Expr>) -> Expr {
250 Expr(Expression::Function(Box::new(Function {
251 name: name.to_string(),
252 args: args.into_iter().map(|a| a.0).collect(),
253 ..Function::default()
254 })))
255}
256
257pub fn cast(expr: Expr, to: &str) -> Expr {
273 let data_type = parse_simple_data_type(to);
274 Expr(Expression::Cast(Box::new(Cast {
275 this: expr.0,
276 to: data_type,
277 trailing_comments: Vec::new(),
278 double_colon_syntax: false,
279 format: None,
280 default: None,
281 inferred_type: None,
282 })))
283}
284
285pub fn not(expr: Expr) -> Expr {
290 Expr(Expression::Not(Box::new(UnaryOp::new(expr.0))))
291}
292
293pub fn and(left: Expr, right: Expr) -> Expr {
298 left.and(right)
299}
300
301pub fn or(left: Expr, right: Expr) -> Expr {
306 left.or(right)
307}
308
309pub fn alias(expr: Expr, name: &str) -> Expr {
314 Expr(Expression::Alias(Box::new(Alias {
315 this: expr.0,
316 alias: builder_identifier(name),
317 column_aliases: Vec::new(),
318 alias_explicit_as: false,
319 alias_keyword: None,
320 pre_alias_comments: Vec::new(),
321 trailing_comments: Vec::new(),
322 inferred_type: None,
323 })))
324}
325
326pub fn sql_expr(sql: &str) -> Expr {
350 let wrapped = format!("SELECT {}", sql);
351 let ast = Parser::parse_sql(&wrapped).expect("sql_expr: failed to parse SQL expression");
352 if let Expression::Select(s) = &ast[0] {
353 if let Some(first) = s.expressions.first() {
354 return Expr(first.clone());
355 }
356 }
357 panic!("sql_expr: failed to extract expression from parsed SQL");
358}
359
360pub fn condition(sql: &str) -> Expr {
369 sql_expr(sql)
370}
371
372pub fn count(expr: Expr) -> Expr {
380 Expr(Expression::Count(Box::new(CountFunc {
381 this: Some(expr.0),
382 star: false,
383 distinct: false,
384 filter: None,
385 ignore_nulls: None,
386 original_name: None,
387 inferred_type: None,
388 })))
389}
390
391pub fn count_star() -> Expr {
393 Expr(Expression::Count(Box::new(CountFunc {
394 this: None,
395 star: true,
396 distinct: false,
397 filter: None,
398 ignore_nulls: None,
399 original_name: None,
400 inferred_type: None,
401 })))
402}
403
404pub fn count_distinct(expr: Expr) -> Expr {
406 Expr(Expression::Count(Box::new(CountFunc {
407 this: Some(expr.0),
408 star: false,
409 distinct: true,
410 filter: None,
411 ignore_nulls: None,
412 original_name: None,
413 inferred_type: None,
414 })))
415}
416
417pub fn sum(expr: Expr) -> Expr {
419 Expr(Expression::Sum(Box::new(AggFunc {
420 this: expr.0,
421 distinct: false,
422 filter: None,
423 order_by: vec![],
424 name: None,
425 ignore_nulls: None,
426 having_max: None,
427 limit: None,
428 inferred_type: None,
429 })))
430}
431
432pub fn avg(expr: Expr) -> Expr {
434 Expr(Expression::Avg(Box::new(AggFunc {
435 this: expr.0,
436 distinct: false,
437 filter: None,
438 order_by: vec![],
439 name: None,
440 ignore_nulls: None,
441 having_max: None,
442 limit: None,
443 inferred_type: None,
444 })))
445}
446
447pub fn min_(expr: Expr) -> Expr {
449 Expr(Expression::Min(Box::new(AggFunc {
450 this: expr.0,
451 distinct: false,
452 filter: None,
453 order_by: vec![],
454 name: None,
455 ignore_nulls: None,
456 having_max: None,
457 limit: None,
458 inferred_type: None,
459 })))
460}
461
462pub fn max_(expr: Expr) -> Expr {
464 Expr(Expression::Max(Box::new(AggFunc {
465 this: expr.0,
466 distinct: false,
467 filter: None,
468 order_by: vec![],
469 name: None,
470 ignore_nulls: None,
471 having_max: None,
472 limit: None,
473 inferred_type: None,
474 })))
475}
476
477pub fn approx_distinct(expr: Expr) -> Expr {
479 Expr(Expression::ApproxDistinct(Box::new(AggFunc {
480 this: expr.0,
481 distinct: false,
482 filter: None,
483 order_by: vec![],
484 name: None,
485 ignore_nulls: None,
486 having_max: None,
487 limit: None,
488 inferred_type: None,
489 })))
490}
491
492pub fn upper(expr: Expr) -> Expr {
496 Expr(Expression::Upper(Box::new(UnaryFunc::new(expr.0))))
497}
498
499pub fn lower(expr: Expr) -> Expr {
501 Expr(Expression::Lower(Box::new(UnaryFunc::new(expr.0))))
502}
503
504pub fn length(expr: Expr) -> Expr {
506 Expr(Expression::Length(Box::new(UnaryFunc::new(expr.0))))
507}
508
509pub fn trim(expr: Expr) -> Expr {
511 Expr(Expression::Trim(Box::new(TrimFunc {
512 this: expr.0,
513 characters: None,
514 position: TrimPosition::Both,
515 sql_standard_syntax: false,
516 position_explicit: false,
517 })))
518}
519
520pub fn ltrim(expr: Expr) -> Expr {
522 Expr(Expression::LTrim(Box::new(UnaryFunc::new(expr.0))))
523}
524
525pub fn rtrim(expr: Expr) -> Expr {
527 Expr(Expression::RTrim(Box::new(UnaryFunc::new(expr.0))))
528}
529
530pub fn reverse(expr: Expr) -> Expr {
532 Expr(Expression::Reverse(Box::new(UnaryFunc::new(expr.0))))
533}
534
535pub fn initcap(expr: Expr) -> Expr {
537 Expr(Expression::Initcap(Box::new(UnaryFunc::new(expr.0))))
538}
539
540pub fn substring(expr: Expr, start: Expr, len: Option<Expr>) -> Expr {
542 Expr(Expression::Substring(Box::new(SubstringFunc {
543 this: expr.0,
544 start: start.0,
545 length: len.map(|l| l.0),
546 from_for_syntax: false,
547 })))
548}
549
550pub fn replace_(expr: Expr, old: Expr, new: Expr) -> Expr {
553 Expr(Expression::Replace(Box::new(ReplaceFunc {
554 this: expr.0,
555 old: old.0,
556 new: new.0,
557 })))
558}
559
560pub fn concat_ws(separator: Expr, exprs: impl IntoIterator<Item = Expr>) -> Expr {
562 Expr(Expression::ConcatWs(Box::new(ConcatWs {
563 separator: separator.0,
564 expressions: exprs.into_iter().map(|e| e.0).collect(),
565 })))
566}
567
568pub fn coalesce(exprs: impl IntoIterator<Item = Expr>) -> Expr {
572 Expr(Expression::Coalesce(Box::new(VarArgFunc {
573 expressions: exprs.into_iter().map(|e| e.0).collect(),
574 original_name: None,
575 inferred_type: None,
576 })))
577}
578
579pub fn null_if(expr1: Expr, expr2: Expr) -> Expr {
581 Expr(Expression::NullIf(Box::new(BinaryFunc {
582 this: expr1.0,
583 expression: expr2.0,
584 original_name: None,
585 inferred_type: None,
586 })))
587}
588
589pub fn if_null(expr: Expr, fallback: Expr) -> Expr {
591 Expr(Expression::IfNull(Box::new(BinaryFunc {
592 this: expr.0,
593 expression: fallback.0,
594 original_name: None,
595 inferred_type: None,
596 })))
597}
598
599pub fn abs(expr: Expr) -> Expr {
603 Expr(Expression::Abs(Box::new(UnaryFunc::new(expr.0))))
604}
605
606pub fn round(expr: Expr, decimals: Option<Expr>) -> Expr {
608 Expr(Expression::Round(Box::new(RoundFunc {
609 this: expr.0,
610 decimals: decimals.map(|d| d.0),
611 })))
612}
613
614pub fn floor(expr: Expr) -> Expr {
616 Expr(Expression::Floor(Box::new(FloorFunc {
617 this: expr.0,
618 scale: None,
619 to: None,
620 })))
621}
622
623pub fn ceil(expr: Expr) -> Expr {
625 Expr(Expression::Ceil(Box::new(CeilFunc {
626 this: expr.0,
627 decimals: None,
628 to: None,
629 })))
630}
631
632pub fn power(base: Expr, exponent: Expr) -> Expr {
634 Expr(Expression::Power(Box::new(BinaryFunc {
635 this: base.0,
636 expression: exponent.0,
637 original_name: None,
638 inferred_type: None,
639 })))
640}
641
642pub fn sqrt(expr: Expr) -> Expr {
644 Expr(Expression::Sqrt(Box::new(UnaryFunc::new(expr.0))))
645}
646
647pub fn ln(expr: Expr) -> Expr {
649 Expr(Expression::Ln(Box::new(UnaryFunc::new(expr.0))))
650}
651
652pub fn exp_(expr: Expr) -> Expr {
654 Expr(Expression::Exp(Box::new(UnaryFunc::new(expr.0))))
655}
656
657pub fn sign(expr: Expr) -> Expr {
659 Expr(Expression::Sign(Box::new(UnaryFunc::new(expr.0))))
660}
661
662pub fn greatest(exprs: impl IntoIterator<Item = Expr>) -> Expr {
664 Expr(Expression::Greatest(Box::new(VarArgFunc {
665 expressions: exprs.into_iter().map(|e| e.0).collect(),
666 original_name: None,
667 inferred_type: None,
668 })))
669}
670
671pub fn least(exprs: impl IntoIterator<Item = Expr>) -> Expr {
673 Expr(Expression::Least(Box::new(VarArgFunc {
674 expressions: exprs.into_iter().map(|e| e.0).collect(),
675 original_name: None,
676 inferred_type: None,
677 })))
678}
679
680pub fn current_date_() -> Expr {
684 Expr(Expression::CurrentDate(CurrentDate))
685}
686
687pub fn current_time_() -> Expr {
689 Expr(Expression::CurrentTime(CurrentTime { precision: None }))
690}
691
692pub fn current_timestamp_() -> Expr {
694 Expr(Expression::CurrentTimestamp(CurrentTimestamp {
695 precision: None,
696 sysdate: false,
697 }))
698}
699
700pub fn extract_(field: &str, expr: Expr) -> Expr {
702 Expr(Expression::Extract(Box::new(ExtractFunc {
703 this: expr.0,
704 field: parse_datetime_field(field),
705 })))
706}
707
708fn parse_datetime_field(field: &str) -> DateTimeField {
710 match field.to_uppercase().as_str() {
711 "YEAR" => DateTimeField::Year,
712 "MONTH" => DateTimeField::Month,
713 "DAY" => DateTimeField::Day,
714 "HOUR" => DateTimeField::Hour,
715 "MINUTE" => DateTimeField::Minute,
716 "SECOND" => DateTimeField::Second,
717 "MILLISECOND" => DateTimeField::Millisecond,
718 "MICROSECOND" => DateTimeField::Microsecond,
719 "DOW" | "DAYOFWEEK" => DateTimeField::DayOfWeek,
720 "DOY" | "DAYOFYEAR" => DateTimeField::DayOfYear,
721 "WEEK" => DateTimeField::Week,
722 "QUARTER" => DateTimeField::Quarter,
723 "EPOCH" => DateTimeField::Epoch,
724 "TIMEZONE" => DateTimeField::Timezone,
725 "TIMEZONE_HOUR" => DateTimeField::TimezoneHour,
726 "TIMEZONE_MINUTE" => DateTimeField::TimezoneMinute,
727 "DATE" => DateTimeField::Date,
728 "TIME" => DateTimeField::Time,
729 other => DateTimeField::Custom(other.to_string()),
730 }
731}
732
733pub fn row_number() -> Expr {
737 Expr(Expression::RowNumber(RowNumber))
738}
739
740pub fn rank_() -> Expr {
742 Expr(Expression::Rank(Rank {
743 order_by: None,
744 args: vec![],
745 }))
746}
747
748pub fn dense_rank() -> Expr {
750 Expr(Expression::DenseRank(DenseRank { args: vec![] }))
751}
752
753pub fn select<I, E>(expressions: I) -> SelectBuilder
780where
781 I: IntoIterator<Item = E>,
782 E: IntoExpr,
783{
784 let mut builder = SelectBuilder::new();
785 for expr in expressions {
786 builder.select = builder.select.column(expr.into_expr().0);
787 }
788 builder
789}
790
791pub fn from(table_name: &str) -> SelectBuilder {
806 let mut builder = SelectBuilder::new();
807 builder.select.from = Some(From {
808 expressions: vec![Expression::Table(Box::new(builder_table_ref(table_name)))],
809 });
810 builder
811}
812
813pub fn delete(table_name: &str) -> DeleteBuilder {
826 DeleteBuilder {
827 delete: Delete {
828 table: builder_table_ref(table_name),
829 hint: None,
830 on_cluster: None,
831 alias: None,
832 alias_explicit_as: false,
833 using: Vec::new(),
834 where_clause: None,
835 output: None,
836 leading_comments: Vec::new(),
837 with: None,
838 limit: None,
839 order_by: None,
840 returning: Vec::new(),
841 tables: Vec::new(),
842 tables_from_using: false,
843 joins: Vec::new(),
844 force_index: None,
845 no_from: false,
846 },
847 }
848}
849
850pub fn insert_into(table_name: &str) -> InsertBuilder {
867 InsertBuilder {
868 insert: Insert {
869 table: builder_table_ref(table_name),
870 columns: Vec::new(),
871 values: Vec::new(),
872 query: None,
873 overwrite: false,
874 partition: Vec::new(),
875 directory: None,
876 returning: Vec::new(),
877 output: None,
878 on_conflict: None,
879 leading_comments: Vec::new(),
880 if_exists: false,
881 with: None,
882 ignore: false,
883 source_alias: None,
884 alias: None,
885 alias_explicit_as: false,
886 default_values: false,
887 by_name: false,
888 conflict_action: None,
889 is_replace: false,
890 hint: None,
891 replace_where: None,
892 source: None,
893 function_target: None,
894 partition_by: None,
895 settings: Vec::new(),
896 },
897 }
898}
899
900pub fn update(table_name: &str) -> UpdateBuilder {
918 UpdateBuilder {
919 update: Update {
920 table: builder_table_ref(table_name),
921 hint: None,
922 extra_tables: Vec::new(),
923 table_joins: Vec::new(),
924 set: Vec::new(),
925 from_clause: None,
926 from_joins: Vec::new(),
927 where_clause: None,
928 returning: Vec::new(),
929 output: None,
930 with: None,
931 leading_comments: Vec::new(),
932 limit: None,
933 order_by: None,
934 from_before_set: false,
935 },
936 }
937}
938
939#[derive(Debug, Clone)]
964pub struct Expr(pub Expression);
965
966impl Expr {
967 pub fn into_inner(self) -> Expression {
969 self.0
970 }
971
972 pub fn to_sql(&self) -> String {
976 Generator::sql(&self.0).unwrap_or_default()
977 }
978
979 pub fn eq(self, other: Expr) -> Expr {
983 Expr(Expression::Eq(Box::new(binary_op(self.0, other.0))))
984 }
985
986 pub fn neq(self, other: Expr) -> Expr {
988 Expr(Expression::Neq(Box::new(binary_op(self.0, other.0))))
989 }
990
991 pub fn lt(self, other: Expr) -> Expr {
993 Expr(Expression::Lt(Box::new(binary_op(self.0, other.0))))
994 }
995
996 pub fn lte(self, other: Expr) -> Expr {
998 Expr(Expression::Lte(Box::new(binary_op(self.0, other.0))))
999 }
1000
1001 pub fn gt(self, other: Expr) -> Expr {
1003 Expr(Expression::Gt(Box::new(binary_op(self.0, other.0))))
1004 }
1005
1006 pub fn gte(self, other: Expr) -> Expr {
1008 Expr(Expression::Gte(Box::new(binary_op(self.0, other.0))))
1009 }
1010
1011 pub fn and(self, other: Expr) -> Expr {
1015 Expr(Expression::And(Box::new(binary_op(self.0, other.0))))
1016 }
1017
1018 pub fn or(self, other: Expr) -> Expr {
1020 Expr(Expression::Or(Box::new(binary_op(self.0, other.0))))
1021 }
1022
1023 pub fn not(self) -> Expr {
1025 Expr(Expression::Not(Box::new(UnaryOp::new(self.0))))
1026 }
1027
1028 pub fn xor(self, other: Expr) -> Expr {
1030 Expr(Expression::Xor(Box::new(Xor {
1031 this: Some(Box::new(self.0)),
1032 expression: Some(Box::new(other.0)),
1033 expressions: vec![],
1034 })))
1035 }
1036
1037 pub fn add(self, other: Expr) -> Expr {
1041 Expr(Expression::Add(Box::new(binary_op(self.0, other.0))))
1042 }
1043
1044 pub fn sub(self, other: Expr) -> Expr {
1046 Expr(Expression::Sub(Box::new(binary_op(self.0, other.0))))
1047 }
1048
1049 pub fn mul(self, other: Expr) -> Expr {
1051 Expr(Expression::Mul(Box::new(binary_op(self.0, other.0))))
1052 }
1053
1054 pub fn div(self, other: Expr) -> Expr {
1056 Expr(Expression::Div(Box::new(binary_op(self.0, other.0))))
1057 }
1058
1059 pub fn is_null(self) -> Expr {
1063 Expr(Expression::Is(Box::new(BinaryOp {
1064 left: self.0,
1065 right: Expression::Null(Null),
1066 left_comments: Vec::new(),
1067 operator_comments: Vec::new(),
1068 trailing_comments: Vec::new(),
1069 inferred_type: None,
1070 })))
1071 }
1072
1073 pub fn is_not_null(self) -> Expr {
1075 Expr(Expression::Not(Box::new(UnaryOp::new(Expression::Is(
1076 Box::new(BinaryOp {
1077 left: self.0,
1078 right: Expression::Null(Null),
1079 left_comments: Vec::new(),
1080 operator_comments: Vec::new(),
1081 trailing_comments: Vec::new(),
1082 inferred_type: None,
1083 }),
1084 )))))
1085 }
1086
1087 pub fn in_list(self, values: impl IntoIterator<Item = Expr>) -> Expr {
1091 Expr(Expression::In(Box::new(In {
1092 this: self.0,
1093 expressions: values.into_iter().map(|v| v.0).collect(),
1094 query: None,
1095 not: false,
1096 global: false,
1097 unnest: None,
1098 is_field: false,
1099 })))
1100 }
1101
1102 pub fn between(self, low: Expr, high: Expr) -> Expr {
1104 Expr(Expression::Between(Box::new(Between {
1105 this: self.0,
1106 low: low.0,
1107 high: high.0,
1108 not: false,
1109 symmetric: None,
1110 })))
1111 }
1112
1113 pub fn like(self, pattern: Expr) -> Expr {
1115 Expr(Expression::Like(Box::new(LikeOp {
1116 left: self.0,
1117 right: pattern.0,
1118 escape: None,
1119 quantifier: None,
1120 inferred_type: None,
1121 })))
1122 }
1123
1124 pub fn alias(self, name: &str) -> Expr {
1126 alias(self, name)
1127 }
1128
1129 pub fn cast(self, to: &str) -> Expr {
1133 cast(self, to)
1134 }
1135
1136 pub fn asc(self) -> Expr {
1141 Expr(Expression::Ordered(Box::new(Ordered {
1142 this: self.0,
1143 desc: false,
1144 nulls_first: None,
1145 explicit_asc: true,
1146 with_fill: None,
1147 })))
1148 }
1149
1150 pub fn desc(self) -> Expr {
1154 Expr(Expression::Ordered(Box::new(Ordered {
1155 this: self.0,
1156 desc: true,
1157 nulls_first: None,
1158 explicit_asc: false,
1159 with_fill: None,
1160 })))
1161 }
1162
1163 pub fn ilike(self, pattern: Expr) -> Expr {
1168 Expr(Expression::ILike(Box::new(LikeOp {
1169 left: self.0,
1170 right: pattern.0,
1171 escape: None,
1172 quantifier: None,
1173 inferred_type: None,
1174 })))
1175 }
1176
1177 pub fn rlike(self, pattern: Expr) -> Expr {
1182 Expr(Expression::RegexpLike(Box::new(RegexpFunc {
1183 this: self.0,
1184 pattern: pattern.0,
1185 flags: None,
1186 })))
1187 }
1188
1189 pub fn not_in(self, values: impl IntoIterator<Item = Expr>) -> Expr {
1193 Expr(Expression::In(Box::new(In {
1194 this: self.0,
1195 expressions: values.into_iter().map(|v| v.0).collect(),
1196 query: None,
1197 not: true,
1198 global: false,
1199 unnest: None,
1200 is_field: false,
1201 })))
1202 }
1203}
1204
1205pub struct SelectBuilder {
1231 select: Select,
1232}
1233
1234impl SelectBuilder {
1235 fn new() -> Self {
1236 SelectBuilder {
1237 select: Select::new(),
1238 }
1239 }
1240
1241 pub fn select_cols<I, E>(mut self, expressions: I) -> Self
1246 where
1247 I: IntoIterator<Item = E>,
1248 E: IntoExpr,
1249 {
1250 for expr in expressions {
1251 self.select.expressions.push(expr.into_expr().0);
1252 }
1253 self
1254 }
1255
1256 pub fn from(mut self, table_name: &str) -> Self {
1258 self.select.from = Some(From {
1259 expressions: vec![Expression::Table(Box::new(builder_table_ref(table_name)))],
1260 });
1261 self
1262 }
1263
1264 pub fn from_expr(mut self, expr: Expr) -> Self {
1269 self.select.from = Some(From {
1270 expressions: vec![expr.0],
1271 });
1272 self
1273 }
1274
1275 pub fn join(mut self, table_name: &str, on: Expr) -> Self {
1277 self.select.joins.push(Join {
1278 kind: JoinKind::Inner,
1279 this: Expression::Table(Box::new(builder_table_ref(table_name))),
1280 on: Some(on.0),
1281 using: Vec::new(),
1282 use_inner_keyword: false,
1283 use_outer_keyword: false,
1284 deferred_condition: false,
1285 join_hint: None,
1286 match_condition: None,
1287 pivots: Vec::new(),
1288 comments: Vec::new(),
1289 nesting_group: 0,
1290 directed: false,
1291 });
1292 self
1293 }
1294
1295 pub fn left_join(mut self, table_name: &str, on: Expr) -> Self {
1297 self.select.joins.push(Join {
1298 kind: JoinKind::Left,
1299 this: Expression::Table(Box::new(builder_table_ref(table_name))),
1300 on: Some(on.0),
1301 using: Vec::new(),
1302 use_inner_keyword: false,
1303 use_outer_keyword: false,
1304 deferred_condition: false,
1305 join_hint: None,
1306 match_condition: None,
1307 pivots: Vec::new(),
1308 comments: Vec::new(),
1309 nesting_group: 0,
1310 directed: false,
1311 });
1312 self
1313 }
1314
1315 pub fn where_(mut self, condition: Expr) -> Self {
1321 self.select.where_clause = Some(Where { this: condition.0 });
1322 self
1323 }
1324
1325 pub fn group_by<I, E>(mut self, expressions: I) -> Self
1327 where
1328 I: IntoIterator<Item = E>,
1329 E: IntoExpr,
1330 {
1331 self.select.group_by = Some(GroupBy {
1332 expressions: expressions.into_iter().map(|e| e.into_expr().0).collect(),
1333 all: None,
1334 totals: false,
1335 comments: Vec::new(),
1336 });
1337 self
1338 }
1339
1340 pub fn having(mut self, condition: Expr) -> Self {
1342 self.select.having = Some(Having {
1343 this: condition.0,
1344 comments: Vec::new(),
1345 });
1346 self
1347 }
1348
1349 pub fn order_by<I, E>(mut self, expressions: I) -> Self
1355 where
1356 I: IntoIterator<Item = E>,
1357 E: IntoExpr,
1358 {
1359 self.select.order_by = Some(OrderBy {
1360 siblings: false,
1361 comments: Vec::new(),
1362 expressions: expressions
1363 .into_iter()
1364 .map(|e| {
1365 let expr = e.into_expr().0;
1366 match expr {
1367 Expression::Ordered(_) => expr,
1368 other => Expression::Ordered(Box::new(Ordered {
1369 this: other,
1370 desc: false,
1371 nulls_first: None,
1372 explicit_asc: false,
1373 with_fill: None,
1374 })),
1375 }
1376 })
1377 .collect::<Vec<_>>()
1378 .into_iter()
1379 .map(|e| {
1380 if let Expression::Ordered(o) = e {
1381 *o
1382 } else {
1383 Ordered {
1384 this: e,
1385 desc: false,
1386 nulls_first: None,
1387 explicit_asc: false,
1388 with_fill: None,
1389 }
1390 }
1391 })
1392 .collect(),
1393 });
1394 self
1395 }
1396
1397 pub fn sort_by<I, E>(mut self, expressions: I) -> Self
1404 where
1405 I: IntoIterator<Item = E>,
1406 E: IntoExpr,
1407 {
1408 self.select.sort_by = Some(SortBy {
1409 expressions: expressions
1410 .into_iter()
1411 .map(|e| {
1412 let expr = e.into_expr().0;
1413 match expr {
1414 Expression::Ordered(o) => *o,
1415 other => Ordered {
1416 this: other,
1417 desc: false,
1418 nulls_first: None,
1419 explicit_asc: false,
1420 with_fill: None,
1421 },
1422 }
1423 })
1424 .collect(),
1425 });
1426 self
1427 }
1428
1429 pub fn limit(mut self, count: usize) -> Self {
1431 self.select.limit = Some(Limit {
1432 this: Expression::Literal(Box::new(Literal::Number(count.to_string()))),
1433 percent: false,
1434 comments: Vec::new(),
1435 });
1436 self
1437 }
1438
1439 pub fn offset(mut self, count: usize) -> Self {
1441 self.select.offset = Some(Offset {
1442 this: Expression::Literal(Box::new(Literal::Number(count.to_string()))),
1443 rows: None,
1444 });
1445 self
1446 }
1447
1448 pub fn distinct(mut self) -> Self {
1450 self.select.distinct = true;
1451 self
1452 }
1453
1454 pub fn qualify(mut self, condition: Expr) -> Self {
1459 self.select.qualify = Some(Qualify { this: condition.0 });
1460 self
1461 }
1462
1463 pub fn right_join(mut self, table_name: &str, on: Expr) -> Self {
1465 self.select.joins.push(Join {
1466 kind: JoinKind::Right,
1467 this: Expression::Table(Box::new(builder_table_ref(table_name))),
1468 on: Some(on.0),
1469 using: Vec::new(),
1470 use_inner_keyword: false,
1471 use_outer_keyword: false,
1472 deferred_condition: false,
1473 join_hint: None,
1474 match_condition: None,
1475 pivots: Vec::new(),
1476 comments: Vec::new(),
1477 nesting_group: 0,
1478 directed: false,
1479 });
1480 self
1481 }
1482
1483 pub fn cross_join(mut self, table_name: &str) -> Self {
1485 self.select.joins.push(Join {
1486 kind: JoinKind::Cross,
1487 this: Expression::Table(Box::new(builder_table_ref(table_name))),
1488 on: None,
1489 using: Vec::new(),
1490 use_inner_keyword: false,
1491 use_outer_keyword: false,
1492 deferred_condition: false,
1493 join_hint: None,
1494 match_condition: None,
1495 pivots: Vec::new(),
1496 comments: Vec::new(),
1497 nesting_group: 0,
1498 directed: false,
1499 });
1500 self
1501 }
1502
1503 pub fn lateral_view<S: AsRef<str>>(
1510 mut self,
1511 table_function: Expr,
1512 table_alias: &str,
1513 column_aliases: impl IntoIterator<Item = S>,
1514 ) -> Self {
1515 self.select.lateral_views.push(LateralView {
1516 this: table_function.0,
1517 table_alias: Some(builder_identifier(table_alias)),
1518 column_aliases: column_aliases
1519 .into_iter()
1520 .map(|c| builder_identifier(c.as_ref()))
1521 .collect(),
1522 outer: false,
1523 });
1524 self
1525 }
1526
1527 pub fn window(mut self, name: &str, def: WindowDefBuilder) -> Self {
1533 let named_window = NamedWindow {
1534 name: builder_identifier(name),
1535 spec: Over {
1536 window_name: None,
1537 partition_by: def.partition_by,
1538 order_by: def.order_by,
1539 frame: None,
1540 alias: None,
1541 },
1542 };
1543 match self.select.windows {
1544 Some(ref mut windows) => windows.push(named_window),
1545 None => self.select.windows = Some(vec![named_window]),
1546 }
1547 self
1548 }
1549
1550 pub fn for_update(mut self) -> Self {
1555 self.select.locks.push(Lock {
1556 update: Some(Box::new(Expression::Boolean(BooleanLiteral {
1557 value: true,
1558 }))),
1559 expressions: vec![],
1560 wait: None,
1561 key: None,
1562 });
1563 self
1564 }
1565
1566 pub fn for_share(mut self) -> Self {
1571 self.select.locks.push(Lock {
1572 update: None,
1573 expressions: vec![],
1574 wait: None,
1575 key: None,
1576 });
1577 self
1578 }
1579
1580 pub fn hint(mut self, hint_text: &str) -> Self {
1585 let hint_expr = HintExpression::Raw(hint_text.to_string());
1586 match &mut self.select.hint {
1587 Some(h) => h.expressions.push(hint_expr),
1588 None => {
1589 self.select.hint = Some(Hint {
1590 expressions: vec![hint_expr],
1591 })
1592 }
1593 }
1594 self
1595 }
1596
1597 pub fn ctas(self, table_name: &str) -> Expression {
1613 Expression::CreateTable(Box::new(CreateTable {
1614 name: builder_table_ref(table_name),
1615 on_cluster: None,
1616 columns: vec![],
1617 constraints: vec![],
1618 if_not_exists: false,
1619 temporary: false,
1620 or_replace: false,
1621 table_modifier: None,
1622 as_select: Some(self.build()),
1623 as_select_parenthesized: false,
1624 on_commit: None,
1625 clone_source: None,
1626 clone_at_clause: None,
1627 is_copy: false,
1628 shallow_clone: false,
1629 deep_clone: false,
1630 leading_comments: vec![],
1631 with_properties: vec![],
1632 teradata_post_name_options: vec![],
1633 with_data: None,
1634 with_statistics: None,
1635 teradata_indexes: vec![],
1636 with_cte: None,
1637 properties: vec![],
1638 partition_of: None,
1639 post_table_properties: vec![],
1640 mysql_table_options: vec![],
1641 tidb_table_options: vec![],
1642 inherits: vec![],
1643 on_property: None,
1644 copy_grants: false,
1645 using_template: None,
1646 rollup: None,
1647 uuid: None,
1648 with_partition_columns: vec![],
1649 with_connection: None,
1650 }))
1651 }
1652
1653 pub fn union(self, other: SelectBuilder) -> SetOpBuilder {
1657 SetOpBuilder::new(SetOpKind::Union, self, other, false)
1658 }
1659
1660 pub fn union_all(self, other: SelectBuilder) -> SetOpBuilder {
1664 SetOpBuilder::new(SetOpKind::Union, self, other, true)
1665 }
1666
1667 pub fn intersect(self, other: SelectBuilder) -> SetOpBuilder {
1671 SetOpBuilder::new(SetOpKind::Intersect, self, other, false)
1672 }
1673
1674 pub fn except_(self, other: SelectBuilder) -> SetOpBuilder {
1678 SetOpBuilder::new(SetOpKind::Except, self, other, false)
1679 }
1680
1681 pub fn build(self) -> Expression {
1683 Expression::Select(Box::new(self.select))
1684 }
1685
1686 pub fn to_sql(self) -> String {
1691 Generator::sql(&self.build()).unwrap_or_default()
1692 }
1693}
1694
1695pub struct DeleteBuilder {
1704 delete: Delete,
1705}
1706
1707impl DeleteBuilder {
1708 pub fn where_(mut self, condition: Expr) -> Self {
1710 self.delete.where_clause = Some(Where { this: condition.0 });
1711 self
1712 }
1713
1714 pub fn build(self) -> Expression {
1716 Expression::Delete(Box::new(self.delete))
1717 }
1718
1719 pub fn to_sql(self) -> String {
1721 Generator::sql(&self.build()).unwrap_or_default()
1722 }
1723}
1724
1725pub struct InsertBuilder {
1736 insert: Insert,
1737}
1738
1739impl InsertBuilder {
1740 pub fn columns<I, S>(mut self, columns: I) -> Self
1742 where
1743 I: IntoIterator<Item = S>,
1744 S: AsRef<str>,
1745 {
1746 self.insert.columns = columns
1747 .into_iter()
1748 .map(|c| builder_identifier(c.as_ref()))
1749 .collect();
1750 self
1751 }
1752
1753 pub fn values<I>(mut self, values: I) -> Self
1757 where
1758 I: IntoIterator<Item = Expr>,
1759 {
1760 self.insert
1761 .values
1762 .push(values.into_iter().map(|v| v.0).collect());
1763 self
1764 }
1765
1766 pub fn query(mut self, query: SelectBuilder) -> Self {
1770 self.insert.query = Some(query.build());
1771 self
1772 }
1773
1774 pub fn build(self) -> Expression {
1776 Expression::Insert(Box::new(self.insert))
1777 }
1778
1779 pub fn to_sql(self) -> String {
1781 Generator::sql(&self.build()).unwrap_or_default()
1782 }
1783}
1784
1785pub struct UpdateBuilder {
1795 update: Update,
1796}
1797
1798impl UpdateBuilder {
1799 pub fn set(mut self, column: &str, value: Expr) -> Self {
1803 self.update.set.push((builder_identifier(column), value.0));
1804 self
1805 }
1806
1807 pub fn where_(mut self, condition: Expr) -> Self {
1809 self.update.where_clause = Some(Where { this: condition.0 });
1810 self
1811 }
1812
1813 pub fn from(mut self, table_name: &str) -> Self {
1817 self.update.from_clause = Some(From {
1818 expressions: vec![Expression::Table(Box::new(builder_table_ref(table_name)))],
1819 });
1820 self
1821 }
1822
1823 pub fn build(self) -> Expression {
1825 Expression::Update(Box::new(self.update))
1826 }
1827
1828 pub fn to_sql(self) -> String {
1830 Generator::sql(&self.build()).unwrap_or_default()
1831 }
1832}
1833
1834pub fn case() -> CaseBuilder {
1859 CaseBuilder {
1860 operand: None,
1861 whens: Vec::new(),
1862 else_: None,
1863 }
1864}
1865
1866pub fn case_of(operand: Expr) -> CaseBuilder {
1887 CaseBuilder {
1888 operand: Some(operand.0),
1889 whens: Vec::new(),
1890 else_: None,
1891 }
1892}
1893
1894pub struct CaseBuilder {
1902 operand: Option<Expression>,
1903 whens: Vec<(Expression, Expression)>,
1904 else_: Option<Expression>,
1905}
1906
1907impl CaseBuilder {
1908 pub fn when(mut self, condition: Expr, result: Expr) -> Self {
1913 self.whens.push((condition.0, result.0));
1914 self
1915 }
1916
1917 pub fn else_(mut self, result: Expr) -> Self {
1922 self.else_ = Some(result.0);
1923 self
1924 }
1925
1926 pub fn build(self) -> Expr {
1928 Expr(self.build_expr())
1929 }
1930
1931 pub fn build_expr(self) -> Expression {
1936 Expression::Case(Box::new(Case {
1937 operand: self.operand,
1938 whens: self.whens,
1939 else_: self.else_,
1940 comments: Vec::new(),
1941 inferred_type: None,
1942 }))
1943 }
1944}
1945
1946pub fn subquery(query: SelectBuilder, alias_name: &str) -> Expr {
1970 subquery_expr(query.build(), alias_name)
1971}
1972
1973pub fn subquery_expr(expr: Expression, alias_name: &str) -> Expr {
1978 Expr(Expression::Subquery(Box::new(Subquery {
1979 this: expr,
1980 alias: Some(builder_identifier(alias_name)),
1981 column_aliases: Vec::new(),
1982 alias_explicit_as: false,
1983 alias_keyword: None,
1984 order_by: None,
1985 limit: None,
1986 offset: None,
1987 distribute_by: None,
1988 sort_by: None,
1989 cluster_by: None,
1990 lateral: false,
1991 modifiers_inside: true,
1992 trailing_comments: Vec::new(),
1993 inferred_type: None,
1994 })))
1995}
1996
1997#[derive(Debug, Clone, Copy)]
2003enum SetOpKind {
2004 Union,
2005 Intersect,
2006 Except,
2007}
2008
2009pub struct SetOpBuilder {
2030 kind: SetOpKind,
2031 left: Expression,
2032 right: Expression,
2033 all: bool,
2034 order_by: Option<OrderBy>,
2035 limit: Option<Box<Expression>>,
2036 offset: Option<Box<Expression>>,
2037}
2038
2039impl SetOpBuilder {
2040 fn new(kind: SetOpKind, left: SelectBuilder, right: SelectBuilder, all: bool) -> Self {
2041 SetOpBuilder {
2042 kind,
2043 left: left.build(),
2044 right: right.build(),
2045 all,
2046 order_by: None,
2047 limit: None,
2048 offset: None,
2049 }
2050 }
2051
2052 pub fn order_by<I, E>(mut self, expressions: I) -> Self
2057 where
2058 I: IntoIterator<Item = E>,
2059 E: IntoExpr,
2060 {
2061 self.order_by = Some(OrderBy {
2062 siblings: false,
2063 comments: Vec::new(),
2064 expressions: expressions
2065 .into_iter()
2066 .map(|e| {
2067 let expr = e.into_expr().0;
2068 match expr {
2069 Expression::Ordered(o) => *o,
2070 other => Ordered {
2071 this: other,
2072 desc: false,
2073 nulls_first: None,
2074 explicit_asc: false,
2075 with_fill: None,
2076 },
2077 }
2078 })
2079 .collect(),
2080 });
2081 self
2082 }
2083
2084 pub fn limit(mut self, count: usize) -> Self {
2086 self.limit = Some(Box::new(Expression::Literal(Box::new(Literal::Number(
2087 count.to_string(),
2088 )))));
2089 self
2090 }
2091
2092 pub fn offset(mut self, count: usize) -> Self {
2094 self.offset = Some(Box::new(Expression::Literal(Box::new(Literal::Number(
2095 count.to_string(),
2096 )))));
2097 self
2098 }
2099
2100 pub fn build(self) -> Expression {
2105 match self.kind {
2106 SetOpKind::Union => Expression::Union(Box::new(Union {
2107 left: self.left,
2108 right: self.right,
2109 all: self.all,
2110 distinct: false,
2111 with: None,
2112 order_by: self.order_by,
2113 limit: self.limit,
2114 offset: self.offset,
2115 distribute_by: None,
2116 sort_by: None,
2117 cluster_by: None,
2118 by_name: false,
2119 side: None,
2120 kind: None,
2121 corresponding: false,
2122 strict: false,
2123 on_columns: Vec::new(),
2124 })),
2125 SetOpKind::Intersect => Expression::Intersect(Box::new(Intersect {
2126 left: self.left,
2127 right: self.right,
2128 all: self.all,
2129 distinct: false,
2130 with: None,
2131 order_by: self.order_by,
2132 limit: self.limit,
2133 offset: self.offset,
2134 distribute_by: None,
2135 sort_by: None,
2136 cluster_by: None,
2137 by_name: false,
2138 side: None,
2139 kind: None,
2140 corresponding: false,
2141 strict: false,
2142 on_columns: Vec::new(),
2143 })),
2144 SetOpKind::Except => Expression::Except(Box::new(Except {
2145 left: self.left,
2146 right: self.right,
2147 all: self.all,
2148 distinct: false,
2149 with: None,
2150 order_by: self.order_by,
2151 limit: self.limit,
2152 offset: self.offset,
2153 distribute_by: None,
2154 sort_by: None,
2155 cluster_by: None,
2156 by_name: false,
2157 side: None,
2158 kind: None,
2159 corresponding: false,
2160 strict: false,
2161 on_columns: Vec::new(),
2162 })),
2163 }
2164 }
2165
2166 pub fn to_sql(self) -> String {
2168 Generator::sql(&self.build()).unwrap_or_default()
2169 }
2170}
2171
2172pub fn union(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2176 SetOpBuilder::new(SetOpKind::Union, left, right, false)
2177}
2178
2179pub fn union_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2183 SetOpBuilder::new(SetOpKind::Union, left, right, true)
2184}
2185
2186pub fn intersect(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2190 SetOpBuilder::new(SetOpKind::Intersect, left, right, false)
2191}
2192
2193pub fn intersect_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2197 SetOpBuilder::new(SetOpKind::Intersect, left, right, true)
2198}
2199
2200pub fn except_(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2204 SetOpBuilder::new(SetOpKind::Except, left, right, false)
2205}
2206
2207pub fn except_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2211 SetOpBuilder::new(SetOpKind::Except, left, right, true)
2212}
2213
2214pub struct WindowDefBuilder {
2239 partition_by: Vec<Expression>,
2240 order_by: Vec<Ordered>,
2241}
2242
2243impl WindowDefBuilder {
2244 pub fn new() -> Self {
2246 WindowDefBuilder {
2247 partition_by: Vec::new(),
2248 order_by: Vec::new(),
2249 }
2250 }
2251
2252 pub fn partition_by<I, E>(mut self, expressions: I) -> Self
2254 where
2255 I: IntoIterator<Item = E>,
2256 E: IntoExpr,
2257 {
2258 self.partition_by = expressions.into_iter().map(|e| e.into_expr().0).collect();
2259 self
2260 }
2261
2262 pub fn order_by<I, E>(mut self, expressions: I) -> Self
2267 where
2268 I: IntoIterator<Item = E>,
2269 E: IntoExpr,
2270 {
2271 self.order_by = expressions
2272 .into_iter()
2273 .map(|e| {
2274 let expr = e.into_expr().0;
2275 match expr {
2276 Expression::Ordered(o) => *o,
2277 other => Ordered {
2278 this: other,
2279 desc: false,
2280 nulls_first: None,
2281 explicit_asc: false,
2282 with_fill: None,
2283 },
2284 }
2285 })
2286 .collect();
2287 self
2288 }
2289}
2290
2291pub trait IntoExpr {
2310 fn into_expr(self) -> Expr;
2312}
2313
2314impl IntoExpr for Expr {
2315 fn into_expr(self) -> Expr {
2316 self
2317 }
2318}
2319
2320impl IntoExpr for &str {
2321 fn into_expr(self) -> Expr {
2323 col(self)
2324 }
2325}
2326
2327impl IntoExpr for String {
2328 fn into_expr(self) -> Expr {
2330 col(&self)
2331 }
2332}
2333
2334impl IntoExpr for Expression {
2335 fn into_expr(self) -> Expr {
2337 Expr(self)
2338 }
2339}
2340
2341pub trait IntoLiteral {
2356 fn into_literal(self) -> Expr;
2358}
2359
2360impl IntoLiteral for &str {
2361 fn into_literal(self) -> Expr {
2363 Expr(Expression::Literal(Box::new(Literal::String(
2364 self.to_string(),
2365 ))))
2366 }
2367}
2368
2369impl IntoLiteral for String {
2370 fn into_literal(self) -> Expr {
2372 Expr(Expression::Literal(Box::new(Literal::String(self))))
2373 }
2374}
2375
2376impl IntoLiteral for i64 {
2377 fn into_literal(self) -> Expr {
2379 Expr(Expression::Literal(Box::new(Literal::Number(
2380 self.to_string(),
2381 ))))
2382 }
2383}
2384
2385impl IntoLiteral for i32 {
2386 fn into_literal(self) -> Expr {
2388 Expr(Expression::Literal(Box::new(Literal::Number(
2389 self.to_string(),
2390 ))))
2391 }
2392}
2393
2394impl IntoLiteral for usize {
2395 fn into_literal(self) -> Expr {
2397 Expr(Expression::Literal(Box::new(Literal::Number(
2398 self.to_string(),
2399 ))))
2400 }
2401}
2402
2403impl IntoLiteral for f64 {
2404 fn into_literal(self) -> Expr {
2406 Expr(Expression::Literal(Box::new(Literal::Number(
2407 self.to_string(),
2408 ))))
2409 }
2410}
2411
2412impl IntoLiteral for bool {
2413 fn into_literal(self) -> Expr {
2415 Expr(Expression::Boolean(BooleanLiteral { value: self }))
2416 }
2417}
2418
2419fn binary_op(left: Expression, right: Expression) -> BinaryOp {
2424 BinaryOp {
2425 left,
2426 right,
2427 left_comments: Vec::new(),
2428 operator_comments: Vec::new(),
2429 trailing_comments: Vec::new(),
2430 inferred_type: None,
2431 }
2432}
2433
2434pub fn merge_into(target: &str) -> MergeBuilder {
2456 MergeBuilder {
2457 target: Expression::Table(Box::new(builder_table_ref(target))),
2458 using: None,
2459 on: None,
2460 whens: Vec::new(),
2461 }
2462}
2463
2464pub struct MergeBuilder {
2468 target: Expression,
2469 using: Option<Expression>,
2470 on: Option<Expression>,
2471 whens: Vec<Expression>,
2472}
2473
2474impl MergeBuilder {
2475 pub fn using(mut self, source: &str, on: Expr) -> Self {
2477 self.using = Some(Expression::Table(Box::new(builder_table_ref(source))));
2478 self.on = Some(on.0);
2479 self
2480 }
2481
2482 pub fn when_matched_update(mut self, assignments: Vec<(&str, Expr)>) -> Self {
2484 let eqs: Vec<Expression> = assignments
2485 .into_iter()
2486 .map(|(col_name, val)| {
2487 Expression::Eq(Box::new(BinaryOp {
2488 left: Expression::boxed_column(Column {
2489 name: builder_identifier(col_name),
2490 table: None,
2491 join_mark: false,
2492 trailing_comments: Vec::new(),
2493 span: None,
2494 inferred_type: None,
2495 }),
2496 right: val.0,
2497 left_comments: Vec::new(),
2498 operator_comments: Vec::new(),
2499 trailing_comments: Vec::new(),
2500 inferred_type: None,
2501 }))
2502 })
2503 .collect();
2504
2505 let action = Expression::Tuple(Box::new(Tuple {
2506 expressions: vec![
2507 Expression::Var(Box::new(Var {
2508 this: "UPDATE".to_string(),
2509 })),
2510 Expression::Tuple(Box::new(Tuple { expressions: eqs })),
2511 ],
2512 }));
2513
2514 let when = Expression::When(Box::new(When {
2515 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2516 value: true,
2517 }))),
2518 source: None,
2519 condition: None,
2520 then: Box::new(action),
2521 }));
2522 self.whens.push(when);
2523 self
2524 }
2525
2526 pub fn when_matched_update_where(
2528 mut self,
2529 condition: Expr,
2530 assignments: Vec<(&str, Expr)>,
2531 ) -> Self {
2532 let eqs: Vec<Expression> = assignments
2533 .into_iter()
2534 .map(|(col_name, val)| {
2535 Expression::Eq(Box::new(BinaryOp {
2536 left: Expression::boxed_column(Column {
2537 name: builder_identifier(col_name),
2538 table: None,
2539 join_mark: false,
2540 trailing_comments: Vec::new(),
2541 span: None,
2542 inferred_type: None,
2543 }),
2544 right: val.0,
2545 left_comments: Vec::new(),
2546 operator_comments: Vec::new(),
2547 trailing_comments: Vec::new(),
2548 inferred_type: None,
2549 }))
2550 })
2551 .collect();
2552
2553 let action = Expression::Tuple(Box::new(Tuple {
2554 expressions: vec![
2555 Expression::Var(Box::new(Var {
2556 this: "UPDATE".to_string(),
2557 })),
2558 Expression::Tuple(Box::new(Tuple { expressions: eqs })),
2559 ],
2560 }));
2561
2562 let when = Expression::When(Box::new(When {
2563 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2564 value: true,
2565 }))),
2566 source: None,
2567 condition: Some(Box::new(condition.0)),
2568 then: Box::new(action),
2569 }));
2570 self.whens.push(when);
2571 self
2572 }
2573
2574 pub fn when_matched_delete(mut self) -> Self {
2576 let action = Expression::Var(Box::new(Var {
2577 this: "DELETE".to_string(),
2578 }));
2579
2580 let when = Expression::When(Box::new(When {
2581 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2582 value: true,
2583 }))),
2584 source: None,
2585 condition: None,
2586 then: Box::new(action),
2587 }));
2588 self.whens.push(when);
2589 self
2590 }
2591
2592 pub fn when_not_matched_insert(mut self, columns: &[&str], values: Vec<Expr>) -> Self {
2594 let col_exprs: Vec<Expression> = columns
2595 .iter()
2596 .map(|c| {
2597 Expression::boxed_column(Column {
2598 name: builder_identifier(c),
2599 table: None,
2600 join_mark: false,
2601 trailing_comments: Vec::new(),
2602 span: None,
2603 inferred_type: None,
2604 })
2605 })
2606 .collect();
2607 let val_exprs: Vec<Expression> = values.into_iter().map(|v| v.0).collect();
2608
2609 let action = Expression::Tuple(Box::new(Tuple {
2610 expressions: vec![
2611 Expression::Var(Box::new(Var {
2612 this: "INSERT".to_string(),
2613 })),
2614 Expression::Tuple(Box::new(Tuple {
2615 expressions: col_exprs,
2616 })),
2617 Expression::Tuple(Box::new(Tuple {
2618 expressions: val_exprs,
2619 })),
2620 ],
2621 }));
2622
2623 let when = Expression::When(Box::new(When {
2624 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2625 value: false,
2626 }))),
2627 source: None,
2628 condition: None,
2629 then: Box::new(action),
2630 }));
2631 self.whens.push(when);
2632 self
2633 }
2634
2635 pub fn build(self) -> Expression {
2637 let whens_expr = Expression::Whens(Box::new(Whens {
2638 expressions: self.whens,
2639 }));
2640
2641 Expression::Merge(Box::new(Merge {
2642 this: Box::new(self.target),
2643 using: Box::new(
2644 self.using
2645 .unwrap_or(Expression::Null(crate::expressions::Null)),
2646 ),
2647 on: self.on.map(Box::new),
2648 using_cond: None,
2649 whens: Some(Box::new(whens_expr)),
2650 with_: None,
2651 returning: None,
2652 }))
2653 }
2654
2655 pub fn to_sql(self) -> String {
2657 Generator::sql(&self.build()).unwrap_or_default()
2658 }
2659}
2660
2661fn parse_simple_data_type(name: &str) -> DataType {
2662 let upper = name.trim().to_uppercase();
2663 match upper.as_str() {
2664 "INT" | "INTEGER" => DataType::Int {
2665 length: None,
2666 integer_spelling: upper == "INTEGER",
2667 },
2668 "BIGINT" => DataType::BigInt { length: None },
2669 "SMALLINT" => DataType::SmallInt { length: None },
2670 "TINYINT" => DataType::TinyInt { length: None },
2671 "FLOAT" => DataType::Float {
2672 precision: None,
2673 scale: None,
2674 real_spelling: false,
2675 },
2676 "DOUBLE" => DataType::Double {
2677 precision: None,
2678 scale: None,
2679 },
2680 "BOOLEAN" | "BOOL" => DataType::Boolean,
2681 "TEXT" => DataType::Text,
2682 "DATE" => DataType::Date,
2683 "TIMESTAMP" => DataType::Timestamp {
2684 precision: None,
2685 timezone: false,
2686 },
2687 "VARCHAR" => DataType::VarChar {
2688 length: None,
2689 parenthesized_length: false,
2690 },
2691 "CHAR" => DataType::Char { length: None },
2692 _ => {
2693 if let Ok(ast) =
2695 crate::parser::Parser::parse_sql(&format!("SELECT CAST(x AS {})", name))
2696 {
2697 if let Expression::Select(s) = &ast[0] {
2698 if let Some(Expression::Cast(c)) = s.expressions.first() {
2699 return c.to.clone();
2700 }
2701 }
2702 }
2703 DataType::Custom {
2705 name: name.to_string(),
2706 }
2707 }
2708 }
2709}
2710
2711#[cfg(test)]
2712mod tests {
2713 use super::*;
2714
2715 #[test]
2716 fn test_simple_select() {
2717 let sql = select(["id", "name"]).from("users").to_sql();
2718 assert_eq!(sql, "SELECT id, name FROM users");
2719 }
2720
2721 #[test]
2722 fn test_builder_quotes_unsafe_identifier_tokens() {
2723 let sql = select(["Name; DROP TABLE titanic"]).to_sql();
2724 assert_eq!(sql, r#"SELECT "Name; DROP TABLE titanic""#);
2725 }
2726
2727 #[test]
2728 fn test_builder_string_literal_requires_lit() {
2729 let sql = select([lit("Name; DROP TABLE titanic")]).to_sql();
2730 assert_eq!(sql, "SELECT 'Name; DROP TABLE titanic'");
2731 }
2732
2733 #[test]
2734 fn test_builder_quotes_unsafe_table_name_tokens() {
2735 let sql = select(["id"]).from("users; DROP TABLE x").to_sql();
2736 assert_eq!(sql, r#"SELECT id FROM "users; DROP TABLE x""#);
2737 }
2738
2739 #[test]
2740 fn test_select_star() {
2741 let sql = select([star()]).from("users").to_sql();
2742 assert_eq!(sql, "SELECT * FROM users");
2743 }
2744
2745 #[test]
2746 fn test_select_with_where() {
2747 let sql = select(["id", "name"])
2748 .from("users")
2749 .where_(col("age").gt(lit(18)))
2750 .to_sql();
2751 assert_eq!(sql, "SELECT id, name FROM users WHERE age > 18");
2752 }
2753
2754 #[test]
2755 fn test_select_with_join() {
2756 let sql = select(["u.id", "o.amount"])
2757 .from("users")
2758 .join("orders", col("u.id").eq(col("o.user_id")))
2759 .to_sql();
2760 assert_eq!(
2761 sql,
2762 "SELECT u.id, o.amount FROM users JOIN orders ON u.id = o.user_id"
2763 );
2764 }
2765
2766 #[test]
2767 fn test_select_with_group_by_having() {
2768 let sql = select([col("dept"), func("COUNT", [star()]).alias("cnt")])
2769 .from("employees")
2770 .group_by(["dept"])
2771 .having(func("COUNT", [star()]).gt(lit(5)))
2772 .to_sql();
2773 assert_eq!(
2774 sql,
2775 "SELECT dept, COUNT(*) AS cnt FROM employees GROUP BY dept HAVING COUNT(*) > 5"
2776 );
2777 }
2778
2779 #[test]
2780 fn test_select_with_order_limit_offset() {
2781 let sql = select(["id", "name"])
2782 .from("users")
2783 .order_by(["name"])
2784 .limit(10)
2785 .offset(20)
2786 .to_sql();
2787 assert_eq!(
2788 sql,
2789 "SELECT id, name FROM users ORDER BY name LIMIT 10 OFFSET 20"
2790 );
2791 }
2792
2793 #[test]
2794 fn test_select_distinct() {
2795 let sql = select(["name"]).from("users").distinct().to_sql();
2796 assert_eq!(sql, "SELECT DISTINCT name FROM users");
2797 }
2798
2799 #[test]
2800 fn test_insert_values() {
2801 let sql = insert_into("users")
2802 .columns(["id", "name"])
2803 .values([lit(1), lit("Alice")])
2804 .values([lit(2), lit("Bob")])
2805 .to_sql();
2806 assert_eq!(
2807 sql,
2808 "INSERT INTO users (id, name) VALUES (1, 'Alice'), (2, 'Bob')"
2809 );
2810 }
2811
2812 #[test]
2813 fn test_insert_select() {
2814 let sql = insert_into("archive")
2815 .columns(["id", "name"])
2816 .query(select(["id", "name"]).from("users"))
2817 .to_sql();
2818 assert_eq!(
2819 sql,
2820 "INSERT INTO archive (id, name) SELECT id, name FROM users"
2821 );
2822 }
2823
2824 #[test]
2825 fn test_update() {
2826 let sql = update("users")
2827 .set("name", lit("Bob"))
2828 .set("age", lit(30))
2829 .where_(col("id").eq(lit(1)))
2830 .to_sql();
2831 assert_eq!(sql, "UPDATE users SET name = 'Bob', age = 30 WHERE id = 1");
2832 }
2833
2834 #[test]
2835 fn test_delete() {
2836 let sql = delete("users").where_(col("id").eq(lit(1))).to_sql();
2837 assert_eq!(sql, "DELETE FROM users WHERE id = 1");
2838 }
2839
2840 #[test]
2841 fn test_complex_where() {
2842 let sql = select(["id"])
2843 .from("users")
2844 .where_(
2845 col("age")
2846 .gte(lit(18))
2847 .and(col("active").eq(boolean(true)))
2848 .and(col("name").like(lit("%test%"))),
2849 )
2850 .to_sql();
2851 assert_eq!(
2852 sql,
2853 "SELECT id FROM users WHERE age >= 18 AND active = TRUE AND name LIKE '%test%'"
2854 );
2855 }
2856
2857 #[test]
2858 fn test_in_list() {
2859 let sql = select(["id"])
2860 .from("users")
2861 .where_(col("status").in_list([lit("active"), lit("pending")]))
2862 .to_sql();
2863 assert_eq!(
2864 sql,
2865 "SELECT id FROM users WHERE status IN ('active', 'pending')"
2866 );
2867 }
2868
2869 #[test]
2870 fn test_between() {
2871 let sql = select(["id"])
2872 .from("orders")
2873 .where_(col("amount").between(lit(100), lit(500)))
2874 .to_sql();
2875 assert_eq!(
2876 sql,
2877 "SELECT id FROM orders WHERE amount BETWEEN 100 AND 500"
2878 );
2879 }
2880
2881 #[test]
2882 fn test_is_null() {
2883 let sql = select(["id"])
2884 .from("users")
2885 .where_(col("email").is_null())
2886 .to_sql();
2887 assert_eq!(sql, "SELECT id FROM users WHERE email IS NULL");
2888 }
2889
2890 #[test]
2891 fn test_arithmetic() {
2892 let sql = select([col("price").mul(col("quantity")).alias("total")])
2893 .from("items")
2894 .to_sql();
2895 assert_eq!(sql, "SELECT price * quantity AS total FROM items");
2896 }
2897
2898 #[test]
2899 fn test_cast() {
2900 let sql = select([col("id").cast("VARCHAR")]).from("users").to_sql();
2901 assert_eq!(sql, "SELECT CAST(id AS VARCHAR) FROM users");
2902 }
2903
2904 #[test]
2905 fn test_from_starter() {
2906 let sql = from("users").select_cols(["id", "name"]).to_sql();
2907 assert_eq!(sql, "SELECT id, name FROM users");
2908 }
2909
2910 #[test]
2911 fn test_qualified_column() {
2912 let sql = select([col("u.id"), col("u.name")]).from("users").to_sql();
2913 assert_eq!(sql, "SELECT u.id, u.name FROM users");
2914 }
2915
2916 #[test]
2917 fn test_nested_dot_column() {
2918 let sql = select([col("t.s.f")]).from("users").to_sql();
2919 assert_eq!(sql, "SELECT t.s.f FROM users");
2920 }
2921
2922 #[test]
2923 fn test_not_condition() {
2924 let sql = select(["id"])
2925 .from("users")
2926 .where_(not(col("active").eq(boolean(true))))
2927 .to_sql();
2928 assert_eq!(sql, "SELECT id FROM users WHERE NOT active = TRUE");
2929 }
2930
2931 #[test]
2932 fn test_order_by_desc() {
2933 let sql = select(["id", "name"])
2934 .from("users")
2935 .order_by([col("name").desc()])
2936 .to_sql();
2937 assert_eq!(sql, "SELECT id, name FROM users ORDER BY name DESC");
2938 }
2939
2940 #[test]
2941 fn test_left_join() {
2942 let sql = select(["u.id", "o.amount"])
2943 .from("users")
2944 .left_join("orders", col("u.id").eq(col("o.user_id")))
2945 .to_sql();
2946 assert_eq!(
2947 sql,
2948 "SELECT u.id, o.amount FROM users LEFT JOIN orders ON u.id = o.user_id"
2949 );
2950 }
2951
2952 #[test]
2953 fn test_build_returns_expression() {
2954 let expr = select(["id"]).from("users").build();
2955 assert!(matches!(expr, Expression::Select(_)));
2956 }
2957
2958 #[test]
2959 fn test_expr_interop() {
2960 let age_check = col("age").gt(lit(18));
2962 let sql = select([col("id"), age_check.alias("is_adult")])
2963 .from("users")
2964 .to_sql();
2965 assert_eq!(sql, "SELECT id, age > 18 AS is_adult FROM users");
2966 }
2967
2968 #[test]
2971 fn test_sql_expr_simple() {
2972 let expr = sql_expr("age > 18");
2973 let sql = select(["id"]).from("users").where_(expr).to_sql();
2974 assert_eq!(sql, "SELECT id FROM users WHERE age > 18");
2975 }
2976
2977 #[test]
2978 fn test_sql_expr_compound() {
2979 let expr = sql_expr("a > 1 AND b < 10");
2980 let sql = select(["*"]).from("t").where_(expr).to_sql();
2981 assert_eq!(sql, "SELECT * FROM t WHERE a > 1 AND b < 10");
2982 }
2983
2984 #[test]
2985 fn test_sql_expr_function() {
2986 let expr = sql_expr("COALESCE(a, b, 0)");
2987 let sql = select([expr.alias("val")]).from("t").to_sql();
2988 assert_eq!(sql, "SELECT COALESCE(a, b, 0) AS val FROM t");
2989 }
2990
2991 #[test]
2992 fn test_condition_alias() {
2993 let cond = condition("x > 0");
2994 let sql = select(["*"]).from("t").where_(cond).to_sql();
2995 assert_eq!(sql, "SELECT * FROM t WHERE x > 0");
2996 }
2997
2998 #[test]
3001 fn test_ilike() {
3002 let sql = select(["id"])
3003 .from("users")
3004 .where_(col("name").ilike(lit("%test%")))
3005 .to_sql();
3006 assert_eq!(sql, "SELECT id FROM users WHERE name ILIKE '%test%'");
3007 }
3008
3009 #[test]
3010 fn test_rlike() {
3011 let sql = select(["id"])
3012 .from("users")
3013 .where_(col("name").rlike(lit("^[A-Z]")))
3014 .to_sql();
3015 assert_eq!(
3016 sql,
3017 "SELECT id FROM users WHERE REGEXP_LIKE(name, '^[A-Z]')"
3018 );
3019 }
3020
3021 #[test]
3022 fn test_not_in() {
3023 let sql = select(["id"])
3024 .from("users")
3025 .where_(col("status").not_in([lit("deleted"), lit("banned")]))
3026 .to_sql();
3027 assert_eq!(
3028 sql,
3029 "SELECT id FROM users WHERE NOT status IN ('deleted', 'banned')"
3030 );
3031 }
3032
3033 #[test]
3036 fn test_case_searched() {
3037 let expr = case()
3038 .when(col("x").gt(lit(0)), lit("positive"))
3039 .when(col("x").eq(lit(0)), lit("zero"))
3040 .else_(lit("negative"))
3041 .build();
3042 let sql = select([expr.alias("label")]).from("t").to_sql();
3043 assert_eq!(
3044 sql,
3045 "SELECT CASE WHEN x > 0 THEN 'positive' WHEN x = 0 THEN 'zero' ELSE 'negative' END AS label FROM t"
3046 );
3047 }
3048
3049 #[test]
3050 fn test_case_simple() {
3051 let expr = case_of(col("status"))
3052 .when(lit(1), lit("active"))
3053 .when(lit(0), lit("inactive"))
3054 .build();
3055 let sql = select([expr.alias("status_label")]).from("t").to_sql();
3056 assert_eq!(
3057 sql,
3058 "SELECT CASE status WHEN 1 THEN 'active' WHEN 0 THEN 'inactive' END AS status_label FROM t"
3059 );
3060 }
3061
3062 #[test]
3063 fn test_case_no_else() {
3064 let expr = case().when(col("x").gt(lit(0)), lit("yes")).build();
3065 let sql = select([expr]).from("t").to_sql();
3066 assert_eq!(sql, "SELECT CASE WHEN x > 0 THEN 'yes' END FROM t");
3067 }
3068
3069 #[test]
3072 fn test_subquery_in_from() {
3073 let inner = select(["id", "name"])
3074 .from("users")
3075 .where_(col("active").eq(boolean(true)));
3076 let outer = select(["sub.id"])
3077 .from_expr(subquery(inner, "sub"))
3078 .to_sql();
3079 assert_eq!(
3080 outer,
3081 "SELECT sub.id FROM (SELECT id, name FROM users WHERE active = TRUE) AS sub"
3082 );
3083 }
3084
3085 #[test]
3086 fn test_subquery_in_join() {
3087 let inner = select([col("user_id"), func("SUM", [col("amount")]).alias("total")])
3088 .from("orders")
3089 .group_by(["user_id"]);
3090 let sql = select(["u.name", "o.total"])
3091 .from("users")
3092 .join("orders", col("u.id").eq(col("o.user_id")))
3093 .to_sql();
3094 assert!(sql.contains("JOIN"));
3095 let _sub = subquery(inner, "o");
3097 }
3098
3099 #[test]
3102 fn test_union() {
3103 let sql = union(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3104 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
3105 }
3106
3107 #[test]
3108 fn test_union_all() {
3109 let sql = union_all(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3110 assert_eq!(sql, "SELECT id FROM a UNION ALL SELECT id FROM b");
3111 }
3112
3113 #[test]
3114 fn test_intersect_builder() {
3115 let sql = intersect(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3116 assert_eq!(sql, "SELECT id FROM a INTERSECT SELECT id FROM b");
3117 }
3118
3119 #[test]
3120 fn test_except_builder() {
3121 let sql = except_(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3122 assert_eq!(sql, "SELECT id FROM a EXCEPT SELECT id FROM b");
3123 }
3124
3125 #[test]
3126 fn test_union_with_order_limit() {
3127 let sql = union(select(["id"]).from("a"), select(["id"]).from("b"))
3128 .order_by(["id"])
3129 .limit(10)
3130 .to_sql();
3131 assert!(sql.contains("UNION"));
3132 assert!(sql.contains("ORDER BY"));
3133 assert!(sql.contains("LIMIT"));
3134 }
3135
3136 #[test]
3137 fn test_select_builder_union() {
3138 let sql = select(["id"])
3139 .from("a")
3140 .union(select(["id"]).from("b"))
3141 .to_sql();
3142 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
3143 }
3144
3145 #[test]
3148 fn test_qualify() {
3149 let sql = select(["id", "name"])
3150 .from("users")
3151 .qualify(col("rn").eq(lit(1)))
3152 .to_sql();
3153 assert_eq!(sql, "SELECT id, name FROM users QUALIFY rn = 1");
3154 }
3155
3156 #[test]
3157 fn test_right_join() {
3158 let sql = select(["u.id", "o.amount"])
3159 .from("users")
3160 .right_join("orders", col("u.id").eq(col("o.user_id")))
3161 .to_sql();
3162 assert_eq!(
3163 sql,
3164 "SELECT u.id, o.amount FROM users RIGHT JOIN orders ON u.id = o.user_id"
3165 );
3166 }
3167
3168 #[test]
3169 fn test_cross_join() {
3170 let sql = select(["a.x", "b.y"]).from("a").cross_join("b").to_sql();
3171 assert_eq!(sql, "SELECT a.x, b.y FROM a CROSS JOIN b");
3172 }
3173
3174 #[test]
3175 fn test_lateral_view() {
3176 let sql = select(["id", "col_val"])
3177 .from("t")
3178 .lateral_view(func("EXPLODE", [col("arr")]), "lv", ["col_val"])
3179 .to_sql();
3180 assert!(sql.contains("LATERAL VIEW"));
3181 assert!(sql.contains("EXPLODE"));
3182 }
3183
3184 #[test]
3185 fn test_window_clause() {
3186 let sql = select(["id"])
3187 .from("t")
3188 .window(
3189 "w",
3190 WindowDefBuilder::new()
3191 .partition_by(["dept"])
3192 .order_by(["salary"]),
3193 )
3194 .to_sql();
3195 assert!(sql.contains("WINDOW"));
3196 assert!(sql.contains("PARTITION BY"));
3197 }
3198
3199 #[test]
3202 fn test_xor() {
3203 let sql = select(["*"])
3204 .from("t")
3205 .where_(col("a").xor(col("b")))
3206 .to_sql();
3207 assert_eq!(sql, "SELECT * FROM t WHERE a XOR b");
3208 }
3209
3210 #[test]
3213 fn test_for_update() {
3214 let sql = select(["id"]).from("t").for_update().to_sql();
3215 assert_eq!(sql, "SELECT id FROM t FOR UPDATE");
3216 }
3217
3218 #[test]
3219 fn test_for_share() {
3220 let sql = select(["id"]).from("t").for_share().to_sql();
3221 assert_eq!(sql, "SELECT id FROM t FOR SHARE");
3222 }
3223
3224 #[test]
3227 fn test_hint() {
3228 let sql = select(["*"]).from("t").hint("FULL(t)").to_sql();
3229 assert!(sql.contains("FULL(t)"), "Expected hint in: {}", sql);
3230 }
3231
3232 #[test]
3235 fn test_ctas() {
3236 let expr = select(["*"]).from("t").ctas("new_table");
3237 let sql = Generator::sql(&expr).unwrap();
3238 assert_eq!(sql, "CREATE TABLE new_table AS SELECT * FROM t");
3239 }
3240
3241 #[test]
3244 fn test_merge_update_insert() {
3245 let sql = merge_into("target")
3246 .using("source", col("target.id").eq(col("source.id")))
3247 .when_matched_update(vec![("name", col("source.name"))])
3248 .when_not_matched_insert(&["id", "name"], vec![col("source.id"), col("source.name")])
3249 .to_sql();
3250 assert!(
3251 sql.contains("MERGE INTO"),
3252 "Expected MERGE INTO in: {}",
3253 sql
3254 );
3255 assert!(sql.contains("USING"), "Expected USING in: {}", sql);
3256 assert!(
3257 sql.contains("WHEN MATCHED"),
3258 "Expected WHEN MATCHED in: {}",
3259 sql
3260 );
3261 assert!(
3262 sql.contains("UPDATE SET"),
3263 "Expected UPDATE SET in: {}",
3264 sql
3265 );
3266 assert!(
3267 sql.contains("WHEN NOT MATCHED"),
3268 "Expected WHEN NOT MATCHED in: {}",
3269 sql
3270 );
3271 assert!(sql.contains("INSERT"), "Expected INSERT in: {}", sql);
3272 }
3273
3274 #[test]
3275 fn test_merge_delete() {
3276 let sql = merge_into("target")
3277 .using("source", col("target.id").eq(col("source.id")))
3278 .when_matched_delete()
3279 .to_sql();
3280 assert!(
3281 sql.contains("MERGE INTO"),
3282 "Expected MERGE INTO in: {}",
3283 sql
3284 );
3285 assert!(
3286 sql.contains("WHEN MATCHED THEN DELETE"),
3287 "Expected WHEN MATCHED THEN DELETE in: {}",
3288 sql
3289 );
3290 }
3291
3292 #[test]
3293 fn test_merge_with_condition() {
3294 let sql = merge_into("target")
3295 .using("source", col("target.id").eq(col("source.id")))
3296 .when_matched_update_where(
3297 col("source.active").eq(boolean(true)),
3298 vec![("name", col("source.name"))],
3299 )
3300 .to_sql();
3301 assert!(
3302 sql.contains("MERGE INTO"),
3303 "Expected MERGE INTO in: {}",
3304 sql
3305 );
3306 assert!(
3307 sql.contains("AND source.active = TRUE"),
3308 "Expected condition in: {}",
3309 sql
3310 );
3311 }
3312}