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 deep_clone: false,
1607 leading_comments: vec![],
1608 with_properties: vec![],
1609 teradata_post_name_options: vec![],
1610 with_data: None,
1611 with_statistics: None,
1612 teradata_indexes: vec![],
1613 with_cte: None,
1614 properties: vec![],
1615 partition_of: None,
1616 post_table_properties: vec![],
1617 mysql_table_options: vec![],
1618 inherits: vec![],
1619 on_property: None,
1620 copy_grants: false,
1621 using_template: None,
1622 rollup: None,
1623 uuid: None,
1624 with_partition_columns: vec![],
1625 with_connection: None,
1626 }))
1627 }
1628
1629 pub fn union(self, other: SelectBuilder) -> SetOpBuilder {
1633 SetOpBuilder::new(SetOpKind::Union, self, other, false)
1634 }
1635
1636 pub fn union_all(self, other: SelectBuilder) -> SetOpBuilder {
1640 SetOpBuilder::new(SetOpKind::Union, self, other, true)
1641 }
1642
1643 pub fn intersect(self, other: SelectBuilder) -> SetOpBuilder {
1647 SetOpBuilder::new(SetOpKind::Intersect, self, other, false)
1648 }
1649
1650 pub fn except_(self, other: SelectBuilder) -> SetOpBuilder {
1654 SetOpBuilder::new(SetOpKind::Except, self, other, false)
1655 }
1656
1657 pub fn build(self) -> Expression {
1659 Expression::Select(Box::new(self.select))
1660 }
1661
1662 pub fn to_sql(self) -> String {
1667 Generator::sql(&self.build()).unwrap_or_default()
1668 }
1669}
1670
1671pub struct DeleteBuilder {
1680 delete: Delete,
1681}
1682
1683impl DeleteBuilder {
1684 pub fn where_(mut self, condition: Expr) -> Self {
1686 self.delete.where_clause = Some(Where { this: condition.0 });
1687 self
1688 }
1689
1690 pub fn build(self) -> Expression {
1692 Expression::Delete(Box::new(self.delete))
1693 }
1694
1695 pub fn to_sql(self) -> String {
1697 Generator::sql(&self.build()).unwrap_or_default()
1698 }
1699}
1700
1701pub struct InsertBuilder {
1712 insert: Insert,
1713}
1714
1715impl InsertBuilder {
1716 pub fn columns<I, S>(mut self, columns: I) -> Self
1718 where
1719 I: IntoIterator<Item = S>,
1720 S: AsRef<str>,
1721 {
1722 self.insert.columns = columns
1723 .into_iter()
1724 .map(|c| builder_identifier(c.as_ref()))
1725 .collect();
1726 self
1727 }
1728
1729 pub fn values<I>(mut self, values: I) -> Self
1733 where
1734 I: IntoIterator<Item = Expr>,
1735 {
1736 self.insert
1737 .values
1738 .push(values.into_iter().map(|v| v.0).collect());
1739 self
1740 }
1741
1742 pub fn query(mut self, query: SelectBuilder) -> Self {
1746 self.insert.query = Some(query.build());
1747 self
1748 }
1749
1750 pub fn build(self) -> Expression {
1752 Expression::Insert(Box::new(self.insert))
1753 }
1754
1755 pub fn to_sql(self) -> String {
1757 Generator::sql(&self.build()).unwrap_or_default()
1758 }
1759}
1760
1761pub struct UpdateBuilder {
1771 update: Update,
1772}
1773
1774impl UpdateBuilder {
1775 pub fn set(mut self, column: &str, value: Expr) -> Self {
1779 self.update.set.push((builder_identifier(column), value.0));
1780 self
1781 }
1782
1783 pub fn where_(mut self, condition: Expr) -> Self {
1785 self.update.where_clause = Some(Where { this: condition.0 });
1786 self
1787 }
1788
1789 pub fn from(mut self, table_name: &str) -> Self {
1793 self.update.from_clause = Some(From {
1794 expressions: vec![Expression::Table(Box::new(builder_table_ref(table_name)))],
1795 });
1796 self
1797 }
1798
1799 pub fn build(self) -> Expression {
1801 Expression::Update(Box::new(self.update))
1802 }
1803
1804 pub fn to_sql(self) -> String {
1806 Generator::sql(&self.build()).unwrap_or_default()
1807 }
1808}
1809
1810pub fn case() -> CaseBuilder {
1835 CaseBuilder {
1836 operand: None,
1837 whens: Vec::new(),
1838 else_: None,
1839 }
1840}
1841
1842pub fn case_of(operand: Expr) -> CaseBuilder {
1863 CaseBuilder {
1864 operand: Some(operand.0),
1865 whens: Vec::new(),
1866 else_: None,
1867 }
1868}
1869
1870pub struct CaseBuilder {
1878 operand: Option<Expression>,
1879 whens: Vec<(Expression, Expression)>,
1880 else_: Option<Expression>,
1881}
1882
1883impl CaseBuilder {
1884 pub fn when(mut self, condition: Expr, result: Expr) -> Self {
1889 self.whens.push((condition.0, result.0));
1890 self
1891 }
1892
1893 pub fn else_(mut self, result: Expr) -> Self {
1898 self.else_ = Some(result.0);
1899 self
1900 }
1901
1902 pub fn build(self) -> Expr {
1904 Expr(self.build_expr())
1905 }
1906
1907 pub fn build_expr(self) -> Expression {
1912 Expression::Case(Box::new(Case {
1913 operand: self.operand,
1914 whens: self.whens,
1915 else_: self.else_,
1916 comments: Vec::new(),
1917 inferred_type: None,
1918 }))
1919 }
1920}
1921
1922pub fn subquery(query: SelectBuilder, alias_name: &str) -> Expr {
1946 subquery_expr(query.build(), alias_name)
1947}
1948
1949pub fn subquery_expr(expr: Expression, alias_name: &str) -> Expr {
1954 Expr(Expression::Subquery(Box::new(Subquery {
1955 this: expr,
1956 alias: Some(builder_identifier(alias_name)),
1957 column_aliases: Vec::new(),
1958 order_by: None,
1959 limit: None,
1960 offset: None,
1961 distribute_by: None,
1962 sort_by: None,
1963 cluster_by: None,
1964 lateral: false,
1965 modifiers_inside: true,
1966 trailing_comments: Vec::new(),
1967 inferred_type: None,
1968 })))
1969}
1970
1971#[derive(Debug, Clone, Copy)]
1977enum SetOpKind {
1978 Union,
1979 Intersect,
1980 Except,
1981}
1982
1983pub struct SetOpBuilder {
2004 kind: SetOpKind,
2005 left: Expression,
2006 right: Expression,
2007 all: bool,
2008 order_by: Option<OrderBy>,
2009 limit: Option<Box<Expression>>,
2010 offset: Option<Box<Expression>>,
2011}
2012
2013impl SetOpBuilder {
2014 fn new(kind: SetOpKind, left: SelectBuilder, right: SelectBuilder, all: bool) -> Self {
2015 SetOpBuilder {
2016 kind,
2017 left: left.build(),
2018 right: right.build(),
2019 all,
2020 order_by: None,
2021 limit: None,
2022 offset: None,
2023 }
2024 }
2025
2026 pub fn order_by<I, E>(mut self, expressions: I) -> Self
2031 where
2032 I: IntoIterator<Item = E>,
2033 E: IntoExpr,
2034 {
2035 self.order_by = Some(OrderBy {
2036 siblings: false,
2037 comments: Vec::new(),
2038 expressions: expressions
2039 .into_iter()
2040 .map(|e| {
2041 let expr = e.into_expr().0;
2042 match expr {
2043 Expression::Ordered(o) => *o,
2044 other => Ordered {
2045 this: other,
2046 desc: false,
2047 nulls_first: None,
2048 explicit_asc: false,
2049 with_fill: None,
2050 },
2051 }
2052 })
2053 .collect(),
2054 });
2055 self
2056 }
2057
2058 pub fn limit(mut self, count: usize) -> Self {
2060 self.limit = Some(Box::new(Expression::Literal(Box::new(Literal::Number(
2061 count.to_string(),
2062 )))));
2063 self
2064 }
2065
2066 pub fn offset(mut self, count: usize) -> Self {
2068 self.offset = Some(Box::new(Expression::Literal(Box::new(Literal::Number(
2069 count.to_string(),
2070 )))));
2071 self
2072 }
2073
2074 pub fn build(self) -> Expression {
2079 match self.kind {
2080 SetOpKind::Union => Expression::Union(Box::new(Union {
2081 left: self.left,
2082 right: self.right,
2083 all: self.all,
2084 distinct: false,
2085 with: None,
2086 order_by: self.order_by,
2087 limit: self.limit,
2088 offset: self.offset,
2089 distribute_by: None,
2090 sort_by: None,
2091 cluster_by: None,
2092 by_name: false,
2093 side: None,
2094 kind: None,
2095 corresponding: false,
2096 strict: false,
2097 on_columns: Vec::new(),
2098 })),
2099 SetOpKind::Intersect => Expression::Intersect(Box::new(Intersect {
2100 left: self.left,
2101 right: self.right,
2102 all: self.all,
2103 distinct: false,
2104 with: None,
2105 order_by: self.order_by,
2106 limit: self.limit,
2107 offset: self.offset,
2108 distribute_by: None,
2109 sort_by: None,
2110 cluster_by: None,
2111 by_name: false,
2112 side: None,
2113 kind: None,
2114 corresponding: false,
2115 strict: false,
2116 on_columns: Vec::new(),
2117 })),
2118 SetOpKind::Except => Expression::Except(Box::new(Except {
2119 left: self.left,
2120 right: self.right,
2121 all: self.all,
2122 distinct: false,
2123 with: None,
2124 order_by: self.order_by,
2125 limit: self.limit,
2126 offset: self.offset,
2127 distribute_by: None,
2128 sort_by: None,
2129 cluster_by: None,
2130 by_name: false,
2131 side: None,
2132 kind: None,
2133 corresponding: false,
2134 strict: false,
2135 on_columns: Vec::new(),
2136 })),
2137 }
2138 }
2139
2140 pub fn to_sql(self) -> String {
2142 Generator::sql(&self.build()).unwrap_or_default()
2143 }
2144}
2145
2146pub fn union(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2150 SetOpBuilder::new(SetOpKind::Union, left, right, false)
2151}
2152
2153pub fn union_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2157 SetOpBuilder::new(SetOpKind::Union, left, right, true)
2158}
2159
2160pub fn intersect(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2164 SetOpBuilder::new(SetOpKind::Intersect, left, right, false)
2165}
2166
2167pub fn intersect_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2171 SetOpBuilder::new(SetOpKind::Intersect, left, right, true)
2172}
2173
2174pub fn except_(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2178 SetOpBuilder::new(SetOpKind::Except, left, right, false)
2179}
2180
2181pub fn except_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2185 SetOpBuilder::new(SetOpKind::Except, left, right, true)
2186}
2187
2188pub struct WindowDefBuilder {
2213 partition_by: Vec<Expression>,
2214 order_by: Vec<Ordered>,
2215}
2216
2217impl WindowDefBuilder {
2218 pub fn new() -> Self {
2220 WindowDefBuilder {
2221 partition_by: Vec::new(),
2222 order_by: Vec::new(),
2223 }
2224 }
2225
2226 pub fn partition_by<I, E>(mut self, expressions: I) -> Self
2228 where
2229 I: IntoIterator<Item = E>,
2230 E: IntoExpr,
2231 {
2232 self.partition_by = expressions.into_iter().map(|e| e.into_expr().0).collect();
2233 self
2234 }
2235
2236 pub fn order_by<I, E>(mut self, expressions: I) -> Self
2241 where
2242 I: IntoIterator<Item = E>,
2243 E: IntoExpr,
2244 {
2245 self.order_by = expressions
2246 .into_iter()
2247 .map(|e| {
2248 let expr = e.into_expr().0;
2249 match expr {
2250 Expression::Ordered(o) => *o,
2251 other => Ordered {
2252 this: other,
2253 desc: false,
2254 nulls_first: None,
2255 explicit_asc: false,
2256 with_fill: None,
2257 },
2258 }
2259 })
2260 .collect();
2261 self
2262 }
2263}
2264
2265pub trait IntoExpr {
2284 fn into_expr(self) -> Expr;
2286}
2287
2288impl IntoExpr for Expr {
2289 fn into_expr(self) -> Expr {
2290 self
2291 }
2292}
2293
2294impl IntoExpr for &str {
2295 fn into_expr(self) -> Expr {
2297 col(self)
2298 }
2299}
2300
2301impl IntoExpr for String {
2302 fn into_expr(self) -> Expr {
2304 col(&self)
2305 }
2306}
2307
2308impl IntoExpr for Expression {
2309 fn into_expr(self) -> Expr {
2311 Expr(self)
2312 }
2313}
2314
2315pub trait IntoLiteral {
2330 fn into_literal(self) -> Expr;
2332}
2333
2334impl IntoLiteral for &str {
2335 fn into_literal(self) -> Expr {
2337 Expr(Expression::Literal(Box::new(Literal::String(
2338 self.to_string(),
2339 ))))
2340 }
2341}
2342
2343impl IntoLiteral for String {
2344 fn into_literal(self) -> Expr {
2346 Expr(Expression::Literal(Box::new(Literal::String(self))))
2347 }
2348}
2349
2350impl IntoLiteral for i64 {
2351 fn into_literal(self) -> Expr {
2353 Expr(Expression::Literal(Box::new(Literal::Number(
2354 self.to_string(),
2355 ))))
2356 }
2357}
2358
2359impl IntoLiteral for i32 {
2360 fn into_literal(self) -> Expr {
2362 Expr(Expression::Literal(Box::new(Literal::Number(
2363 self.to_string(),
2364 ))))
2365 }
2366}
2367
2368impl IntoLiteral for usize {
2369 fn into_literal(self) -> Expr {
2371 Expr(Expression::Literal(Box::new(Literal::Number(
2372 self.to_string(),
2373 ))))
2374 }
2375}
2376
2377impl IntoLiteral for f64 {
2378 fn into_literal(self) -> Expr {
2380 Expr(Expression::Literal(Box::new(Literal::Number(
2381 self.to_string(),
2382 ))))
2383 }
2384}
2385
2386impl IntoLiteral for bool {
2387 fn into_literal(self) -> Expr {
2389 Expr(Expression::Boolean(BooleanLiteral { value: self }))
2390 }
2391}
2392
2393fn binary_op(left: Expression, right: Expression) -> BinaryOp {
2398 BinaryOp {
2399 left,
2400 right,
2401 left_comments: Vec::new(),
2402 operator_comments: Vec::new(),
2403 trailing_comments: Vec::new(),
2404 inferred_type: None,
2405 }
2406}
2407
2408pub fn merge_into(target: &str) -> MergeBuilder {
2430 MergeBuilder {
2431 target: Expression::Table(Box::new(builder_table_ref(target))),
2432 using: None,
2433 on: None,
2434 whens: Vec::new(),
2435 }
2436}
2437
2438pub struct MergeBuilder {
2442 target: Expression,
2443 using: Option<Expression>,
2444 on: Option<Expression>,
2445 whens: Vec<Expression>,
2446}
2447
2448impl MergeBuilder {
2449 pub fn using(mut self, source: &str, on: Expr) -> Self {
2451 self.using = Some(Expression::Table(Box::new(builder_table_ref(source))));
2452 self.on = Some(on.0);
2453 self
2454 }
2455
2456 pub fn when_matched_update(mut self, assignments: Vec<(&str, Expr)>) -> Self {
2458 let eqs: Vec<Expression> = assignments
2459 .into_iter()
2460 .map(|(col_name, val)| {
2461 Expression::Eq(Box::new(BinaryOp {
2462 left: Expression::boxed_column(Column {
2463 name: builder_identifier(col_name),
2464 table: None,
2465 join_mark: false,
2466 trailing_comments: Vec::new(),
2467 span: None,
2468 inferred_type: None,
2469 }),
2470 right: val.0,
2471 left_comments: Vec::new(),
2472 operator_comments: Vec::new(),
2473 trailing_comments: Vec::new(),
2474 inferred_type: None,
2475 }))
2476 })
2477 .collect();
2478
2479 let action = Expression::Tuple(Box::new(Tuple {
2480 expressions: vec![
2481 Expression::Var(Box::new(Var {
2482 this: "UPDATE".to_string(),
2483 })),
2484 Expression::Tuple(Box::new(Tuple { expressions: eqs })),
2485 ],
2486 }));
2487
2488 let when = Expression::When(Box::new(When {
2489 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2490 value: true,
2491 }))),
2492 source: None,
2493 condition: None,
2494 then: Box::new(action),
2495 }));
2496 self.whens.push(when);
2497 self
2498 }
2499
2500 pub fn when_matched_update_where(
2502 mut self,
2503 condition: Expr,
2504 assignments: Vec<(&str, Expr)>,
2505 ) -> Self {
2506 let eqs: Vec<Expression> = assignments
2507 .into_iter()
2508 .map(|(col_name, val)| {
2509 Expression::Eq(Box::new(BinaryOp {
2510 left: Expression::boxed_column(Column {
2511 name: builder_identifier(col_name),
2512 table: None,
2513 join_mark: false,
2514 trailing_comments: Vec::new(),
2515 span: None,
2516 inferred_type: None,
2517 }),
2518 right: val.0,
2519 left_comments: Vec::new(),
2520 operator_comments: Vec::new(),
2521 trailing_comments: Vec::new(),
2522 inferred_type: None,
2523 }))
2524 })
2525 .collect();
2526
2527 let action = Expression::Tuple(Box::new(Tuple {
2528 expressions: vec![
2529 Expression::Var(Box::new(Var {
2530 this: "UPDATE".to_string(),
2531 })),
2532 Expression::Tuple(Box::new(Tuple { expressions: eqs })),
2533 ],
2534 }));
2535
2536 let when = Expression::When(Box::new(When {
2537 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2538 value: true,
2539 }))),
2540 source: None,
2541 condition: Some(Box::new(condition.0)),
2542 then: Box::new(action),
2543 }));
2544 self.whens.push(when);
2545 self
2546 }
2547
2548 pub fn when_matched_delete(mut self) -> Self {
2550 let action = Expression::Var(Box::new(Var {
2551 this: "DELETE".to_string(),
2552 }));
2553
2554 let when = Expression::When(Box::new(When {
2555 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2556 value: true,
2557 }))),
2558 source: None,
2559 condition: None,
2560 then: Box::new(action),
2561 }));
2562 self.whens.push(when);
2563 self
2564 }
2565
2566 pub fn when_not_matched_insert(mut self, columns: &[&str], values: Vec<Expr>) -> Self {
2568 let col_exprs: Vec<Expression> = columns
2569 .iter()
2570 .map(|c| {
2571 Expression::boxed_column(Column {
2572 name: builder_identifier(c),
2573 table: None,
2574 join_mark: false,
2575 trailing_comments: Vec::new(),
2576 span: None,
2577 inferred_type: None,
2578 })
2579 })
2580 .collect();
2581 let val_exprs: Vec<Expression> = values.into_iter().map(|v| v.0).collect();
2582
2583 let action = Expression::Tuple(Box::new(Tuple {
2584 expressions: vec![
2585 Expression::Var(Box::new(Var {
2586 this: "INSERT".to_string(),
2587 })),
2588 Expression::Tuple(Box::new(Tuple {
2589 expressions: col_exprs,
2590 })),
2591 Expression::Tuple(Box::new(Tuple {
2592 expressions: val_exprs,
2593 })),
2594 ],
2595 }));
2596
2597 let when = Expression::When(Box::new(When {
2598 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2599 value: false,
2600 }))),
2601 source: None,
2602 condition: None,
2603 then: Box::new(action),
2604 }));
2605 self.whens.push(when);
2606 self
2607 }
2608
2609 pub fn build(self) -> Expression {
2611 let whens_expr = Expression::Whens(Box::new(Whens {
2612 expressions: self.whens,
2613 }));
2614
2615 Expression::Merge(Box::new(Merge {
2616 this: Box::new(self.target),
2617 using: Box::new(
2618 self.using
2619 .unwrap_or(Expression::Null(crate::expressions::Null)),
2620 ),
2621 on: self.on.map(Box::new),
2622 using_cond: None,
2623 whens: Some(Box::new(whens_expr)),
2624 with_: None,
2625 returning: None,
2626 }))
2627 }
2628
2629 pub fn to_sql(self) -> String {
2631 Generator::sql(&self.build()).unwrap_or_default()
2632 }
2633}
2634
2635fn parse_simple_data_type(name: &str) -> DataType {
2636 let upper = name.trim().to_uppercase();
2637 match upper.as_str() {
2638 "INT" | "INTEGER" => DataType::Int {
2639 length: None,
2640 integer_spelling: upper == "INTEGER",
2641 },
2642 "BIGINT" => DataType::BigInt { length: None },
2643 "SMALLINT" => DataType::SmallInt { length: None },
2644 "TINYINT" => DataType::TinyInt { length: None },
2645 "FLOAT" => DataType::Float {
2646 precision: None,
2647 scale: None,
2648 real_spelling: false,
2649 },
2650 "DOUBLE" => DataType::Double {
2651 precision: None,
2652 scale: None,
2653 },
2654 "BOOLEAN" | "BOOL" => DataType::Boolean,
2655 "TEXT" => DataType::Text,
2656 "DATE" => DataType::Date,
2657 "TIMESTAMP" => DataType::Timestamp {
2658 precision: None,
2659 timezone: false,
2660 },
2661 "VARCHAR" => DataType::VarChar {
2662 length: None,
2663 parenthesized_length: false,
2664 },
2665 "CHAR" => DataType::Char { length: None },
2666 _ => {
2667 if let Ok(ast) =
2669 crate::parser::Parser::parse_sql(&format!("SELECT CAST(x AS {})", name))
2670 {
2671 if let Expression::Select(s) = &ast[0] {
2672 if let Some(Expression::Cast(c)) = s.expressions.first() {
2673 return c.to.clone();
2674 }
2675 }
2676 }
2677 DataType::Custom {
2679 name: name.to_string(),
2680 }
2681 }
2682 }
2683}
2684
2685#[cfg(test)]
2686mod tests {
2687 use super::*;
2688
2689 #[test]
2690 fn test_simple_select() {
2691 let sql = select(["id", "name"]).from("users").to_sql();
2692 assert_eq!(sql, "SELECT id, name FROM users");
2693 }
2694
2695 #[test]
2696 fn test_builder_quotes_unsafe_identifier_tokens() {
2697 let sql = select(["Name; DROP TABLE titanic"]).to_sql();
2698 assert_eq!(sql, r#"SELECT "Name; DROP TABLE titanic""#);
2699 }
2700
2701 #[test]
2702 fn test_builder_string_literal_requires_lit() {
2703 let sql = select([lit("Name; DROP TABLE titanic")]).to_sql();
2704 assert_eq!(sql, "SELECT 'Name; DROP TABLE titanic'");
2705 }
2706
2707 #[test]
2708 fn test_builder_quotes_unsafe_table_name_tokens() {
2709 let sql = select(["id"]).from("users; DROP TABLE x").to_sql();
2710 assert_eq!(sql, r#"SELECT id FROM "users; DROP TABLE x""#);
2711 }
2712
2713 #[test]
2714 fn test_select_star() {
2715 let sql = select([star()]).from("users").to_sql();
2716 assert_eq!(sql, "SELECT * FROM users");
2717 }
2718
2719 #[test]
2720 fn test_select_with_where() {
2721 let sql = select(["id", "name"])
2722 .from("users")
2723 .where_(col("age").gt(lit(18)))
2724 .to_sql();
2725 assert_eq!(sql, "SELECT id, name FROM users WHERE age > 18");
2726 }
2727
2728 #[test]
2729 fn test_select_with_join() {
2730 let sql = select(["u.id", "o.amount"])
2731 .from("users")
2732 .join("orders", col("u.id").eq(col("o.user_id")))
2733 .to_sql();
2734 assert_eq!(
2735 sql,
2736 "SELECT u.id, o.amount FROM users JOIN orders ON u.id = o.user_id"
2737 );
2738 }
2739
2740 #[test]
2741 fn test_select_with_group_by_having() {
2742 let sql = select([col("dept"), func("COUNT", [star()]).alias("cnt")])
2743 .from("employees")
2744 .group_by(["dept"])
2745 .having(func("COUNT", [star()]).gt(lit(5)))
2746 .to_sql();
2747 assert_eq!(
2748 sql,
2749 "SELECT dept, COUNT(*) AS cnt FROM employees GROUP BY dept HAVING COUNT(*) > 5"
2750 );
2751 }
2752
2753 #[test]
2754 fn test_select_with_order_limit_offset() {
2755 let sql = select(["id", "name"])
2756 .from("users")
2757 .order_by(["name"])
2758 .limit(10)
2759 .offset(20)
2760 .to_sql();
2761 assert_eq!(
2762 sql,
2763 "SELECT id, name FROM users ORDER BY name LIMIT 10 OFFSET 20"
2764 );
2765 }
2766
2767 #[test]
2768 fn test_select_distinct() {
2769 let sql = select(["name"]).from("users").distinct().to_sql();
2770 assert_eq!(sql, "SELECT DISTINCT name FROM users");
2771 }
2772
2773 #[test]
2774 fn test_insert_values() {
2775 let sql = insert_into("users")
2776 .columns(["id", "name"])
2777 .values([lit(1), lit("Alice")])
2778 .values([lit(2), lit("Bob")])
2779 .to_sql();
2780 assert_eq!(
2781 sql,
2782 "INSERT INTO users (id, name) VALUES (1, 'Alice'), (2, 'Bob')"
2783 );
2784 }
2785
2786 #[test]
2787 fn test_insert_select() {
2788 let sql = insert_into("archive")
2789 .columns(["id", "name"])
2790 .query(select(["id", "name"]).from("users"))
2791 .to_sql();
2792 assert_eq!(
2793 sql,
2794 "INSERT INTO archive (id, name) SELECT id, name FROM users"
2795 );
2796 }
2797
2798 #[test]
2799 fn test_update() {
2800 let sql = update("users")
2801 .set("name", lit("Bob"))
2802 .set("age", lit(30))
2803 .where_(col("id").eq(lit(1)))
2804 .to_sql();
2805 assert_eq!(sql, "UPDATE users SET name = 'Bob', age = 30 WHERE id = 1");
2806 }
2807
2808 #[test]
2809 fn test_delete() {
2810 let sql = delete("users").where_(col("id").eq(lit(1))).to_sql();
2811 assert_eq!(sql, "DELETE FROM users WHERE id = 1");
2812 }
2813
2814 #[test]
2815 fn test_complex_where() {
2816 let sql = select(["id"])
2817 .from("users")
2818 .where_(
2819 col("age")
2820 .gte(lit(18))
2821 .and(col("active").eq(boolean(true)))
2822 .and(col("name").like(lit("%test%"))),
2823 )
2824 .to_sql();
2825 assert_eq!(
2826 sql,
2827 "SELECT id FROM users WHERE age >= 18 AND active = TRUE AND name LIKE '%test%'"
2828 );
2829 }
2830
2831 #[test]
2832 fn test_in_list() {
2833 let sql = select(["id"])
2834 .from("users")
2835 .where_(col("status").in_list([lit("active"), lit("pending")]))
2836 .to_sql();
2837 assert_eq!(
2838 sql,
2839 "SELECT id FROM users WHERE status IN ('active', 'pending')"
2840 );
2841 }
2842
2843 #[test]
2844 fn test_between() {
2845 let sql = select(["id"])
2846 .from("orders")
2847 .where_(col("amount").between(lit(100), lit(500)))
2848 .to_sql();
2849 assert_eq!(
2850 sql,
2851 "SELECT id FROM orders WHERE amount BETWEEN 100 AND 500"
2852 );
2853 }
2854
2855 #[test]
2856 fn test_is_null() {
2857 let sql = select(["id"])
2858 .from("users")
2859 .where_(col("email").is_null())
2860 .to_sql();
2861 assert_eq!(sql, "SELECT id FROM users WHERE email IS NULL");
2862 }
2863
2864 #[test]
2865 fn test_arithmetic() {
2866 let sql = select([col("price").mul(col("quantity")).alias("total")])
2867 .from("items")
2868 .to_sql();
2869 assert_eq!(sql, "SELECT price * quantity AS total FROM items");
2870 }
2871
2872 #[test]
2873 fn test_cast() {
2874 let sql = select([col("id").cast("VARCHAR")]).from("users").to_sql();
2875 assert_eq!(sql, "SELECT CAST(id AS VARCHAR) FROM users");
2876 }
2877
2878 #[test]
2879 fn test_from_starter() {
2880 let sql = from("users").select_cols(["id", "name"]).to_sql();
2881 assert_eq!(sql, "SELECT id, name FROM users");
2882 }
2883
2884 #[test]
2885 fn test_qualified_column() {
2886 let sql = select([col("u.id"), col("u.name")]).from("users").to_sql();
2887 assert_eq!(sql, "SELECT u.id, u.name FROM users");
2888 }
2889
2890 #[test]
2891 fn test_not_condition() {
2892 let sql = select(["id"])
2893 .from("users")
2894 .where_(not(col("active").eq(boolean(true))))
2895 .to_sql();
2896 assert_eq!(sql, "SELECT id FROM users WHERE NOT active = TRUE");
2897 }
2898
2899 #[test]
2900 fn test_order_by_desc() {
2901 let sql = select(["id", "name"])
2902 .from("users")
2903 .order_by([col("name").desc()])
2904 .to_sql();
2905 assert_eq!(sql, "SELECT id, name FROM users ORDER BY name DESC");
2906 }
2907
2908 #[test]
2909 fn test_left_join() {
2910 let sql = select(["u.id", "o.amount"])
2911 .from("users")
2912 .left_join("orders", col("u.id").eq(col("o.user_id")))
2913 .to_sql();
2914 assert_eq!(
2915 sql,
2916 "SELECT u.id, o.amount FROM users LEFT JOIN orders ON u.id = o.user_id"
2917 );
2918 }
2919
2920 #[test]
2921 fn test_build_returns_expression() {
2922 let expr = select(["id"]).from("users").build();
2923 assert!(matches!(expr, Expression::Select(_)));
2924 }
2925
2926 #[test]
2927 fn test_expr_interop() {
2928 let age_check = col("age").gt(lit(18));
2930 let sql = select([col("id"), age_check.alias("is_adult")])
2931 .from("users")
2932 .to_sql();
2933 assert_eq!(sql, "SELECT id, age > 18 AS is_adult FROM users");
2934 }
2935
2936 #[test]
2939 fn test_sql_expr_simple() {
2940 let expr = sql_expr("age > 18");
2941 let sql = select(["id"]).from("users").where_(expr).to_sql();
2942 assert_eq!(sql, "SELECT id FROM users WHERE age > 18");
2943 }
2944
2945 #[test]
2946 fn test_sql_expr_compound() {
2947 let expr = sql_expr("a > 1 AND b < 10");
2948 let sql = select(["*"]).from("t").where_(expr).to_sql();
2949 assert_eq!(sql, "SELECT * FROM t WHERE a > 1 AND b < 10");
2950 }
2951
2952 #[test]
2953 fn test_sql_expr_function() {
2954 let expr = sql_expr("COALESCE(a, b, 0)");
2955 let sql = select([expr.alias("val")]).from("t").to_sql();
2956 assert_eq!(sql, "SELECT COALESCE(a, b, 0) AS val FROM t");
2957 }
2958
2959 #[test]
2960 fn test_condition_alias() {
2961 let cond = condition("x > 0");
2962 let sql = select(["*"]).from("t").where_(cond).to_sql();
2963 assert_eq!(sql, "SELECT * FROM t WHERE x > 0");
2964 }
2965
2966 #[test]
2969 fn test_ilike() {
2970 let sql = select(["id"])
2971 .from("users")
2972 .where_(col("name").ilike(lit("%test%")))
2973 .to_sql();
2974 assert_eq!(sql, "SELECT id FROM users WHERE name ILIKE '%test%'");
2975 }
2976
2977 #[test]
2978 fn test_rlike() {
2979 let sql = select(["id"])
2980 .from("users")
2981 .where_(col("name").rlike(lit("^[A-Z]")))
2982 .to_sql();
2983 assert_eq!(
2984 sql,
2985 "SELECT id FROM users WHERE REGEXP_LIKE(name, '^[A-Z]')"
2986 );
2987 }
2988
2989 #[test]
2990 fn test_not_in() {
2991 let sql = select(["id"])
2992 .from("users")
2993 .where_(col("status").not_in([lit("deleted"), lit("banned")]))
2994 .to_sql();
2995 assert_eq!(
2996 sql,
2997 "SELECT id FROM users WHERE NOT status IN ('deleted', 'banned')"
2998 );
2999 }
3000
3001 #[test]
3004 fn test_case_searched() {
3005 let expr = case()
3006 .when(col("x").gt(lit(0)), lit("positive"))
3007 .when(col("x").eq(lit(0)), lit("zero"))
3008 .else_(lit("negative"))
3009 .build();
3010 let sql = select([expr.alias("label")]).from("t").to_sql();
3011 assert_eq!(
3012 sql,
3013 "SELECT CASE WHEN x > 0 THEN 'positive' WHEN x = 0 THEN 'zero' ELSE 'negative' END AS label FROM t"
3014 );
3015 }
3016
3017 #[test]
3018 fn test_case_simple() {
3019 let expr = case_of(col("status"))
3020 .when(lit(1), lit("active"))
3021 .when(lit(0), lit("inactive"))
3022 .build();
3023 let sql = select([expr.alias("status_label")]).from("t").to_sql();
3024 assert_eq!(
3025 sql,
3026 "SELECT CASE status WHEN 1 THEN 'active' WHEN 0 THEN 'inactive' END AS status_label FROM t"
3027 );
3028 }
3029
3030 #[test]
3031 fn test_case_no_else() {
3032 let expr = case().when(col("x").gt(lit(0)), lit("yes")).build();
3033 let sql = select([expr]).from("t").to_sql();
3034 assert_eq!(sql, "SELECT CASE WHEN x > 0 THEN 'yes' END FROM t");
3035 }
3036
3037 #[test]
3040 fn test_subquery_in_from() {
3041 let inner = select(["id", "name"])
3042 .from("users")
3043 .where_(col("active").eq(boolean(true)));
3044 let outer = select(["sub.id"])
3045 .from_expr(subquery(inner, "sub"))
3046 .to_sql();
3047 assert_eq!(
3048 outer,
3049 "SELECT sub.id FROM (SELECT id, name FROM users WHERE active = TRUE) AS sub"
3050 );
3051 }
3052
3053 #[test]
3054 fn test_subquery_in_join() {
3055 let inner = select([col("user_id"), func("SUM", [col("amount")]).alias("total")])
3056 .from("orders")
3057 .group_by(["user_id"]);
3058 let sql = select(["u.name", "o.total"])
3059 .from("users")
3060 .join("orders", col("u.id").eq(col("o.user_id")))
3061 .to_sql();
3062 assert!(sql.contains("JOIN"));
3063 let _sub = subquery(inner, "o");
3065 }
3066
3067 #[test]
3070 fn test_union() {
3071 let sql = union(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3072 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
3073 }
3074
3075 #[test]
3076 fn test_union_all() {
3077 let sql = union_all(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3078 assert_eq!(sql, "SELECT id FROM a UNION ALL SELECT id FROM b");
3079 }
3080
3081 #[test]
3082 fn test_intersect_builder() {
3083 let sql = intersect(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3084 assert_eq!(sql, "SELECT id FROM a INTERSECT SELECT id FROM b");
3085 }
3086
3087 #[test]
3088 fn test_except_builder() {
3089 let sql = except_(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3090 assert_eq!(sql, "SELECT id FROM a EXCEPT SELECT id FROM b");
3091 }
3092
3093 #[test]
3094 fn test_union_with_order_limit() {
3095 let sql = union(select(["id"]).from("a"), select(["id"]).from("b"))
3096 .order_by(["id"])
3097 .limit(10)
3098 .to_sql();
3099 assert!(sql.contains("UNION"));
3100 assert!(sql.contains("ORDER BY"));
3101 assert!(sql.contains("LIMIT"));
3102 }
3103
3104 #[test]
3105 fn test_select_builder_union() {
3106 let sql = select(["id"])
3107 .from("a")
3108 .union(select(["id"]).from("b"))
3109 .to_sql();
3110 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
3111 }
3112
3113 #[test]
3116 fn test_qualify() {
3117 let sql = select(["id", "name"])
3118 .from("users")
3119 .qualify(col("rn").eq(lit(1)))
3120 .to_sql();
3121 assert_eq!(sql, "SELECT id, name FROM users QUALIFY rn = 1");
3122 }
3123
3124 #[test]
3125 fn test_right_join() {
3126 let sql = select(["u.id", "o.amount"])
3127 .from("users")
3128 .right_join("orders", col("u.id").eq(col("o.user_id")))
3129 .to_sql();
3130 assert_eq!(
3131 sql,
3132 "SELECT u.id, o.amount FROM users RIGHT JOIN orders ON u.id = o.user_id"
3133 );
3134 }
3135
3136 #[test]
3137 fn test_cross_join() {
3138 let sql = select(["a.x", "b.y"]).from("a").cross_join("b").to_sql();
3139 assert_eq!(sql, "SELECT a.x, b.y FROM a CROSS JOIN b");
3140 }
3141
3142 #[test]
3143 fn test_lateral_view() {
3144 let sql = select(["id", "col_val"])
3145 .from("t")
3146 .lateral_view(func("EXPLODE", [col("arr")]), "lv", ["col_val"])
3147 .to_sql();
3148 assert!(sql.contains("LATERAL VIEW"));
3149 assert!(sql.contains("EXPLODE"));
3150 }
3151
3152 #[test]
3153 fn test_window_clause() {
3154 let sql = select(["id"])
3155 .from("t")
3156 .window(
3157 "w",
3158 WindowDefBuilder::new()
3159 .partition_by(["dept"])
3160 .order_by(["salary"]),
3161 )
3162 .to_sql();
3163 assert!(sql.contains("WINDOW"));
3164 assert!(sql.contains("PARTITION BY"));
3165 }
3166
3167 #[test]
3170 fn test_xor() {
3171 let sql = select(["*"])
3172 .from("t")
3173 .where_(col("a").xor(col("b")))
3174 .to_sql();
3175 assert_eq!(sql, "SELECT * FROM t WHERE a XOR b");
3176 }
3177
3178 #[test]
3181 fn test_for_update() {
3182 let sql = select(["id"]).from("t").for_update().to_sql();
3183 assert_eq!(sql, "SELECT id FROM t FOR UPDATE");
3184 }
3185
3186 #[test]
3187 fn test_for_share() {
3188 let sql = select(["id"]).from("t").for_share().to_sql();
3189 assert_eq!(sql, "SELECT id FROM t FOR SHARE");
3190 }
3191
3192 #[test]
3195 fn test_hint() {
3196 let sql = select(["*"]).from("t").hint("FULL(t)").to_sql();
3197 assert!(sql.contains("FULL(t)"), "Expected hint in: {}", sql);
3198 }
3199
3200 #[test]
3203 fn test_ctas() {
3204 let expr = select(["*"]).from("t").ctas("new_table");
3205 let sql = Generator::sql(&expr).unwrap();
3206 assert_eq!(sql, "CREATE TABLE new_table AS SELECT * FROM t");
3207 }
3208
3209 #[test]
3212 fn test_merge_update_insert() {
3213 let sql = merge_into("target")
3214 .using("source", col("target.id").eq(col("source.id")))
3215 .when_matched_update(vec![("name", col("source.name"))])
3216 .when_not_matched_insert(&["id", "name"], vec![col("source.id"), col("source.name")])
3217 .to_sql();
3218 assert!(
3219 sql.contains("MERGE INTO"),
3220 "Expected MERGE INTO in: {}",
3221 sql
3222 );
3223 assert!(sql.contains("USING"), "Expected USING in: {}", sql);
3224 assert!(
3225 sql.contains("WHEN MATCHED"),
3226 "Expected WHEN MATCHED in: {}",
3227 sql
3228 );
3229 assert!(
3230 sql.contains("UPDATE SET"),
3231 "Expected UPDATE SET in: {}",
3232 sql
3233 );
3234 assert!(
3235 sql.contains("WHEN NOT MATCHED"),
3236 "Expected WHEN NOT MATCHED in: {}",
3237 sql
3238 );
3239 assert!(sql.contains("INSERT"), "Expected INSERT in: {}", sql);
3240 }
3241
3242 #[test]
3243 fn test_merge_delete() {
3244 let sql = merge_into("target")
3245 .using("source", col("target.id").eq(col("source.id")))
3246 .when_matched_delete()
3247 .to_sql();
3248 assert!(
3249 sql.contains("MERGE INTO"),
3250 "Expected MERGE INTO in: {}",
3251 sql
3252 );
3253 assert!(
3254 sql.contains("WHEN MATCHED THEN DELETE"),
3255 "Expected WHEN MATCHED THEN DELETE in: {}",
3256 sql
3257 );
3258 }
3259
3260 #[test]
3261 fn test_merge_with_condition() {
3262 let sql = merge_into("target")
3263 .using("source", col("target.id").eq(col("source.id")))
3264 .when_matched_update_where(
3265 col("source.active").eq(boolean(true)),
3266 vec![("name", col("source.name"))],
3267 )
3268 .to_sql();
3269 assert!(
3270 sql.contains("MERGE INTO"),
3271 "Expected MERGE INTO in: {}",
3272 sql
3273 );
3274 assert!(
3275 sql.contains("AND source.active = TRUE"),
3276 "Expected condition in: {}",
3277 sql
3278 );
3279 }
3280}