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 if let Some((table, column)) = name.rsplit_once('.') {
138 Expr(Expression::boxed_column(Column {
139 name: builder_identifier(column),
140 table: Some(builder_identifier(table)),
141 join_mark: false,
142 trailing_comments: Vec::new(),
143 span: None,
144 inferred_type: None,
145 }))
146 } else {
147 Expr(Expression::boxed_column(Column {
148 name: builder_identifier(name),
149 table: None,
150 join_mark: false,
151 trailing_comments: Vec::new(),
152 span: None,
153 inferred_type: None,
154 }))
155 }
156}
157
158pub fn lit<V: IntoLiteral>(value: V) -> Expr {
174 value.into_literal()
175}
176
177pub fn star() -> Expr {
179 Expr(Expression::star())
180}
181
182pub fn null() -> Expr {
184 Expr(Expression::Null(Null))
185}
186
187pub fn boolean(value: bool) -> Expr {
189 Expr(Expression::Boolean(BooleanLiteral { value }))
190}
191
192pub fn table(name: &str) -> Expr {
209 Expr(Expression::Table(Box::new(builder_table_ref(name))))
210}
211
212pub fn func(name: &str, args: impl IntoIterator<Item = Expr>) -> Expr {
229 Expr(Expression::Function(Box::new(Function {
230 name: name.to_string(),
231 args: args.into_iter().map(|a| a.0).collect(),
232 ..Function::default()
233 })))
234}
235
236pub fn cast(expr: Expr, to: &str) -> Expr {
252 let data_type = parse_simple_data_type(to);
253 Expr(Expression::Cast(Box::new(Cast {
254 this: expr.0,
255 to: data_type,
256 trailing_comments: Vec::new(),
257 double_colon_syntax: false,
258 format: None,
259 default: None,
260 inferred_type: None,
261 })))
262}
263
264pub fn not(expr: Expr) -> Expr {
269 Expr(Expression::Not(Box::new(UnaryOp::new(expr.0))))
270}
271
272pub fn and(left: Expr, right: Expr) -> Expr {
277 left.and(right)
278}
279
280pub fn or(left: Expr, right: Expr) -> Expr {
285 left.or(right)
286}
287
288pub fn alias(expr: Expr, name: &str) -> Expr {
293 Expr(Expression::Alias(Box::new(Alias {
294 this: expr.0,
295 alias: builder_identifier(name),
296 column_aliases: Vec::new(),
297 pre_alias_comments: Vec::new(),
298 trailing_comments: Vec::new(),
299 inferred_type: None,
300 })))
301}
302
303pub fn sql_expr(sql: &str) -> Expr {
327 let wrapped = format!("SELECT {}", sql);
328 let ast = Parser::parse_sql(&wrapped).expect("sql_expr: failed to parse SQL expression");
329 if let Expression::Select(s) = &ast[0] {
330 if let Some(first) = s.expressions.first() {
331 return Expr(first.clone());
332 }
333 }
334 panic!("sql_expr: failed to extract expression from parsed SQL");
335}
336
337pub fn condition(sql: &str) -> Expr {
346 sql_expr(sql)
347}
348
349pub fn count(expr: Expr) -> Expr {
357 Expr(Expression::Count(Box::new(CountFunc {
358 this: Some(expr.0),
359 star: false,
360 distinct: false,
361 filter: None,
362 ignore_nulls: None,
363 original_name: None,
364 inferred_type: None,
365 })))
366}
367
368pub fn count_star() -> Expr {
370 Expr(Expression::Count(Box::new(CountFunc {
371 this: None,
372 star: true,
373 distinct: false,
374 filter: None,
375 ignore_nulls: None,
376 original_name: None,
377 inferred_type: None,
378 })))
379}
380
381pub fn count_distinct(expr: Expr) -> Expr {
383 Expr(Expression::Count(Box::new(CountFunc {
384 this: Some(expr.0),
385 star: false,
386 distinct: true,
387 filter: None,
388 ignore_nulls: None,
389 original_name: None,
390 inferred_type: None,
391 })))
392}
393
394pub fn sum(expr: Expr) -> Expr {
396 Expr(Expression::Sum(Box::new(AggFunc {
397 this: expr.0,
398 distinct: false,
399 filter: None,
400 order_by: vec![],
401 name: None,
402 ignore_nulls: None,
403 having_max: None,
404 limit: None,
405 inferred_type: None,
406 })))
407}
408
409pub fn avg(expr: Expr) -> Expr {
411 Expr(Expression::Avg(Box::new(AggFunc {
412 this: expr.0,
413 distinct: false,
414 filter: None,
415 order_by: vec![],
416 name: None,
417 ignore_nulls: None,
418 having_max: None,
419 limit: None,
420 inferred_type: None,
421 })))
422}
423
424pub fn min_(expr: Expr) -> Expr {
426 Expr(Expression::Min(Box::new(AggFunc {
427 this: expr.0,
428 distinct: false,
429 filter: None,
430 order_by: vec![],
431 name: None,
432 ignore_nulls: None,
433 having_max: None,
434 limit: None,
435 inferred_type: None,
436 })))
437}
438
439pub fn max_(expr: Expr) -> Expr {
441 Expr(Expression::Max(Box::new(AggFunc {
442 this: expr.0,
443 distinct: false,
444 filter: None,
445 order_by: vec![],
446 name: None,
447 ignore_nulls: None,
448 having_max: None,
449 limit: None,
450 inferred_type: None,
451 })))
452}
453
454pub fn approx_distinct(expr: Expr) -> Expr {
456 Expr(Expression::ApproxDistinct(Box::new(AggFunc {
457 this: expr.0,
458 distinct: false,
459 filter: None,
460 order_by: vec![],
461 name: None,
462 ignore_nulls: None,
463 having_max: None,
464 limit: None,
465 inferred_type: None,
466 })))
467}
468
469pub fn upper(expr: Expr) -> Expr {
473 Expr(Expression::Upper(Box::new(UnaryFunc::new(expr.0))))
474}
475
476pub fn lower(expr: Expr) -> Expr {
478 Expr(Expression::Lower(Box::new(UnaryFunc::new(expr.0))))
479}
480
481pub fn length(expr: Expr) -> Expr {
483 Expr(Expression::Length(Box::new(UnaryFunc::new(expr.0))))
484}
485
486pub fn trim(expr: Expr) -> Expr {
488 Expr(Expression::Trim(Box::new(TrimFunc {
489 this: expr.0,
490 characters: None,
491 position: TrimPosition::Both,
492 sql_standard_syntax: false,
493 position_explicit: false,
494 })))
495}
496
497pub fn ltrim(expr: Expr) -> Expr {
499 Expr(Expression::LTrim(Box::new(UnaryFunc::new(expr.0))))
500}
501
502pub fn rtrim(expr: Expr) -> Expr {
504 Expr(Expression::RTrim(Box::new(UnaryFunc::new(expr.0))))
505}
506
507pub fn reverse(expr: Expr) -> Expr {
509 Expr(Expression::Reverse(Box::new(UnaryFunc::new(expr.0))))
510}
511
512pub fn initcap(expr: Expr) -> Expr {
514 Expr(Expression::Initcap(Box::new(UnaryFunc::new(expr.0))))
515}
516
517pub fn substring(expr: Expr, start: Expr, len: Option<Expr>) -> Expr {
519 Expr(Expression::Substring(Box::new(SubstringFunc {
520 this: expr.0,
521 start: start.0,
522 length: len.map(|l| l.0),
523 from_for_syntax: false,
524 })))
525}
526
527pub fn replace_(expr: Expr, old: Expr, new: Expr) -> Expr {
530 Expr(Expression::Replace(Box::new(ReplaceFunc {
531 this: expr.0,
532 old: old.0,
533 new: new.0,
534 })))
535}
536
537pub fn concat_ws(separator: Expr, exprs: impl IntoIterator<Item = Expr>) -> Expr {
539 Expr(Expression::ConcatWs(Box::new(ConcatWs {
540 separator: separator.0,
541 expressions: exprs.into_iter().map(|e| e.0).collect(),
542 })))
543}
544
545pub fn coalesce(exprs: impl IntoIterator<Item = Expr>) -> Expr {
549 Expr(Expression::Coalesce(Box::new(VarArgFunc {
550 expressions: exprs.into_iter().map(|e| e.0).collect(),
551 original_name: None,
552 inferred_type: None,
553 })))
554}
555
556pub fn null_if(expr1: Expr, expr2: Expr) -> Expr {
558 Expr(Expression::NullIf(Box::new(BinaryFunc {
559 this: expr1.0,
560 expression: expr2.0,
561 original_name: None,
562 inferred_type: None,
563 })))
564}
565
566pub fn if_null(expr: Expr, fallback: Expr) -> Expr {
568 Expr(Expression::IfNull(Box::new(BinaryFunc {
569 this: expr.0,
570 expression: fallback.0,
571 original_name: None,
572 inferred_type: None,
573 })))
574}
575
576pub fn abs(expr: Expr) -> Expr {
580 Expr(Expression::Abs(Box::new(UnaryFunc::new(expr.0))))
581}
582
583pub fn round(expr: Expr, decimals: Option<Expr>) -> Expr {
585 Expr(Expression::Round(Box::new(RoundFunc {
586 this: expr.0,
587 decimals: decimals.map(|d| d.0),
588 })))
589}
590
591pub fn floor(expr: Expr) -> Expr {
593 Expr(Expression::Floor(Box::new(FloorFunc {
594 this: expr.0,
595 scale: None,
596 to: None,
597 })))
598}
599
600pub fn ceil(expr: Expr) -> Expr {
602 Expr(Expression::Ceil(Box::new(CeilFunc {
603 this: expr.0,
604 decimals: None,
605 to: None,
606 })))
607}
608
609pub fn power(base: Expr, exponent: Expr) -> Expr {
611 Expr(Expression::Power(Box::new(BinaryFunc {
612 this: base.0,
613 expression: exponent.0,
614 original_name: None,
615 inferred_type: None,
616 })))
617}
618
619pub fn sqrt(expr: Expr) -> Expr {
621 Expr(Expression::Sqrt(Box::new(UnaryFunc::new(expr.0))))
622}
623
624pub fn ln(expr: Expr) -> Expr {
626 Expr(Expression::Ln(Box::new(UnaryFunc::new(expr.0))))
627}
628
629pub fn exp_(expr: Expr) -> Expr {
631 Expr(Expression::Exp(Box::new(UnaryFunc::new(expr.0))))
632}
633
634pub fn sign(expr: Expr) -> Expr {
636 Expr(Expression::Sign(Box::new(UnaryFunc::new(expr.0))))
637}
638
639pub fn greatest(exprs: impl IntoIterator<Item = Expr>) -> Expr {
641 Expr(Expression::Greatest(Box::new(VarArgFunc {
642 expressions: exprs.into_iter().map(|e| e.0).collect(),
643 original_name: None,
644 inferred_type: None,
645 })))
646}
647
648pub fn least(exprs: impl IntoIterator<Item = Expr>) -> Expr {
650 Expr(Expression::Least(Box::new(VarArgFunc {
651 expressions: exprs.into_iter().map(|e| e.0).collect(),
652 original_name: None,
653 inferred_type: None,
654 })))
655}
656
657pub fn current_date_() -> Expr {
661 Expr(Expression::CurrentDate(CurrentDate))
662}
663
664pub fn current_time_() -> Expr {
666 Expr(Expression::CurrentTime(CurrentTime { precision: None }))
667}
668
669pub fn current_timestamp_() -> Expr {
671 Expr(Expression::CurrentTimestamp(CurrentTimestamp {
672 precision: None,
673 sysdate: false,
674 }))
675}
676
677pub fn extract_(field: &str, expr: Expr) -> Expr {
679 Expr(Expression::Extract(Box::new(ExtractFunc {
680 this: expr.0,
681 field: parse_datetime_field(field),
682 })))
683}
684
685fn parse_datetime_field(field: &str) -> DateTimeField {
687 match field.to_uppercase().as_str() {
688 "YEAR" => DateTimeField::Year,
689 "MONTH" => DateTimeField::Month,
690 "DAY" => DateTimeField::Day,
691 "HOUR" => DateTimeField::Hour,
692 "MINUTE" => DateTimeField::Minute,
693 "SECOND" => DateTimeField::Second,
694 "MILLISECOND" => DateTimeField::Millisecond,
695 "MICROSECOND" => DateTimeField::Microsecond,
696 "DOW" | "DAYOFWEEK" => DateTimeField::DayOfWeek,
697 "DOY" | "DAYOFYEAR" => DateTimeField::DayOfYear,
698 "WEEK" => DateTimeField::Week,
699 "QUARTER" => DateTimeField::Quarter,
700 "EPOCH" => DateTimeField::Epoch,
701 "TIMEZONE" => DateTimeField::Timezone,
702 "TIMEZONE_HOUR" => DateTimeField::TimezoneHour,
703 "TIMEZONE_MINUTE" => DateTimeField::TimezoneMinute,
704 "DATE" => DateTimeField::Date,
705 "TIME" => DateTimeField::Time,
706 other => DateTimeField::Custom(other.to_string()),
707 }
708}
709
710pub fn row_number() -> Expr {
714 Expr(Expression::RowNumber(RowNumber))
715}
716
717pub fn rank_() -> Expr {
719 Expr(Expression::Rank(Rank {
720 order_by: None,
721 args: vec![],
722 }))
723}
724
725pub fn dense_rank() -> Expr {
727 Expr(Expression::DenseRank(DenseRank { args: vec![] }))
728}
729
730pub fn select<I, E>(expressions: I) -> SelectBuilder
757where
758 I: IntoIterator<Item = E>,
759 E: IntoExpr,
760{
761 let mut builder = SelectBuilder::new();
762 for expr in expressions {
763 builder.select = builder.select.column(expr.into_expr().0);
764 }
765 builder
766}
767
768pub fn from(table_name: &str) -> SelectBuilder {
783 let mut builder = SelectBuilder::new();
784 builder.select.from = Some(From {
785 expressions: vec![Expression::Table(Box::new(builder_table_ref(table_name)))],
786 });
787 builder
788}
789
790pub fn delete(table_name: &str) -> DeleteBuilder {
803 DeleteBuilder {
804 delete: Delete {
805 table: builder_table_ref(table_name),
806 hint: None,
807 on_cluster: None,
808 alias: None,
809 alias_explicit_as: false,
810 using: Vec::new(),
811 where_clause: None,
812 output: None,
813 leading_comments: Vec::new(),
814 with: None,
815 limit: None,
816 order_by: None,
817 returning: Vec::new(),
818 tables: Vec::new(),
819 tables_from_using: false,
820 joins: Vec::new(),
821 force_index: None,
822 no_from: false,
823 },
824 }
825}
826
827pub fn insert_into(table_name: &str) -> InsertBuilder {
844 InsertBuilder {
845 insert: Insert {
846 table: builder_table_ref(table_name),
847 columns: Vec::new(),
848 values: Vec::new(),
849 query: None,
850 overwrite: false,
851 partition: Vec::new(),
852 directory: None,
853 returning: Vec::new(),
854 output: None,
855 on_conflict: None,
856 leading_comments: Vec::new(),
857 if_exists: false,
858 with: None,
859 ignore: false,
860 source_alias: None,
861 alias: None,
862 alias_explicit_as: false,
863 default_values: false,
864 by_name: false,
865 conflict_action: None,
866 is_replace: false,
867 hint: None,
868 replace_where: None,
869 source: None,
870 function_target: None,
871 partition_by: None,
872 settings: Vec::new(),
873 },
874 }
875}
876
877pub fn update(table_name: &str) -> UpdateBuilder {
895 UpdateBuilder {
896 update: Update {
897 table: builder_table_ref(table_name),
898 hint: None,
899 extra_tables: Vec::new(),
900 table_joins: Vec::new(),
901 set: Vec::new(),
902 from_clause: None,
903 from_joins: Vec::new(),
904 where_clause: None,
905 returning: Vec::new(),
906 output: None,
907 with: None,
908 leading_comments: Vec::new(),
909 limit: None,
910 order_by: None,
911 from_before_set: false,
912 },
913 }
914}
915
916#[derive(Debug, Clone)]
941pub struct Expr(pub Expression);
942
943impl Expr {
944 pub fn into_inner(self) -> Expression {
946 self.0
947 }
948
949 pub fn to_sql(&self) -> String {
953 Generator::sql(&self.0).unwrap_or_default()
954 }
955
956 pub fn eq(self, other: Expr) -> Expr {
960 Expr(Expression::Eq(Box::new(binary_op(self.0, other.0))))
961 }
962
963 pub fn neq(self, other: Expr) -> Expr {
965 Expr(Expression::Neq(Box::new(binary_op(self.0, other.0))))
966 }
967
968 pub fn lt(self, other: Expr) -> Expr {
970 Expr(Expression::Lt(Box::new(binary_op(self.0, other.0))))
971 }
972
973 pub fn lte(self, other: Expr) -> Expr {
975 Expr(Expression::Lte(Box::new(binary_op(self.0, other.0))))
976 }
977
978 pub fn gt(self, other: Expr) -> Expr {
980 Expr(Expression::Gt(Box::new(binary_op(self.0, other.0))))
981 }
982
983 pub fn gte(self, other: Expr) -> Expr {
985 Expr(Expression::Gte(Box::new(binary_op(self.0, other.0))))
986 }
987
988 pub fn and(self, other: Expr) -> Expr {
992 Expr(Expression::And(Box::new(binary_op(self.0, other.0))))
993 }
994
995 pub fn or(self, other: Expr) -> Expr {
997 Expr(Expression::Or(Box::new(binary_op(self.0, other.0))))
998 }
999
1000 pub fn not(self) -> Expr {
1002 Expr(Expression::Not(Box::new(UnaryOp::new(self.0))))
1003 }
1004
1005 pub fn xor(self, other: Expr) -> Expr {
1007 Expr(Expression::Xor(Box::new(Xor {
1008 this: Some(Box::new(self.0)),
1009 expression: Some(Box::new(other.0)),
1010 expressions: vec![],
1011 })))
1012 }
1013
1014 pub fn add(self, other: Expr) -> Expr {
1018 Expr(Expression::Add(Box::new(binary_op(self.0, other.0))))
1019 }
1020
1021 pub fn sub(self, other: Expr) -> Expr {
1023 Expr(Expression::Sub(Box::new(binary_op(self.0, other.0))))
1024 }
1025
1026 pub fn mul(self, other: Expr) -> Expr {
1028 Expr(Expression::Mul(Box::new(binary_op(self.0, other.0))))
1029 }
1030
1031 pub fn div(self, other: Expr) -> Expr {
1033 Expr(Expression::Div(Box::new(binary_op(self.0, other.0))))
1034 }
1035
1036 pub fn is_null(self) -> Expr {
1040 Expr(Expression::Is(Box::new(BinaryOp {
1041 left: self.0,
1042 right: Expression::Null(Null),
1043 left_comments: Vec::new(),
1044 operator_comments: Vec::new(),
1045 trailing_comments: Vec::new(),
1046 inferred_type: None,
1047 })))
1048 }
1049
1050 pub fn is_not_null(self) -> Expr {
1052 Expr(Expression::Not(Box::new(UnaryOp::new(Expression::Is(
1053 Box::new(BinaryOp {
1054 left: self.0,
1055 right: Expression::Null(Null),
1056 left_comments: Vec::new(),
1057 operator_comments: Vec::new(),
1058 trailing_comments: Vec::new(),
1059 inferred_type: None,
1060 }),
1061 )))))
1062 }
1063
1064 pub fn in_list(self, values: impl IntoIterator<Item = Expr>) -> Expr {
1068 Expr(Expression::In(Box::new(In {
1069 this: self.0,
1070 expressions: values.into_iter().map(|v| v.0).collect(),
1071 query: None,
1072 not: false,
1073 global: false,
1074 unnest: None,
1075 is_field: false,
1076 })))
1077 }
1078
1079 pub fn between(self, low: Expr, high: Expr) -> Expr {
1081 Expr(Expression::Between(Box::new(Between {
1082 this: self.0,
1083 low: low.0,
1084 high: high.0,
1085 not: false,
1086 symmetric: None,
1087 })))
1088 }
1089
1090 pub fn like(self, pattern: Expr) -> Expr {
1092 Expr(Expression::Like(Box::new(LikeOp {
1093 left: self.0,
1094 right: pattern.0,
1095 escape: None,
1096 quantifier: None,
1097 inferred_type: None,
1098 })))
1099 }
1100
1101 pub fn alias(self, name: &str) -> Expr {
1103 alias(self, name)
1104 }
1105
1106 pub fn cast(self, to: &str) -> Expr {
1110 cast(self, to)
1111 }
1112
1113 pub fn asc(self) -> Expr {
1118 Expr(Expression::Ordered(Box::new(Ordered {
1119 this: self.0,
1120 desc: false,
1121 nulls_first: None,
1122 explicit_asc: true,
1123 with_fill: None,
1124 })))
1125 }
1126
1127 pub fn desc(self) -> Expr {
1131 Expr(Expression::Ordered(Box::new(Ordered {
1132 this: self.0,
1133 desc: true,
1134 nulls_first: None,
1135 explicit_asc: false,
1136 with_fill: None,
1137 })))
1138 }
1139
1140 pub fn ilike(self, pattern: Expr) -> Expr {
1145 Expr(Expression::ILike(Box::new(LikeOp {
1146 left: self.0,
1147 right: pattern.0,
1148 escape: None,
1149 quantifier: None,
1150 inferred_type: None,
1151 })))
1152 }
1153
1154 pub fn rlike(self, pattern: Expr) -> Expr {
1159 Expr(Expression::RegexpLike(Box::new(RegexpFunc {
1160 this: self.0,
1161 pattern: pattern.0,
1162 flags: None,
1163 })))
1164 }
1165
1166 pub fn not_in(self, values: impl IntoIterator<Item = Expr>) -> Expr {
1170 Expr(Expression::In(Box::new(In {
1171 this: self.0,
1172 expressions: values.into_iter().map(|v| v.0).collect(),
1173 query: None,
1174 not: true,
1175 global: false,
1176 unnest: None,
1177 is_field: false,
1178 })))
1179 }
1180}
1181
1182pub struct SelectBuilder {
1208 select: Select,
1209}
1210
1211impl SelectBuilder {
1212 fn new() -> Self {
1213 SelectBuilder {
1214 select: Select::new(),
1215 }
1216 }
1217
1218 pub fn select_cols<I, E>(mut self, expressions: I) -> Self
1223 where
1224 I: IntoIterator<Item = E>,
1225 E: IntoExpr,
1226 {
1227 for expr in expressions {
1228 self.select.expressions.push(expr.into_expr().0);
1229 }
1230 self
1231 }
1232
1233 pub fn from(mut self, table_name: &str) -> Self {
1235 self.select.from = Some(From {
1236 expressions: vec![Expression::Table(Box::new(builder_table_ref(table_name)))],
1237 });
1238 self
1239 }
1240
1241 pub fn from_expr(mut self, expr: Expr) -> Self {
1246 self.select.from = Some(From {
1247 expressions: vec![expr.0],
1248 });
1249 self
1250 }
1251
1252 pub fn join(mut self, table_name: &str, on: Expr) -> Self {
1254 self.select.joins.push(Join {
1255 kind: JoinKind::Inner,
1256 this: Expression::Table(Box::new(builder_table_ref(table_name))),
1257 on: Some(on.0),
1258 using: Vec::new(),
1259 use_inner_keyword: false,
1260 use_outer_keyword: false,
1261 deferred_condition: false,
1262 join_hint: None,
1263 match_condition: None,
1264 pivots: Vec::new(),
1265 comments: Vec::new(),
1266 nesting_group: 0,
1267 directed: false,
1268 });
1269 self
1270 }
1271
1272 pub fn left_join(mut self, table_name: &str, on: Expr) -> Self {
1274 self.select.joins.push(Join {
1275 kind: JoinKind::Left,
1276 this: Expression::Table(Box::new(builder_table_ref(table_name))),
1277 on: Some(on.0),
1278 using: Vec::new(),
1279 use_inner_keyword: false,
1280 use_outer_keyword: false,
1281 deferred_condition: false,
1282 join_hint: None,
1283 match_condition: None,
1284 pivots: Vec::new(),
1285 comments: Vec::new(),
1286 nesting_group: 0,
1287 directed: false,
1288 });
1289 self
1290 }
1291
1292 pub fn where_(mut self, condition: Expr) -> Self {
1298 self.select.where_clause = Some(Where { this: condition.0 });
1299 self
1300 }
1301
1302 pub fn group_by<I, E>(mut self, expressions: I) -> Self
1304 where
1305 I: IntoIterator<Item = E>,
1306 E: IntoExpr,
1307 {
1308 self.select.group_by = Some(GroupBy {
1309 expressions: expressions.into_iter().map(|e| e.into_expr().0).collect(),
1310 all: None,
1311 totals: false,
1312 comments: Vec::new(),
1313 });
1314 self
1315 }
1316
1317 pub fn having(mut self, condition: Expr) -> Self {
1319 self.select.having = Some(Having {
1320 this: condition.0,
1321 comments: Vec::new(),
1322 });
1323 self
1324 }
1325
1326 pub fn order_by<I, E>(mut self, expressions: I) -> Self
1332 where
1333 I: IntoIterator<Item = E>,
1334 E: IntoExpr,
1335 {
1336 self.select.order_by = Some(OrderBy {
1337 siblings: false,
1338 comments: Vec::new(),
1339 expressions: expressions
1340 .into_iter()
1341 .map(|e| {
1342 let expr = e.into_expr().0;
1343 match expr {
1344 Expression::Ordered(_) => expr,
1345 other => Expression::Ordered(Box::new(Ordered {
1346 this: other,
1347 desc: false,
1348 nulls_first: None,
1349 explicit_asc: false,
1350 with_fill: None,
1351 })),
1352 }
1353 })
1354 .collect::<Vec<_>>()
1355 .into_iter()
1356 .map(|e| {
1357 if let Expression::Ordered(o) = e {
1358 *o
1359 } else {
1360 Ordered {
1361 this: e,
1362 desc: false,
1363 nulls_first: None,
1364 explicit_asc: false,
1365 with_fill: None,
1366 }
1367 }
1368 })
1369 .collect(),
1370 });
1371 self
1372 }
1373
1374 pub fn sort_by<I, E>(mut self, expressions: I) -> Self
1381 where
1382 I: IntoIterator<Item = E>,
1383 E: IntoExpr,
1384 {
1385 self.select.sort_by = Some(SortBy {
1386 expressions: expressions
1387 .into_iter()
1388 .map(|e| {
1389 let expr = e.into_expr().0;
1390 match expr {
1391 Expression::Ordered(o) => *o,
1392 other => Ordered {
1393 this: other,
1394 desc: false,
1395 nulls_first: None,
1396 explicit_asc: false,
1397 with_fill: None,
1398 },
1399 }
1400 })
1401 .collect(),
1402 });
1403 self
1404 }
1405
1406 pub fn limit(mut self, count: usize) -> Self {
1408 self.select.limit = Some(Limit {
1409 this: Expression::Literal(Box::new(Literal::Number(count.to_string()))),
1410 percent: false,
1411 comments: Vec::new(),
1412 });
1413 self
1414 }
1415
1416 pub fn offset(mut self, count: usize) -> Self {
1418 self.select.offset = Some(Offset {
1419 this: Expression::Literal(Box::new(Literal::Number(count.to_string()))),
1420 rows: None,
1421 });
1422 self
1423 }
1424
1425 pub fn distinct(mut self) -> Self {
1427 self.select.distinct = true;
1428 self
1429 }
1430
1431 pub fn qualify(mut self, condition: Expr) -> Self {
1436 self.select.qualify = Some(Qualify { this: condition.0 });
1437 self
1438 }
1439
1440 pub fn right_join(mut self, table_name: &str, on: Expr) -> Self {
1442 self.select.joins.push(Join {
1443 kind: JoinKind::Right,
1444 this: Expression::Table(Box::new(builder_table_ref(table_name))),
1445 on: Some(on.0),
1446 using: Vec::new(),
1447 use_inner_keyword: false,
1448 use_outer_keyword: false,
1449 deferred_condition: false,
1450 join_hint: None,
1451 match_condition: None,
1452 pivots: Vec::new(),
1453 comments: Vec::new(),
1454 nesting_group: 0,
1455 directed: false,
1456 });
1457 self
1458 }
1459
1460 pub fn cross_join(mut self, table_name: &str) -> Self {
1462 self.select.joins.push(Join {
1463 kind: JoinKind::Cross,
1464 this: Expression::Table(Box::new(builder_table_ref(table_name))),
1465 on: None,
1466 using: Vec::new(),
1467 use_inner_keyword: false,
1468 use_outer_keyword: false,
1469 deferred_condition: false,
1470 join_hint: None,
1471 match_condition: None,
1472 pivots: Vec::new(),
1473 comments: Vec::new(),
1474 nesting_group: 0,
1475 directed: false,
1476 });
1477 self
1478 }
1479
1480 pub fn lateral_view<S: AsRef<str>>(
1487 mut self,
1488 table_function: Expr,
1489 table_alias: &str,
1490 column_aliases: impl IntoIterator<Item = S>,
1491 ) -> Self {
1492 self.select.lateral_views.push(LateralView {
1493 this: table_function.0,
1494 table_alias: Some(builder_identifier(table_alias)),
1495 column_aliases: column_aliases
1496 .into_iter()
1497 .map(|c| builder_identifier(c.as_ref()))
1498 .collect(),
1499 outer: false,
1500 });
1501 self
1502 }
1503
1504 pub fn window(mut self, name: &str, def: WindowDefBuilder) -> Self {
1510 let named_window = NamedWindow {
1511 name: builder_identifier(name),
1512 spec: Over {
1513 window_name: None,
1514 partition_by: def.partition_by,
1515 order_by: def.order_by,
1516 frame: None,
1517 alias: None,
1518 },
1519 };
1520 match self.select.windows {
1521 Some(ref mut windows) => windows.push(named_window),
1522 None => self.select.windows = Some(vec![named_window]),
1523 }
1524 self
1525 }
1526
1527 pub fn for_update(mut self) -> Self {
1532 self.select.locks.push(Lock {
1533 update: Some(Box::new(Expression::Boolean(BooleanLiteral {
1534 value: true,
1535 }))),
1536 expressions: vec![],
1537 wait: None,
1538 key: None,
1539 });
1540 self
1541 }
1542
1543 pub fn for_share(mut self) -> Self {
1548 self.select.locks.push(Lock {
1549 update: None,
1550 expressions: vec![],
1551 wait: None,
1552 key: None,
1553 });
1554 self
1555 }
1556
1557 pub fn hint(mut self, hint_text: &str) -> Self {
1562 let hint_expr = HintExpression::Raw(hint_text.to_string());
1563 match &mut self.select.hint {
1564 Some(h) => h.expressions.push(hint_expr),
1565 None => {
1566 self.select.hint = Some(Hint {
1567 expressions: vec![hint_expr],
1568 })
1569 }
1570 }
1571 self
1572 }
1573
1574 pub fn ctas(self, table_name: &str) -> Expression {
1590 Expression::CreateTable(Box::new(CreateTable {
1591 name: builder_table_ref(table_name),
1592 on_cluster: None,
1593 columns: vec![],
1594 constraints: vec![],
1595 if_not_exists: false,
1596 temporary: false,
1597 or_replace: false,
1598 table_modifier: None,
1599 as_select: Some(self.build()),
1600 as_select_parenthesized: false,
1601 on_commit: None,
1602 clone_source: None,
1603 clone_at_clause: None,
1604 is_copy: false,
1605 shallow_clone: false,
1606 leading_comments: vec![],
1607 with_properties: vec![],
1608 teradata_post_name_options: vec![],
1609 with_data: None,
1610 with_statistics: None,
1611 teradata_indexes: vec![],
1612 with_cte: None,
1613 properties: vec![],
1614 partition_of: None,
1615 post_table_properties: vec![],
1616 mysql_table_options: vec![],
1617 inherits: vec![],
1618 on_property: None,
1619 copy_grants: false,
1620 using_template: None,
1621 rollup: None,
1622 uuid: None,
1623 with_partition_columns: vec![],
1624 with_connection: None,
1625 }))
1626 }
1627
1628 pub fn union(self, other: SelectBuilder) -> SetOpBuilder {
1632 SetOpBuilder::new(SetOpKind::Union, self, other, false)
1633 }
1634
1635 pub fn union_all(self, other: SelectBuilder) -> SetOpBuilder {
1639 SetOpBuilder::new(SetOpKind::Union, self, other, true)
1640 }
1641
1642 pub fn intersect(self, other: SelectBuilder) -> SetOpBuilder {
1646 SetOpBuilder::new(SetOpKind::Intersect, self, other, false)
1647 }
1648
1649 pub fn except_(self, other: SelectBuilder) -> SetOpBuilder {
1653 SetOpBuilder::new(SetOpKind::Except, self, other, false)
1654 }
1655
1656 pub fn build(self) -> Expression {
1658 Expression::Select(Box::new(self.select))
1659 }
1660
1661 pub fn to_sql(self) -> String {
1666 Generator::sql(&self.build()).unwrap_or_default()
1667 }
1668}
1669
1670pub struct DeleteBuilder {
1679 delete: Delete,
1680}
1681
1682impl DeleteBuilder {
1683 pub fn where_(mut self, condition: Expr) -> Self {
1685 self.delete.where_clause = Some(Where { this: condition.0 });
1686 self
1687 }
1688
1689 pub fn build(self) -> Expression {
1691 Expression::Delete(Box::new(self.delete))
1692 }
1693
1694 pub fn to_sql(self) -> String {
1696 Generator::sql(&self.build()).unwrap_or_default()
1697 }
1698}
1699
1700pub struct InsertBuilder {
1711 insert: Insert,
1712}
1713
1714impl InsertBuilder {
1715 pub fn columns<I, S>(mut self, columns: I) -> Self
1717 where
1718 I: IntoIterator<Item = S>,
1719 S: AsRef<str>,
1720 {
1721 self.insert.columns = columns
1722 .into_iter()
1723 .map(|c| builder_identifier(c.as_ref()))
1724 .collect();
1725 self
1726 }
1727
1728 pub fn values<I>(mut self, values: I) -> Self
1732 where
1733 I: IntoIterator<Item = Expr>,
1734 {
1735 self.insert
1736 .values
1737 .push(values.into_iter().map(|v| v.0).collect());
1738 self
1739 }
1740
1741 pub fn query(mut self, query: SelectBuilder) -> Self {
1745 self.insert.query = Some(query.build());
1746 self
1747 }
1748
1749 pub fn build(self) -> Expression {
1751 Expression::Insert(Box::new(self.insert))
1752 }
1753
1754 pub fn to_sql(self) -> String {
1756 Generator::sql(&self.build()).unwrap_or_default()
1757 }
1758}
1759
1760pub struct UpdateBuilder {
1770 update: Update,
1771}
1772
1773impl UpdateBuilder {
1774 pub fn set(mut self, column: &str, value: Expr) -> Self {
1778 self.update.set.push((builder_identifier(column), value.0));
1779 self
1780 }
1781
1782 pub fn where_(mut self, condition: Expr) -> Self {
1784 self.update.where_clause = Some(Where { this: condition.0 });
1785 self
1786 }
1787
1788 pub fn from(mut self, table_name: &str) -> Self {
1792 self.update.from_clause = Some(From {
1793 expressions: vec![Expression::Table(Box::new(builder_table_ref(table_name)))],
1794 });
1795 self
1796 }
1797
1798 pub fn build(self) -> Expression {
1800 Expression::Update(Box::new(self.update))
1801 }
1802
1803 pub fn to_sql(self) -> String {
1805 Generator::sql(&self.build()).unwrap_or_default()
1806 }
1807}
1808
1809pub fn case() -> CaseBuilder {
1834 CaseBuilder {
1835 operand: None,
1836 whens: Vec::new(),
1837 else_: None,
1838 }
1839}
1840
1841pub fn case_of(operand: Expr) -> CaseBuilder {
1862 CaseBuilder {
1863 operand: Some(operand.0),
1864 whens: Vec::new(),
1865 else_: None,
1866 }
1867}
1868
1869pub struct CaseBuilder {
1877 operand: Option<Expression>,
1878 whens: Vec<(Expression, Expression)>,
1879 else_: Option<Expression>,
1880}
1881
1882impl CaseBuilder {
1883 pub fn when(mut self, condition: Expr, result: Expr) -> Self {
1888 self.whens.push((condition.0, result.0));
1889 self
1890 }
1891
1892 pub fn else_(mut self, result: Expr) -> Self {
1897 self.else_ = Some(result.0);
1898 self
1899 }
1900
1901 pub fn build(self) -> Expr {
1903 Expr(self.build_expr())
1904 }
1905
1906 pub fn build_expr(self) -> Expression {
1911 Expression::Case(Box::new(Case {
1912 operand: self.operand,
1913 whens: self.whens,
1914 else_: self.else_,
1915 comments: Vec::new(),
1916 inferred_type: None,
1917 }))
1918 }
1919}
1920
1921pub fn subquery(query: SelectBuilder, alias_name: &str) -> Expr {
1945 subquery_expr(query.build(), alias_name)
1946}
1947
1948pub fn subquery_expr(expr: Expression, alias_name: &str) -> Expr {
1953 Expr(Expression::Subquery(Box::new(Subquery {
1954 this: expr,
1955 alias: Some(builder_identifier(alias_name)),
1956 column_aliases: Vec::new(),
1957 order_by: None,
1958 limit: None,
1959 offset: None,
1960 distribute_by: None,
1961 sort_by: None,
1962 cluster_by: None,
1963 lateral: false,
1964 modifiers_inside: true,
1965 trailing_comments: Vec::new(),
1966 inferred_type: None,
1967 })))
1968}
1969
1970#[derive(Debug, Clone, Copy)]
1976enum SetOpKind {
1977 Union,
1978 Intersect,
1979 Except,
1980}
1981
1982pub struct SetOpBuilder {
2003 kind: SetOpKind,
2004 left: Expression,
2005 right: Expression,
2006 all: bool,
2007 order_by: Option<OrderBy>,
2008 limit: Option<Box<Expression>>,
2009 offset: Option<Box<Expression>>,
2010}
2011
2012impl SetOpBuilder {
2013 fn new(kind: SetOpKind, left: SelectBuilder, right: SelectBuilder, all: bool) -> Self {
2014 SetOpBuilder {
2015 kind,
2016 left: left.build(),
2017 right: right.build(),
2018 all,
2019 order_by: None,
2020 limit: None,
2021 offset: None,
2022 }
2023 }
2024
2025 pub fn order_by<I, E>(mut self, expressions: I) -> Self
2030 where
2031 I: IntoIterator<Item = E>,
2032 E: IntoExpr,
2033 {
2034 self.order_by = Some(OrderBy {
2035 siblings: false,
2036 comments: Vec::new(),
2037 expressions: expressions
2038 .into_iter()
2039 .map(|e| {
2040 let expr = e.into_expr().0;
2041 match expr {
2042 Expression::Ordered(o) => *o,
2043 other => Ordered {
2044 this: other,
2045 desc: false,
2046 nulls_first: None,
2047 explicit_asc: false,
2048 with_fill: None,
2049 },
2050 }
2051 })
2052 .collect(),
2053 });
2054 self
2055 }
2056
2057 pub fn limit(mut self, count: usize) -> Self {
2059 self.limit = Some(Box::new(Expression::Literal(Box::new(Literal::Number(
2060 count.to_string(),
2061 )))));
2062 self
2063 }
2064
2065 pub fn offset(mut self, count: usize) -> Self {
2067 self.offset = Some(Box::new(Expression::Literal(Box::new(Literal::Number(
2068 count.to_string(),
2069 )))));
2070 self
2071 }
2072
2073 pub fn build(self) -> Expression {
2078 match self.kind {
2079 SetOpKind::Union => Expression::Union(Box::new(Union {
2080 left: self.left,
2081 right: self.right,
2082 all: self.all,
2083 distinct: false,
2084 with: None,
2085 order_by: self.order_by,
2086 limit: self.limit,
2087 offset: self.offset,
2088 distribute_by: None,
2089 sort_by: None,
2090 cluster_by: None,
2091 by_name: false,
2092 side: None,
2093 kind: None,
2094 corresponding: false,
2095 strict: false,
2096 on_columns: Vec::new(),
2097 })),
2098 SetOpKind::Intersect => Expression::Intersect(Box::new(Intersect {
2099 left: self.left,
2100 right: self.right,
2101 all: self.all,
2102 distinct: false,
2103 with: None,
2104 order_by: self.order_by,
2105 limit: self.limit,
2106 offset: self.offset,
2107 distribute_by: None,
2108 sort_by: None,
2109 cluster_by: None,
2110 by_name: false,
2111 side: None,
2112 kind: None,
2113 corresponding: false,
2114 strict: false,
2115 on_columns: Vec::new(),
2116 })),
2117 SetOpKind::Except => Expression::Except(Box::new(Except {
2118 left: self.left,
2119 right: self.right,
2120 all: self.all,
2121 distinct: false,
2122 with: None,
2123 order_by: self.order_by,
2124 limit: self.limit,
2125 offset: self.offset,
2126 distribute_by: None,
2127 sort_by: None,
2128 cluster_by: None,
2129 by_name: false,
2130 side: None,
2131 kind: None,
2132 corresponding: false,
2133 strict: false,
2134 on_columns: Vec::new(),
2135 })),
2136 }
2137 }
2138
2139 pub fn to_sql(self) -> String {
2141 Generator::sql(&self.build()).unwrap_or_default()
2142 }
2143}
2144
2145pub fn union(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2149 SetOpBuilder::new(SetOpKind::Union, left, right, false)
2150}
2151
2152pub fn union_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2156 SetOpBuilder::new(SetOpKind::Union, left, right, true)
2157}
2158
2159pub fn intersect(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2163 SetOpBuilder::new(SetOpKind::Intersect, left, right, false)
2164}
2165
2166pub fn intersect_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2170 SetOpBuilder::new(SetOpKind::Intersect, left, right, true)
2171}
2172
2173pub fn except_(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2177 SetOpBuilder::new(SetOpKind::Except, left, right, false)
2178}
2179
2180pub fn except_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2184 SetOpBuilder::new(SetOpKind::Except, left, right, true)
2185}
2186
2187pub struct WindowDefBuilder {
2212 partition_by: Vec<Expression>,
2213 order_by: Vec<Ordered>,
2214}
2215
2216impl WindowDefBuilder {
2217 pub fn new() -> Self {
2219 WindowDefBuilder {
2220 partition_by: Vec::new(),
2221 order_by: Vec::new(),
2222 }
2223 }
2224
2225 pub fn partition_by<I, E>(mut self, expressions: I) -> Self
2227 where
2228 I: IntoIterator<Item = E>,
2229 E: IntoExpr,
2230 {
2231 self.partition_by = expressions.into_iter().map(|e| e.into_expr().0).collect();
2232 self
2233 }
2234
2235 pub fn order_by<I, E>(mut self, expressions: I) -> Self
2240 where
2241 I: IntoIterator<Item = E>,
2242 E: IntoExpr,
2243 {
2244 self.order_by = expressions
2245 .into_iter()
2246 .map(|e| {
2247 let expr = e.into_expr().0;
2248 match expr {
2249 Expression::Ordered(o) => *o,
2250 other => Ordered {
2251 this: other,
2252 desc: false,
2253 nulls_first: None,
2254 explicit_asc: false,
2255 with_fill: None,
2256 },
2257 }
2258 })
2259 .collect();
2260 self
2261 }
2262}
2263
2264pub trait IntoExpr {
2283 fn into_expr(self) -> Expr;
2285}
2286
2287impl IntoExpr for Expr {
2288 fn into_expr(self) -> Expr {
2289 self
2290 }
2291}
2292
2293impl IntoExpr for &str {
2294 fn into_expr(self) -> Expr {
2296 col(self)
2297 }
2298}
2299
2300impl IntoExpr for String {
2301 fn into_expr(self) -> Expr {
2303 col(&self)
2304 }
2305}
2306
2307impl IntoExpr for Expression {
2308 fn into_expr(self) -> Expr {
2310 Expr(self)
2311 }
2312}
2313
2314pub trait IntoLiteral {
2329 fn into_literal(self) -> Expr;
2331}
2332
2333impl IntoLiteral for &str {
2334 fn into_literal(self) -> Expr {
2336 Expr(Expression::Literal(Box::new(Literal::String(
2337 self.to_string(),
2338 ))))
2339 }
2340}
2341
2342impl IntoLiteral for String {
2343 fn into_literal(self) -> Expr {
2345 Expr(Expression::Literal(Box::new(Literal::String(self))))
2346 }
2347}
2348
2349impl IntoLiteral for i64 {
2350 fn into_literal(self) -> Expr {
2352 Expr(Expression::Literal(Box::new(Literal::Number(
2353 self.to_string(),
2354 ))))
2355 }
2356}
2357
2358impl IntoLiteral for i32 {
2359 fn into_literal(self) -> Expr {
2361 Expr(Expression::Literal(Box::new(Literal::Number(
2362 self.to_string(),
2363 ))))
2364 }
2365}
2366
2367impl IntoLiteral for usize {
2368 fn into_literal(self) -> Expr {
2370 Expr(Expression::Literal(Box::new(Literal::Number(
2371 self.to_string(),
2372 ))))
2373 }
2374}
2375
2376impl IntoLiteral for f64 {
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 bool {
2386 fn into_literal(self) -> Expr {
2388 Expr(Expression::Boolean(BooleanLiteral { value: self }))
2389 }
2390}
2391
2392fn binary_op(left: Expression, right: Expression) -> BinaryOp {
2397 BinaryOp {
2398 left,
2399 right,
2400 left_comments: Vec::new(),
2401 operator_comments: Vec::new(),
2402 trailing_comments: Vec::new(),
2403 inferred_type: None,
2404 }
2405}
2406
2407pub fn merge_into(target: &str) -> MergeBuilder {
2429 MergeBuilder {
2430 target: Expression::Table(Box::new(builder_table_ref(target))),
2431 using: None,
2432 on: None,
2433 whens: Vec::new(),
2434 }
2435}
2436
2437pub struct MergeBuilder {
2441 target: Expression,
2442 using: Option<Expression>,
2443 on: Option<Expression>,
2444 whens: Vec<Expression>,
2445}
2446
2447impl MergeBuilder {
2448 pub fn using(mut self, source: &str, on: Expr) -> Self {
2450 self.using = Some(Expression::Table(Box::new(builder_table_ref(source))));
2451 self.on = Some(on.0);
2452 self
2453 }
2454
2455 pub fn when_matched_update(mut self, assignments: Vec<(&str, Expr)>) -> Self {
2457 let eqs: Vec<Expression> = assignments
2458 .into_iter()
2459 .map(|(col_name, val)| {
2460 Expression::Eq(Box::new(BinaryOp {
2461 left: Expression::boxed_column(Column {
2462 name: builder_identifier(col_name),
2463 table: None,
2464 join_mark: false,
2465 trailing_comments: Vec::new(),
2466 span: None,
2467 inferred_type: None,
2468 }),
2469 right: val.0,
2470 left_comments: Vec::new(),
2471 operator_comments: Vec::new(),
2472 trailing_comments: Vec::new(),
2473 inferred_type: None,
2474 }))
2475 })
2476 .collect();
2477
2478 let action = Expression::Tuple(Box::new(Tuple {
2479 expressions: vec![
2480 Expression::Var(Box::new(Var {
2481 this: "UPDATE".to_string(),
2482 })),
2483 Expression::Tuple(Box::new(Tuple { expressions: eqs })),
2484 ],
2485 }));
2486
2487 let when = Expression::When(Box::new(When {
2488 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2489 value: true,
2490 }))),
2491 source: None,
2492 condition: None,
2493 then: Box::new(action),
2494 }));
2495 self.whens.push(when);
2496 self
2497 }
2498
2499 pub fn when_matched_update_where(
2501 mut self,
2502 condition: Expr,
2503 assignments: Vec<(&str, Expr)>,
2504 ) -> Self {
2505 let eqs: Vec<Expression> = assignments
2506 .into_iter()
2507 .map(|(col_name, val)| {
2508 Expression::Eq(Box::new(BinaryOp {
2509 left: Expression::boxed_column(Column {
2510 name: builder_identifier(col_name),
2511 table: None,
2512 join_mark: false,
2513 trailing_comments: Vec::new(),
2514 span: None,
2515 inferred_type: None,
2516 }),
2517 right: val.0,
2518 left_comments: Vec::new(),
2519 operator_comments: Vec::new(),
2520 trailing_comments: Vec::new(),
2521 inferred_type: None,
2522 }))
2523 })
2524 .collect();
2525
2526 let action = Expression::Tuple(Box::new(Tuple {
2527 expressions: vec![
2528 Expression::Var(Box::new(Var {
2529 this: "UPDATE".to_string(),
2530 })),
2531 Expression::Tuple(Box::new(Tuple { expressions: eqs })),
2532 ],
2533 }));
2534
2535 let when = Expression::When(Box::new(When {
2536 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2537 value: true,
2538 }))),
2539 source: None,
2540 condition: Some(Box::new(condition.0)),
2541 then: Box::new(action),
2542 }));
2543 self.whens.push(when);
2544 self
2545 }
2546
2547 pub fn when_matched_delete(mut self) -> Self {
2549 let action = Expression::Var(Box::new(Var {
2550 this: "DELETE".to_string(),
2551 }));
2552
2553 let when = Expression::When(Box::new(When {
2554 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2555 value: true,
2556 }))),
2557 source: None,
2558 condition: None,
2559 then: Box::new(action),
2560 }));
2561 self.whens.push(when);
2562 self
2563 }
2564
2565 pub fn when_not_matched_insert(mut self, columns: &[&str], values: Vec<Expr>) -> Self {
2567 let col_exprs: Vec<Expression> = columns
2568 .iter()
2569 .map(|c| {
2570 Expression::boxed_column(Column {
2571 name: builder_identifier(c),
2572 table: None,
2573 join_mark: false,
2574 trailing_comments: Vec::new(),
2575 span: None,
2576 inferred_type: None,
2577 })
2578 })
2579 .collect();
2580 let val_exprs: Vec<Expression> = values.into_iter().map(|v| v.0).collect();
2581
2582 let action = Expression::Tuple(Box::new(Tuple {
2583 expressions: vec![
2584 Expression::Var(Box::new(Var {
2585 this: "INSERT".to_string(),
2586 })),
2587 Expression::Tuple(Box::new(Tuple {
2588 expressions: col_exprs,
2589 })),
2590 Expression::Tuple(Box::new(Tuple {
2591 expressions: val_exprs,
2592 })),
2593 ],
2594 }));
2595
2596 let when = Expression::When(Box::new(When {
2597 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2598 value: false,
2599 }))),
2600 source: None,
2601 condition: None,
2602 then: Box::new(action),
2603 }));
2604 self.whens.push(when);
2605 self
2606 }
2607
2608 pub fn build(self) -> Expression {
2610 let whens_expr = Expression::Whens(Box::new(Whens {
2611 expressions: self.whens,
2612 }));
2613
2614 Expression::Merge(Box::new(Merge {
2615 this: Box::new(self.target),
2616 using: Box::new(
2617 self.using
2618 .unwrap_or(Expression::Null(crate::expressions::Null)),
2619 ),
2620 on: self.on.map(Box::new),
2621 using_cond: None,
2622 whens: Some(Box::new(whens_expr)),
2623 with_: None,
2624 returning: None,
2625 }))
2626 }
2627
2628 pub fn to_sql(self) -> String {
2630 Generator::sql(&self.build()).unwrap_or_default()
2631 }
2632}
2633
2634fn parse_simple_data_type(name: &str) -> DataType {
2635 let upper = name.trim().to_uppercase();
2636 match upper.as_str() {
2637 "INT" | "INTEGER" => DataType::Int {
2638 length: None,
2639 integer_spelling: upper == "INTEGER",
2640 },
2641 "BIGINT" => DataType::BigInt { length: None },
2642 "SMALLINT" => DataType::SmallInt { length: None },
2643 "TINYINT" => DataType::TinyInt { length: None },
2644 "FLOAT" => DataType::Float {
2645 precision: None,
2646 scale: None,
2647 real_spelling: false,
2648 },
2649 "DOUBLE" => DataType::Double {
2650 precision: None,
2651 scale: None,
2652 },
2653 "BOOLEAN" | "BOOL" => DataType::Boolean,
2654 "TEXT" => DataType::Text,
2655 "DATE" => DataType::Date,
2656 "TIMESTAMP" => DataType::Timestamp {
2657 precision: None,
2658 timezone: false,
2659 },
2660 "VARCHAR" => DataType::VarChar {
2661 length: None,
2662 parenthesized_length: false,
2663 },
2664 "CHAR" => DataType::Char { length: None },
2665 _ => {
2666 if let Ok(ast) =
2668 crate::parser::Parser::parse_sql(&format!("SELECT CAST(x AS {})", name))
2669 {
2670 if let Expression::Select(s) = &ast[0] {
2671 if let Some(Expression::Cast(c)) = s.expressions.first() {
2672 return c.to.clone();
2673 }
2674 }
2675 }
2676 DataType::Custom {
2678 name: name.to_string(),
2679 }
2680 }
2681 }
2682}
2683
2684#[cfg(test)]
2685mod tests {
2686 use super::*;
2687
2688 #[test]
2689 fn test_simple_select() {
2690 let sql = select(["id", "name"]).from("users").to_sql();
2691 assert_eq!(sql, "SELECT id, name FROM users");
2692 }
2693
2694 #[test]
2695 fn test_builder_quotes_unsafe_identifier_tokens() {
2696 let sql = select(["Name; DROP TABLE titanic"]).to_sql();
2697 assert_eq!(sql, r#"SELECT "Name; DROP TABLE titanic""#);
2698 }
2699
2700 #[test]
2701 fn test_builder_string_literal_requires_lit() {
2702 let sql = select([lit("Name; DROP TABLE titanic")]).to_sql();
2703 assert_eq!(sql, "SELECT 'Name; DROP TABLE titanic'");
2704 }
2705
2706 #[test]
2707 fn test_builder_quotes_unsafe_table_name_tokens() {
2708 let sql = select(["id"]).from("users; DROP TABLE x").to_sql();
2709 assert_eq!(sql, r#"SELECT id FROM "users; DROP TABLE x""#);
2710 }
2711
2712 #[test]
2713 fn test_select_star() {
2714 let sql = select([star()]).from("users").to_sql();
2715 assert_eq!(sql, "SELECT * FROM users");
2716 }
2717
2718 #[test]
2719 fn test_select_with_where() {
2720 let sql = select(["id", "name"])
2721 .from("users")
2722 .where_(col("age").gt(lit(18)))
2723 .to_sql();
2724 assert_eq!(sql, "SELECT id, name FROM users WHERE age > 18");
2725 }
2726
2727 #[test]
2728 fn test_select_with_join() {
2729 let sql = select(["u.id", "o.amount"])
2730 .from("users")
2731 .join("orders", col("u.id").eq(col("o.user_id")))
2732 .to_sql();
2733 assert_eq!(
2734 sql,
2735 "SELECT u.id, o.amount FROM users JOIN orders ON u.id = o.user_id"
2736 );
2737 }
2738
2739 #[test]
2740 fn test_select_with_group_by_having() {
2741 let sql = select([col("dept"), func("COUNT", [star()]).alias("cnt")])
2742 .from("employees")
2743 .group_by(["dept"])
2744 .having(func("COUNT", [star()]).gt(lit(5)))
2745 .to_sql();
2746 assert_eq!(
2747 sql,
2748 "SELECT dept, COUNT(*) AS cnt FROM employees GROUP BY dept HAVING COUNT(*) > 5"
2749 );
2750 }
2751
2752 #[test]
2753 fn test_select_with_order_limit_offset() {
2754 let sql = select(["id", "name"])
2755 .from("users")
2756 .order_by(["name"])
2757 .limit(10)
2758 .offset(20)
2759 .to_sql();
2760 assert_eq!(
2761 sql,
2762 "SELECT id, name FROM users ORDER BY name LIMIT 10 OFFSET 20"
2763 );
2764 }
2765
2766 #[test]
2767 fn test_select_distinct() {
2768 let sql = select(["name"]).from("users").distinct().to_sql();
2769 assert_eq!(sql, "SELECT DISTINCT name FROM users");
2770 }
2771
2772 #[test]
2773 fn test_insert_values() {
2774 let sql = insert_into("users")
2775 .columns(["id", "name"])
2776 .values([lit(1), lit("Alice")])
2777 .values([lit(2), lit("Bob")])
2778 .to_sql();
2779 assert_eq!(
2780 sql,
2781 "INSERT INTO users (id, name) VALUES (1, 'Alice'), (2, 'Bob')"
2782 );
2783 }
2784
2785 #[test]
2786 fn test_insert_select() {
2787 let sql = insert_into("archive")
2788 .columns(["id", "name"])
2789 .query(select(["id", "name"]).from("users"))
2790 .to_sql();
2791 assert_eq!(
2792 sql,
2793 "INSERT INTO archive (id, name) SELECT id, name FROM users"
2794 );
2795 }
2796
2797 #[test]
2798 fn test_update() {
2799 let sql = update("users")
2800 .set("name", lit("Bob"))
2801 .set("age", lit(30))
2802 .where_(col("id").eq(lit(1)))
2803 .to_sql();
2804 assert_eq!(sql, "UPDATE users SET name = 'Bob', age = 30 WHERE id = 1");
2805 }
2806
2807 #[test]
2808 fn test_delete() {
2809 let sql = delete("users").where_(col("id").eq(lit(1))).to_sql();
2810 assert_eq!(sql, "DELETE FROM users WHERE id = 1");
2811 }
2812
2813 #[test]
2814 fn test_complex_where() {
2815 let sql = select(["id"])
2816 .from("users")
2817 .where_(
2818 col("age")
2819 .gte(lit(18))
2820 .and(col("active").eq(boolean(true)))
2821 .and(col("name").like(lit("%test%"))),
2822 )
2823 .to_sql();
2824 assert_eq!(
2825 sql,
2826 "SELECT id FROM users WHERE age >= 18 AND active = TRUE AND name LIKE '%test%'"
2827 );
2828 }
2829
2830 #[test]
2831 fn test_in_list() {
2832 let sql = select(["id"])
2833 .from("users")
2834 .where_(col("status").in_list([lit("active"), lit("pending")]))
2835 .to_sql();
2836 assert_eq!(
2837 sql,
2838 "SELECT id FROM users WHERE status IN ('active', 'pending')"
2839 );
2840 }
2841
2842 #[test]
2843 fn test_between() {
2844 let sql = select(["id"])
2845 .from("orders")
2846 .where_(col("amount").between(lit(100), lit(500)))
2847 .to_sql();
2848 assert_eq!(
2849 sql,
2850 "SELECT id FROM orders WHERE amount BETWEEN 100 AND 500"
2851 );
2852 }
2853
2854 #[test]
2855 fn test_is_null() {
2856 let sql = select(["id"])
2857 .from("users")
2858 .where_(col("email").is_null())
2859 .to_sql();
2860 assert_eq!(sql, "SELECT id FROM users WHERE email IS NULL");
2861 }
2862
2863 #[test]
2864 fn test_arithmetic() {
2865 let sql = select([col("price").mul(col("quantity")).alias("total")])
2866 .from("items")
2867 .to_sql();
2868 assert_eq!(sql, "SELECT price * quantity AS total FROM items");
2869 }
2870
2871 #[test]
2872 fn test_cast() {
2873 let sql = select([col("id").cast("VARCHAR")]).from("users").to_sql();
2874 assert_eq!(sql, "SELECT CAST(id AS VARCHAR) FROM users");
2875 }
2876
2877 #[test]
2878 fn test_from_starter() {
2879 let sql = from("users").select_cols(["id", "name"]).to_sql();
2880 assert_eq!(sql, "SELECT id, name FROM users");
2881 }
2882
2883 #[test]
2884 fn test_qualified_column() {
2885 let sql = select([col("u.id"), col("u.name")]).from("users").to_sql();
2886 assert_eq!(sql, "SELECT u.id, u.name FROM users");
2887 }
2888
2889 #[test]
2890 fn test_not_condition() {
2891 let sql = select(["id"])
2892 .from("users")
2893 .where_(not(col("active").eq(boolean(true))))
2894 .to_sql();
2895 assert_eq!(sql, "SELECT id FROM users WHERE NOT active = TRUE");
2896 }
2897
2898 #[test]
2899 fn test_order_by_desc() {
2900 let sql = select(["id", "name"])
2901 .from("users")
2902 .order_by([col("name").desc()])
2903 .to_sql();
2904 assert_eq!(sql, "SELECT id, name FROM users ORDER BY name DESC");
2905 }
2906
2907 #[test]
2908 fn test_left_join() {
2909 let sql = select(["u.id", "o.amount"])
2910 .from("users")
2911 .left_join("orders", col("u.id").eq(col("o.user_id")))
2912 .to_sql();
2913 assert_eq!(
2914 sql,
2915 "SELECT u.id, o.amount FROM users LEFT JOIN orders ON u.id = o.user_id"
2916 );
2917 }
2918
2919 #[test]
2920 fn test_build_returns_expression() {
2921 let expr = select(["id"]).from("users").build();
2922 assert!(matches!(expr, Expression::Select(_)));
2923 }
2924
2925 #[test]
2926 fn test_expr_interop() {
2927 let age_check = col("age").gt(lit(18));
2929 let sql = select([col("id"), age_check.alias("is_adult")])
2930 .from("users")
2931 .to_sql();
2932 assert_eq!(sql, "SELECT id, age > 18 AS is_adult FROM users");
2933 }
2934
2935 #[test]
2938 fn test_sql_expr_simple() {
2939 let expr = sql_expr("age > 18");
2940 let sql = select(["id"]).from("users").where_(expr).to_sql();
2941 assert_eq!(sql, "SELECT id FROM users WHERE age > 18");
2942 }
2943
2944 #[test]
2945 fn test_sql_expr_compound() {
2946 let expr = sql_expr("a > 1 AND b < 10");
2947 let sql = select(["*"]).from("t").where_(expr).to_sql();
2948 assert_eq!(sql, "SELECT * FROM t WHERE a > 1 AND b < 10");
2949 }
2950
2951 #[test]
2952 fn test_sql_expr_function() {
2953 let expr = sql_expr("COALESCE(a, b, 0)");
2954 let sql = select([expr.alias("val")]).from("t").to_sql();
2955 assert_eq!(sql, "SELECT COALESCE(a, b, 0) AS val FROM t");
2956 }
2957
2958 #[test]
2959 fn test_condition_alias() {
2960 let cond = condition("x > 0");
2961 let sql = select(["*"]).from("t").where_(cond).to_sql();
2962 assert_eq!(sql, "SELECT * FROM t WHERE x > 0");
2963 }
2964
2965 #[test]
2968 fn test_ilike() {
2969 let sql = select(["id"])
2970 .from("users")
2971 .where_(col("name").ilike(lit("%test%")))
2972 .to_sql();
2973 assert_eq!(sql, "SELECT id FROM users WHERE name ILIKE '%test%'");
2974 }
2975
2976 #[test]
2977 fn test_rlike() {
2978 let sql = select(["id"])
2979 .from("users")
2980 .where_(col("name").rlike(lit("^[A-Z]")))
2981 .to_sql();
2982 assert_eq!(
2983 sql,
2984 "SELECT id FROM users WHERE REGEXP_LIKE(name, '^[A-Z]')"
2985 );
2986 }
2987
2988 #[test]
2989 fn test_not_in() {
2990 let sql = select(["id"])
2991 .from("users")
2992 .where_(col("status").not_in([lit("deleted"), lit("banned")]))
2993 .to_sql();
2994 assert_eq!(
2995 sql,
2996 "SELECT id FROM users WHERE NOT status IN ('deleted', 'banned')"
2997 );
2998 }
2999
3000 #[test]
3003 fn test_case_searched() {
3004 let expr = case()
3005 .when(col("x").gt(lit(0)), lit("positive"))
3006 .when(col("x").eq(lit(0)), lit("zero"))
3007 .else_(lit("negative"))
3008 .build();
3009 let sql = select([expr.alias("label")]).from("t").to_sql();
3010 assert_eq!(
3011 sql,
3012 "SELECT CASE WHEN x > 0 THEN 'positive' WHEN x = 0 THEN 'zero' ELSE 'negative' END AS label FROM t"
3013 );
3014 }
3015
3016 #[test]
3017 fn test_case_simple() {
3018 let expr = case_of(col("status"))
3019 .when(lit(1), lit("active"))
3020 .when(lit(0), lit("inactive"))
3021 .build();
3022 let sql = select([expr.alias("status_label")]).from("t").to_sql();
3023 assert_eq!(
3024 sql,
3025 "SELECT CASE status WHEN 1 THEN 'active' WHEN 0 THEN 'inactive' END AS status_label FROM t"
3026 );
3027 }
3028
3029 #[test]
3030 fn test_case_no_else() {
3031 let expr = case().when(col("x").gt(lit(0)), lit("yes")).build();
3032 let sql = select([expr]).from("t").to_sql();
3033 assert_eq!(sql, "SELECT CASE WHEN x > 0 THEN 'yes' END FROM t");
3034 }
3035
3036 #[test]
3039 fn test_subquery_in_from() {
3040 let inner = select(["id", "name"])
3041 .from("users")
3042 .where_(col("active").eq(boolean(true)));
3043 let outer = select(["sub.id"])
3044 .from_expr(subquery(inner, "sub"))
3045 .to_sql();
3046 assert_eq!(
3047 outer,
3048 "SELECT sub.id FROM (SELECT id, name FROM users WHERE active = TRUE) AS sub"
3049 );
3050 }
3051
3052 #[test]
3053 fn test_subquery_in_join() {
3054 let inner = select([col("user_id"), func("SUM", [col("amount")]).alias("total")])
3055 .from("orders")
3056 .group_by(["user_id"]);
3057 let sql = select(["u.name", "o.total"])
3058 .from("users")
3059 .join("orders", col("u.id").eq(col("o.user_id")))
3060 .to_sql();
3061 assert!(sql.contains("JOIN"));
3062 let _sub = subquery(inner, "o");
3064 }
3065
3066 #[test]
3069 fn test_union() {
3070 let sql = union(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3071 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
3072 }
3073
3074 #[test]
3075 fn test_union_all() {
3076 let sql = union_all(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3077 assert_eq!(sql, "SELECT id FROM a UNION ALL SELECT id FROM b");
3078 }
3079
3080 #[test]
3081 fn test_intersect_builder() {
3082 let sql = intersect(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3083 assert_eq!(sql, "SELECT id FROM a INTERSECT SELECT id FROM b");
3084 }
3085
3086 #[test]
3087 fn test_except_builder() {
3088 let sql = except_(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3089 assert_eq!(sql, "SELECT id FROM a EXCEPT SELECT id FROM b");
3090 }
3091
3092 #[test]
3093 fn test_union_with_order_limit() {
3094 let sql = union(select(["id"]).from("a"), select(["id"]).from("b"))
3095 .order_by(["id"])
3096 .limit(10)
3097 .to_sql();
3098 assert!(sql.contains("UNION"));
3099 assert!(sql.contains("ORDER BY"));
3100 assert!(sql.contains("LIMIT"));
3101 }
3102
3103 #[test]
3104 fn test_select_builder_union() {
3105 let sql = select(["id"])
3106 .from("a")
3107 .union(select(["id"]).from("b"))
3108 .to_sql();
3109 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
3110 }
3111
3112 #[test]
3115 fn test_qualify() {
3116 let sql = select(["id", "name"])
3117 .from("users")
3118 .qualify(col("rn").eq(lit(1)))
3119 .to_sql();
3120 assert_eq!(sql, "SELECT id, name FROM users QUALIFY rn = 1");
3121 }
3122
3123 #[test]
3124 fn test_right_join() {
3125 let sql = select(["u.id", "o.amount"])
3126 .from("users")
3127 .right_join("orders", col("u.id").eq(col("o.user_id")))
3128 .to_sql();
3129 assert_eq!(
3130 sql,
3131 "SELECT u.id, o.amount FROM users RIGHT JOIN orders ON u.id = o.user_id"
3132 );
3133 }
3134
3135 #[test]
3136 fn test_cross_join() {
3137 let sql = select(["a.x", "b.y"]).from("a").cross_join("b").to_sql();
3138 assert_eq!(sql, "SELECT a.x, b.y FROM a CROSS JOIN b");
3139 }
3140
3141 #[test]
3142 fn test_lateral_view() {
3143 let sql = select(["id", "col_val"])
3144 .from("t")
3145 .lateral_view(func("EXPLODE", [col("arr")]), "lv", ["col_val"])
3146 .to_sql();
3147 assert!(sql.contains("LATERAL VIEW"));
3148 assert!(sql.contains("EXPLODE"));
3149 }
3150
3151 #[test]
3152 fn test_window_clause() {
3153 let sql = select(["id"])
3154 .from("t")
3155 .window(
3156 "w",
3157 WindowDefBuilder::new()
3158 .partition_by(["dept"])
3159 .order_by(["salary"]),
3160 )
3161 .to_sql();
3162 assert!(sql.contains("WINDOW"));
3163 assert!(sql.contains("PARTITION BY"));
3164 }
3165
3166 #[test]
3169 fn test_xor() {
3170 let sql = select(["*"])
3171 .from("t")
3172 .where_(col("a").xor(col("b")))
3173 .to_sql();
3174 assert_eq!(sql, "SELECT * FROM t WHERE a XOR b");
3175 }
3176
3177 #[test]
3180 fn test_for_update() {
3181 let sql = select(["id"]).from("t").for_update().to_sql();
3182 assert_eq!(sql, "SELECT id FROM t FOR UPDATE");
3183 }
3184
3185 #[test]
3186 fn test_for_share() {
3187 let sql = select(["id"]).from("t").for_share().to_sql();
3188 assert_eq!(sql, "SELECT id FROM t FOR SHARE");
3189 }
3190
3191 #[test]
3194 fn test_hint() {
3195 let sql = select(["*"]).from("t").hint("FULL(t)").to_sql();
3196 assert!(sql.contains("FULL(t)"), "Expected hint in: {}", sql);
3197 }
3198
3199 #[test]
3202 fn test_ctas() {
3203 let expr = select(["*"]).from("t").ctas("new_table");
3204 let sql = Generator::sql(&expr).unwrap();
3205 assert_eq!(sql, "CREATE TABLE new_table AS SELECT * FROM t");
3206 }
3207
3208 #[test]
3211 fn test_merge_update_insert() {
3212 let sql = merge_into("target")
3213 .using("source", col("target.id").eq(col("source.id")))
3214 .when_matched_update(vec![("name", col("source.name"))])
3215 .when_not_matched_insert(&["id", "name"], vec![col("source.id"), col("source.name")])
3216 .to_sql();
3217 assert!(
3218 sql.contains("MERGE INTO"),
3219 "Expected MERGE INTO in: {}",
3220 sql
3221 );
3222 assert!(sql.contains("USING"), "Expected USING in: {}", sql);
3223 assert!(
3224 sql.contains("WHEN MATCHED"),
3225 "Expected WHEN MATCHED in: {}",
3226 sql
3227 );
3228 assert!(
3229 sql.contains("UPDATE SET"),
3230 "Expected UPDATE SET in: {}",
3231 sql
3232 );
3233 assert!(
3234 sql.contains("WHEN NOT MATCHED"),
3235 "Expected WHEN NOT MATCHED in: {}",
3236 sql
3237 );
3238 assert!(sql.contains("INSERT"), "Expected INSERT in: {}", sql);
3239 }
3240
3241 #[test]
3242 fn test_merge_delete() {
3243 let sql = merge_into("target")
3244 .using("source", col("target.id").eq(col("source.id")))
3245 .when_matched_delete()
3246 .to_sql();
3247 assert!(
3248 sql.contains("MERGE INTO"),
3249 "Expected MERGE INTO in: {}",
3250 sql
3251 );
3252 assert!(
3253 sql.contains("WHEN MATCHED THEN DELETE"),
3254 "Expected WHEN MATCHED THEN DELETE in: {}",
3255 sql
3256 );
3257 }
3258
3259 #[test]
3260 fn test_merge_with_condition() {
3261 let sql = merge_into("target")
3262 .using("source", col("target.id").eq(col("source.id")))
3263 .when_matched_update_where(
3264 col("source.active").eq(boolean(true)),
3265 vec![("name", col("source.name"))],
3266 )
3267 .to_sql();
3268 assert!(
3269 sql.contains("MERGE INTO"),
3270 "Expected MERGE INTO in: {}",
3271 sql
3272 );
3273 assert!(
3274 sql.contains("AND source.active = TRUE"),
3275 "Expected condition in: {}",
3276 sql
3277 );
3278 }
3279}