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::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::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(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(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 on_cluster: None,
807 alias: None,
808 alias_explicit_as: false,
809 using: Vec::new(),
810 where_clause: None,
811 output: None,
812 leading_comments: Vec::new(),
813 with: None,
814 limit: None,
815 order_by: None,
816 returning: Vec::new(),
817 tables: Vec::new(),
818 tables_from_using: false,
819 joins: Vec::new(),
820 force_index: None,
821 no_from: false,
822 },
823 }
824}
825
826pub fn insert_into(table_name: &str) -> InsertBuilder {
843 InsertBuilder {
844 insert: Insert {
845 table: builder_table_ref(table_name),
846 columns: Vec::new(),
847 values: Vec::new(),
848 query: None,
849 overwrite: false,
850 partition: Vec::new(),
851 directory: None,
852 returning: Vec::new(),
853 output: None,
854 on_conflict: None,
855 leading_comments: Vec::new(),
856 if_exists: false,
857 with: None,
858 ignore: false,
859 source_alias: None,
860 alias: None,
861 alias_explicit_as: false,
862 default_values: false,
863 by_name: false,
864 conflict_action: None,
865 is_replace: false,
866 hint: None,
867 replace_where: None,
868 source: None,
869 function_target: None,
870 partition_by: None,
871 settings: Vec::new(),
872 },
873 }
874}
875
876pub fn update(table_name: &str) -> UpdateBuilder {
894 UpdateBuilder {
895 update: Update {
896 table: builder_table_ref(table_name),
897 extra_tables: Vec::new(),
898 table_joins: Vec::new(),
899 set: Vec::new(),
900 from_clause: None,
901 from_joins: Vec::new(),
902 where_clause: None,
903 returning: Vec::new(),
904 output: None,
905 with: None,
906 leading_comments: Vec::new(),
907 limit: None,
908 order_by: None,
909 from_before_set: false,
910 },
911 }
912}
913
914#[derive(Debug, Clone)]
939pub struct Expr(pub Expression);
940
941impl Expr {
942 pub fn into_inner(self) -> Expression {
944 self.0
945 }
946
947 pub fn to_sql(&self) -> String {
951 Generator::sql(&self.0).unwrap_or_default()
952 }
953
954 pub fn eq(self, other: Expr) -> Expr {
958 Expr(Expression::Eq(Box::new(binary_op(self.0, other.0))))
959 }
960
961 pub fn neq(self, other: Expr) -> Expr {
963 Expr(Expression::Neq(Box::new(binary_op(self.0, other.0))))
964 }
965
966 pub fn lt(self, other: Expr) -> Expr {
968 Expr(Expression::Lt(Box::new(binary_op(self.0, other.0))))
969 }
970
971 pub fn lte(self, other: Expr) -> Expr {
973 Expr(Expression::Lte(Box::new(binary_op(self.0, other.0))))
974 }
975
976 pub fn gt(self, other: Expr) -> Expr {
978 Expr(Expression::Gt(Box::new(binary_op(self.0, other.0))))
979 }
980
981 pub fn gte(self, other: Expr) -> Expr {
983 Expr(Expression::Gte(Box::new(binary_op(self.0, other.0))))
984 }
985
986 pub fn and(self, other: Expr) -> Expr {
990 Expr(Expression::And(Box::new(binary_op(self.0, other.0))))
991 }
992
993 pub fn or(self, other: Expr) -> Expr {
995 Expr(Expression::Or(Box::new(binary_op(self.0, other.0))))
996 }
997
998 pub fn not(self) -> Expr {
1000 Expr(Expression::Not(Box::new(UnaryOp::new(self.0))))
1001 }
1002
1003 pub fn xor(self, other: Expr) -> Expr {
1005 Expr(Expression::Xor(Box::new(Xor {
1006 this: Some(Box::new(self.0)),
1007 expression: Some(Box::new(other.0)),
1008 expressions: vec![],
1009 })))
1010 }
1011
1012 pub fn add(self, other: Expr) -> Expr {
1016 Expr(Expression::Add(Box::new(binary_op(self.0, other.0))))
1017 }
1018
1019 pub fn sub(self, other: Expr) -> Expr {
1021 Expr(Expression::Sub(Box::new(binary_op(self.0, other.0))))
1022 }
1023
1024 pub fn mul(self, other: Expr) -> Expr {
1026 Expr(Expression::Mul(Box::new(binary_op(self.0, other.0))))
1027 }
1028
1029 pub fn div(self, other: Expr) -> Expr {
1031 Expr(Expression::Div(Box::new(binary_op(self.0, other.0))))
1032 }
1033
1034 pub fn is_null(self) -> Expr {
1038 Expr(Expression::Is(Box::new(BinaryOp {
1039 left: self.0,
1040 right: Expression::Null(Null),
1041 left_comments: Vec::new(),
1042 operator_comments: Vec::new(),
1043 trailing_comments: Vec::new(),
1044 inferred_type: None,
1045 })))
1046 }
1047
1048 pub fn is_not_null(self) -> Expr {
1050 Expr(Expression::Not(Box::new(UnaryOp::new(Expression::Is(
1051 Box::new(BinaryOp {
1052 left: self.0,
1053 right: Expression::Null(Null),
1054 left_comments: Vec::new(),
1055 operator_comments: Vec::new(),
1056 trailing_comments: Vec::new(),
1057 inferred_type: None,
1058 }),
1059 )))))
1060 }
1061
1062 pub fn in_list(self, values: impl IntoIterator<Item = Expr>) -> Expr {
1066 Expr(Expression::In(Box::new(In {
1067 this: self.0,
1068 expressions: values.into_iter().map(|v| v.0).collect(),
1069 query: None,
1070 not: false,
1071 global: false,
1072 unnest: None,
1073 is_field: false,
1074 })))
1075 }
1076
1077 pub fn between(self, low: Expr, high: Expr) -> Expr {
1079 Expr(Expression::Between(Box::new(Between {
1080 this: self.0,
1081 low: low.0,
1082 high: high.0,
1083 not: false,
1084 symmetric: None,
1085 })))
1086 }
1087
1088 pub fn like(self, pattern: Expr) -> Expr {
1090 Expr(Expression::Like(Box::new(LikeOp {
1091 left: self.0,
1092 right: pattern.0,
1093 escape: None,
1094 quantifier: None,
1095 inferred_type: None,
1096 })))
1097 }
1098
1099 pub fn alias(self, name: &str) -> Expr {
1101 alias(self, name)
1102 }
1103
1104 pub fn cast(self, to: &str) -> Expr {
1108 cast(self, to)
1109 }
1110
1111 pub fn asc(self) -> Expr {
1116 Expr(Expression::Ordered(Box::new(Ordered {
1117 this: self.0,
1118 desc: false,
1119 nulls_first: None,
1120 explicit_asc: true,
1121 with_fill: None,
1122 })))
1123 }
1124
1125 pub fn desc(self) -> Expr {
1129 Expr(Expression::Ordered(Box::new(Ordered {
1130 this: self.0,
1131 desc: true,
1132 nulls_first: None,
1133 explicit_asc: false,
1134 with_fill: None,
1135 })))
1136 }
1137
1138 pub fn ilike(self, pattern: Expr) -> Expr {
1143 Expr(Expression::ILike(Box::new(LikeOp {
1144 left: self.0,
1145 right: pattern.0,
1146 escape: None,
1147 quantifier: None,
1148 inferred_type: None,
1149 })))
1150 }
1151
1152 pub fn rlike(self, pattern: Expr) -> Expr {
1157 Expr(Expression::RegexpLike(Box::new(RegexpFunc {
1158 this: self.0,
1159 pattern: pattern.0,
1160 flags: None,
1161 })))
1162 }
1163
1164 pub fn not_in(self, values: impl IntoIterator<Item = Expr>) -> Expr {
1168 Expr(Expression::In(Box::new(In {
1169 this: self.0,
1170 expressions: values.into_iter().map(|v| v.0).collect(),
1171 query: None,
1172 not: true,
1173 global: false,
1174 unnest: None,
1175 is_field: false,
1176 })))
1177 }
1178}
1179
1180pub struct SelectBuilder {
1206 select: Select,
1207}
1208
1209impl SelectBuilder {
1210 fn new() -> Self {
1211 SelectBuilder {
1212 select: Select::new(),
1213 }
1214 }
1215
1216 pub fn select_cols<I, E>(mut self, expressions: I) -> Self
1221 where
1222 I: IntoIterator<Item = E>,
1223 E: IntoExpr,
1224 {
1225 for expr in expressions {
1226 self.select.expressions.push(expr.into_expr().0);
1227 }
1228 self
1229 }
1230
1231 pub fn from(mut self, table_name: &str) -> Self {
1233 self.select.from = Some(From {
1234 expressions: vec![Expression::Table(builder_table_ref(table_name))],
1235 });
1236 self
1237 }
1238
1239 pub fn from_expr(mut self, expr: Expr) -> Self {
1244 self.select.from = Some(From {
1245 expressions: vec![expr.0],
1246 });
1247 self
1248 }
1249
1250 pub fn join(mut self, table_name: &str, on: Expr) -> Self {
1252 self.select.joins.push(Join {
1253 kind: JoinKind::Inner,
1254 this: Expression::Table(builder_table_ref(table_name)),
1255 on: Some(on.0),
1256 using: Vec::new(),
1257 use_inner_keyword: false,
1258 use_outer_keyword: false,
1259 deferred_condition: false,
1260 join_hint: None,
1261 match_condition: None,
1262 pivots: Vec::new(),
1263 comments: Vec::new(),
1264 nesting_group: 0,
1265 directed: false,
1266 });
1267 self
1268 }
1269
1270 pub fn left_join(mut self, table_name: &str, on: Expr) -> Self {
1272 self.select.joins.push(Join {
1273 kind: JoinKind::Left,
1274 this: Expression::Table(builder_table_ref(table_name)),
1275 on: Some(on.0),
1276 using: Vec::new(),
1277 use_inner_keyword: false,
1278 use_outer_keyword: false,
1279 deferred_condition: false,
1280 join_hint: None,
1281 match_condition: None,
1282 pivots: Vec::new(),
1283 comments: Vec::new(),
1284 nesting_group: 0,
1285 directed: false,
1286 });
1287 self
1288 }
1289
1290 pub fn where_(mut self, condition: Expr) -> Self {
1296 self.select.where_clause = Some(Where { this: condition.0 });
1297 self
1298 }
1299
1300 pub fn group_by<I, E>(mut self, expressions: I) -> Self
1302 where
1303 I: IntoIterator<Item = E>,
1304 E: IntoExpr,
1305 {
1306 self.select.group_by = Some(GroupBy {
1307 expressions: expressions.into_iter().map(|e| e.into_expr().0).collect(),
1308 all: None,
1309 totals: false,
1310 comments: Vec::new(),
1311 });
1312 self
1313 }
1314
1315 pub fn having(mut self, condition: Expr) -> Self {
1317 self.select.having = Some(Having {
1318 this: condition.0,
1319 comments: Vec::new(),
1320 });
1321 self
1322 }
1323
1324 pub fn order_by<I, E>(mut self, expressions: I) -> Self
1330 where
1331 I: IntoIterator<Item = E>,
1332 E: IntoExpr,
1333 {
1334 self.select.order_by = Some(OrderBy {
1335 siblings: false,
1336 comments: Vec::new(),
1337 expressions: expressions
1338 .into_iter()
1339 .map(|e| {
1340 let expr = e.into_expr().0;
1341 match expr {
1342 Expression::Ordered(_) => expr,
1343 other => Expression::Ordered(Box::new(Ordered {
1344 this: other,
1345 desc: false,
1346 nulls_first: None,
1347 explicit_asc: false,
1348 with_fill: None,
1349 })),
1350 }
1351 })
1352 .collect::<Vec<_>>()
1353 .into_iter()
1354 .map(|e| {
1355 if let Expression::Ordered(o) = e {
1356 *o
1357 } else {
1358 Ordered {
1359 this: e,
1360 desc: false,
1361 nulls_first: None,
1362 explicit_asc: false,
1363 with_fill: None,
1364 }
1365 }
1366 })
1367 .collect(),
1368 });
1369 self
1370 }
1371
1372 pub fn sort_by<I, E>(mut self, expressions: I) -> Self
1379 where
1380 I: IntoIterator<Item = E>,
1381 E: IntoExpr,
1382 {
1383 self.select.sort_by = Some(SortBy {
1384 expressions: expressions
1385 .into_iter()
1386 .map(|e| {
1387 let expr = e.into_expr().0;
1388 match expr {
1389 Expression::Ordered(o) => *o,
1390 other => Ordered {
1391 this: other,
1392 desc: false,
1393 nulls_first: None,
1394 explicit_asc: false,
1395 with_fill: None,
1396 },
1397 }
1398 })
1399 .collect(),
1400 });
1401 self
1402 }
1403
1404 pub fn limit(mut self, count: usize) -> Self {
1406 self.select.limit = Some(Limit {
1407 this: Expression::Literal(Literal::Number(count.to_string())),
1408 percent: false,
1409 comments: Vec::new(),
1410 });
1411 self
1412 }
1413
1414 pub fn offset(mut self, count: usize) -> Self {
1416 self.select.offset = Some(Offset {
1417 this: Expression::Literal(Literal::Number(count.to_string())),
1418 rows: None,
1419 });
1420 self
1421 }
1422
1423 pub fn distinct(mut self) -> Self {
1425 self.select.distinct = true;
1426 self
1427 }
1428
1429 pub fn qualify(mut self, condition: Expr) -> Self {
1434 self.select.qualify = Some(Qualify { this: condition.0 });
1435 self
1436 }
1437
1438 pub fn right_join(mut self, table_name: &str, on: Expr) -> Self {
1440 self.select.joins.push(Join {
1441 kind: JoinKind::Right,
1442 this: Expression::Table(builder_table_ref(table_name)),
1443 on: Some(on.0),
1444 using: Vec::new(),
1445 use_inner_keyword: false,
1446 use_outer_keyword: false,
1447 deferred_condition: false,
1448 join_hint: None,
1449 match_condition: None,
1450 pivots: Vec::new(),
1451 comments: Vec::new(),
1452 nesting_group: 0,
1453 directed: false,
1454 });
1455 self
1456 }
1457
1458 pub fn cross_join(mut self, table_name: &str) -> Self {
1460 self.select.joins.push(Join {
1461 kind: JoinKind::Cross,
1462 this: Expression::Table(builder_table_ref(table_name)),
1463 on: None,
1464 using: Vec::new(),
1465 use_inner_keyword: false,
1466 use_outer_keyword: false,
1467 deferred_condition: false,
1468 join_hint: None,
1469 match_condition: None,
1470 pivots: Vec::new(),
1471 comments: Vec::new(),
1472 nesting_group: 0,
1473 directed: false,
1474 });
1475 self
1476 }
1477
1478 pub fn lateral_view<S: AsRef<str>>(
1485 mut self,
1486 table_function: Expr,
1487 table_alias: &str,
1488 column_aliases: impl IntoIterator<Item = S>,
1489 ) -> Self {
1490 self.select.lateral_views.push(LateralView {
1491 this: table_function.0,
1492 table_alias: Some(builder_identifier(table_alias)),
1493 column_aliases: column_aliases
1494 .into_iter()
1495 .map(|c| builder_identifier(c.as_ref()))
1496 .collect(),
1497 outer: false,
1498 });
1499 self
1500 }
1501
1502 pub fn window(mut self, name: &str, def: WindowDefBuilder) -> Self {
1508 let named_window = NamedWindow {
1509 name: builder_identifier(name),
1510 spec: Over {
1511 window_name: None,
1512 partition_by: def.partition_by,
1513 order_by: def.order_by,
1514 frame: None,
1515 alias: None,
1516 },
1517 };
1518 match self.select.windows {
1519 Some(ref mut windows) => windows.push(named_window),
1520 None => self.select.windows = Some(vec![named_window]),
1521 }
1522 self
1523 }
1524
1525 pub fn for_update(mut self) -> Self {
1530 self.select.locks.push(Lock {
1531 update: Some(Box::new(Expression::Boolean(BooleanLiteral {
1532 value: true,
1533 }))),
1534 expressions: vec![],
1535 wait: None,
1536 key: None,
1537 });
1538 self
1539 }
1540
1541 pub fn for_share(mut self) -> Self {
1546 self.select.locks.push(Lock {
1547 update: None,
1548 expressions: vec![],
1549 wait: None,
1550 key: None,
1551 });
1552 self
1553 }
1554
1555 pub fn hint(mut self, hint_text: &str) -> Self {
1560 let hint_expr = HintExpression::Raw(hint_text.to_string());
1561 match &mut self.select.hint {
1562 Some(h) => h.expressions.push(hint_expr),
1563 None => {
1564 self.select.hint = Some(Hint {
1565 expressions: vec![hint_expr],
1566 })
1567 }
1568 }
1569 self
1570 }
1571
1572 pub fn ctas(self, table_name: &str) -> Expression {
1588 Expression::CreateTable(Box::new(CreateTable {
1589 name: builder_table_ref(table_name),
1590 on_cluster: None,
1591 columns: vec![],
1592 constraints: vec![],
1593 if_not_exists: false,
1594 temporary: false,
1595 or_replace: false,
1596 table_modifier: None,
1597 as_select: Some(self.build()),
1598 as_select_parenthesized: false,
1599 on_commit: None,
1600 clone_source: None,
1601 clone_at_clause: None,
1602 is_copy: false,
1603 shallow_clone: false,
1604 leading_comments: vec![],
1605 with_properties: vec![],
1606 teradata_post_name_options: vec![],
1607 with_data: None,
1608 with_statistics: None,
1609 teradata_indexes: vec![],
1610 with_cte: None,
1611 properties: vec![],
1612 partition_of: None,
1613 post_table_properties: vec![],
1614 mysql_table_options: vec![],
1615 inherits: vec![],
1616 on_property: None,
1617 copy_grants: false,
1618 using_template: None,
1619 rollup: None,
1620 }))
1621 }
1622
1623 pub fn union(self, other: SelectBuilder) -> SetOpBuilder {
1627 SetOpBuilder::new(SetOpKind::Union, self, other, false)
1628 }
1629
1630 pub fn union_all(self, other: SelectBuilder) -> SetOpBuilder {
1634 SetOpBuilder::new(SetOpKind::Union, self, other, true)
1635 }
1636
1637 pub fn intersect(self, other: SelectBuilder) -> SetOpBuilder {
1641 SetOpBuilder::new(SetOpKind::Intersect, self, other, false)
1642 }
1643
1644 pub fn except_(self, other: SelectBuilder) -> SetOpBuilder {
1648 SetOpBuilder::new(SetOpKind::Except, self, other, false)
1649 }
1650
1651 pub fn build(self) -> Expression {
1653 Expression::Select(Box::new(self.select))
1654 }
1655
1656 pub fn to_sql(self) -> String {
1661 Generator::sql(&self.build()).unwrap_or_default()
1662 }
1663}
1664
1665pub struct DeleteBuilder {
1674 delete: Delete,
1675}
1676
1677impl DeleteBuilder {
1678 pub fn where_(mut self, condition: Expr) -> Self {
1680 self.delete.where_clause = Some(Where { this: condition.0 });
1681 self
1682 }
1683
1684 pub fn build(self) -> Expression {
1686 Expression::Delete(Box::new(self.delete))
1687 }
1688
1689 pub fn to_sql(self) -> String {
1691 Generator::sql(&self.build()).unwrap_or_default()
1692 }
1693}
1694
1695pub struct InsertBuilder {
1706 insert: Insert,
1707}
1708
1709impl InsertBuilder {
1710 pub fn columns<I, S>(mut self, columns: I) -> Self
1712 where
1713 I: IntoIterator<Item = S>,
1714 S: AsRef<str>,
1715 {
1716 self.insert.columns = columns
1717 .into_iter()
1718 .map(|c| builder_identifier(c.as_ref()))
1719 .collect();
1720 self
1721 }
1722
1723 pub fn values<I>(mut self, values: I) -> Self
1727 where
1728 I: IntoIterator<Item = Expr>,
1729 {
1730 self.insert
1731 .values
1732 .push(values.into_iter().map(|v| v.0).collect());
1733 self
1734 }
1735
1736 pub fn query(mut self, query: SelectBuilder) -> Self {
1740 self.insert.query = Some(query.build());
1741 self
1742 }
1743
1744 pub fn build(self) -> Expression {
1746 Expression::Insert(Box::new(self.insert))
1747 }
1748
1749 pub fn to_sql(self) -> String {
1751 Generator::sql(&self.build()).unwrap_or_default()
1752 }
1753}
1754
1755pub struct UpdateBuilder {
1765 update: Update,
1766}
1767
1768impl UpdateBuilder {
1769 pub fn set(mut self, column: &str, value: Expr) -> Self {
1773 self.update.set.push((builder_identifier(column), value.0));
1774 self
1775 }
1776
1777 pub fn where_(mut self, condition: Expr) -> Self {
1779 self.update.where_clause = Some(Where { this: condition.0 });
1780 self
1781 }
1782
1783 pub fn from(mut self, table_name: &str) -> Self {
1787 self.update.from_clause = Some(From {
1788 expressions: vec![Expression::Table(builder_table_ref(table_name))],
1789 });
1790 self
1791 }
1792
1793 pub fn build(self) -> Expression {
1795 Expression::Update(Box::new(self.update))
1796 }
1797
1798 pub fn to_sql(self) -> String {
1800 Generator::sql(&self.build()).unwrap_or_default()
1801 }
1802}
1803
1804pub fn case() -> CaseBuilder {
1829 CaseBuilder {
1830 operand: None,
1831 whens: Vec::new(),
1832 else_: None,
1833 }
1834}
1835
1836pub fn case_of(operand: Expr) -> CaseBuilder {
1857 CaseBuilder {
1858 operand: Some(operand.0),
1859 whens: Vec::new(),
1860 else_: None,
1861 }
1862}
1863
1864pub struct CaseBuilder {
1872 operand: Option<Expression>,
1873 whens: Vec<(Expression, Expression)>,
1874 else_: Option<Expression>,
1875}
1876
1877impl CaseBuilder {
1878 pub fn when(mut self, condition: Expr, result: Expr) -> Self {
1883 self.whens.push((condition.0, result.0));
1884 self
1885 }
1886
1887 pub fn else_(mut self, result: Expr) -> Self {
1892 self.else_ = Some(result.0);
1893 self
1894 }
1895
1896 pub fn build(self) -> Expr {
1898 Expr(self.build_expr())
1899 }
1900
1901 pub fn build_expr(self) -> Expression {
1906 Expression::Case(Box::new(Case {
1907 operand: self.operand,
1908 whens: self.whens,
1909 else_: self.else_,
1910 comments: Vec::new(),
1911 inferred_type: None,
1912 }))
1913 }
1914}
1915
1916pub fn subquery(query: SelectBuilder, alias_name: &str) -> Expr {
1940 subquery_expr(query.build(), alias_name)
1941}
1942
1943pub fn subquery_expr(expr: Expression, alias_name: &str) -> Expr {
1948 Expr(Expression::Subquery(Box::new(Subquery {
1949 this: expr,
1950 alias: Some(builder_identifier(alias_name)),
1951 column_aliases: Vec::new(),
1952 order_by: None,
1953 limit: None,
1954 offset: None,
1955 distribute_by: None,
1956 sort_by: None,
1957 cluster_by: None,
1958 lateral: false,
1959 modifiers_inside: true,
1960 trailing_comments: Vec::new(),
1961 inferred_type: None,
1962 })))
1963}
1964
1965#[derive(Debug, Clone, Copy)]
1971enum SetOpKind {
1972 Union,
1973 Intersect,
1974 Except,
1975}
1976
1977pub struct SetOpBuilder {
1998 kind: SetOpKind,
1999 left: Expression,
2000 right: Expression,
2001 all: bool,
2002 order_by: Option<OrderBy>,
2003 limit: Option<Box<Expression>>,
2004 offset: Option<Box<Expression>>,
2005}
2006
2007impl SetOpBuilder {
2008 fn new(kind: SetOpKind, left: SelectBuilder, right: SelectBuilder, all: bool) -> Self {
2009 SetOpBuilder {
2010 kind,
2011 left: left.build(),
2012 right: right.build(),
2013 all,
2014 order_by: None,
2015 limit: None,
2016 offset: None,
2017 }
2018 }
2019
2020 pub fn order_by<I, E>(mut self, expressions: I) -> Self
2025 where
2026 I: IntoIterator<Item = E>,
2027 E: IntoExpr,
2028 {
2029 self.order_by = Some(OrderBy {
2030 siblings: false,
2031 comments: Vec::new(),
2032 expressions: expressions
2033 .into_iter()
2034 .map(|e| {
2035 let expr = e.into_expr().0;
2036 match expr {
2037 Expression::Ordered(o) => *o,
2038 other => Ordered {
2039 this: other,
2040 desc: false,
2041 nulls_first: None,
2042 explicit_asc: false,
2043 with_fill: None,
2044 },
2045 }
2046 })
2047 .collect(),
2048 });
2049 self
2050 }
2051
2052 pub fn limit(mut self, count: usize) -> Self {
2054 self.limit = Some(Box::new(Expression::Literal(Literal::Number(
2055 count.to_string(),
2056 ))));
2057 self
2058 }
2059
2060 pub fn offset(mut self, count: usize) -> Self {
2062 self.offset = Some(Box::new(Expression::Literal(Literal::Number(
2063 count.to_string(),
2064 ))));
2065 self
2066 }
2067
2068 pub fn build(self) -> Expression {
2073 match self.kind {
2074 SetOpKind::Union => Expression::Union(Box::new(Union {
2075 left: self.left,
2076 right: self.right,
2077 all: self.all,
2078 distinct: false,
2079 with: None,
2080 order_by: self.order_by,
2081 limit: self.limit,
2082 offset: self.offset,
2083 distribute_by: None,
2084 sort_by: None,
2085 cluster_by: None,
2086 by_name: false,
2087 side: None,
2088 kind: None,
2089 corresponding: false,
2090 strict: false,
2091 on_columns: Vec::new(),
2092 })),
2093 SetOpKind::Intersect => Expression::Intersect(Box::new(Intersect {
2094 left: self.left,
2095 right: self.right,
2096 all: self.all,
2097 distinct: false,
2098 with: None,
2099 order_by: self.order_by,
2100 limit: self.limit,
2101 offset: self.offset,
2102 distribute_by: None,
2103 sort_by: None,
2104 cluster_by: None,
2105 by_name: false,
2106 side: None,
2107 kind: None,
2108 corresponding: false,
2109 strict: false,
2110 on_columns: Vec::new(),
2111 })),
2112 SetOpKind::Except => Expression::Except(Box::new(Except {
2113 left: self.left,
2114 right: self.right,
2115 all: self.all,
2116 distinct: false,
2117 with: None,
2118 order_by: self.order_by,
2119 limit: self.limit,
2120 offset: self.offset,
2121 distribute_by: None,
2122 sort_by: None,
2123 cluster_by: None,
2124 by_name: false,
2125 side: None,
2126 kind: None,
2127 corresponding: false,
2128 strict: false,
2129 on_columns: Vec::new(),
2130 })),
2131 }
2132 }
2133
2134 pub fn to_sql(self) -> String {
2136 Generator::sql(&self.build()).unwrap_or_default()
2137 }
2138}
2139
2140pub fn union(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2144 SetOpBuilder::new(SetOpKind::Union, left, right, false)
2145}
2146
2147pub fn union_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2151 SetOpBuilder::new(SetOpKind::Union, left, right, true)
2152}
2153
2154pub fn intersect(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2158 SetOpBuilder::new(SetOpKind::Intersect, left, right, false)
2159}
2160
2161pub fn intersect_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2165 SetOpBuilder::new(SetOpKind::Intersect, left, right, true)
2166}
2167
2168pub fn except_(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2172 SetOpBuilder::new(SetOpKind::Except, left, right, false)
2173}
2174
2175pub fn except_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2179 SetOpBuilder::new(SetOpKind::Except, left, right, true)
2180}
2181
2182pub struct WindowDefBuilder {
2207 partition_by: Vec<Expression>,
2208 order_by: Vec<Ordered>,
2209}
2210
2211impl WindowDefBuilder {
2212 pub fn new() -> Self {
2214 WindowDefBuilder {
2215 partition_by: Vec::new(),
2216 order_by: Vec::new(),
2217 }
2218 }
2219
2220 pub fn partition_by<I, E>(mut self, expressions: I) -> Self
2222 where
2223 I: IntoIterator<Item = E>,
2224 E: IntoExpr,
2225 {
2226 self.partition_by = expressions.into_iter().map(|e| e.into_expr().0).collect();
2227 self
2228 }
2229
2230 pub fn order_by<I, E>(mut self, expressions: I) -> Self
2235 where
2236 I: IntoIterator<Item = E>,
2237 E: IntoExpr,
2238 {
2239 self.order_by = expressions
2240 .into_iter()
2241 .map(|e| {
2242 let expr = e.into_expr().0;
2243 match expr {
2244 Expression::Ordered(o) => *o,
2245 other => Ordered {
2246 this: other,
2247 desc: false,
2248 nulls_first: None,
2249 explicit_asc: false,
2250 with_fill: None,
2251 },
2252 }
2253 })
2254 .collect();
2255 self
2256 }
2257}
2258
2259pub trait IntoExpr {
2278 fn into_expr(self) -> Expr;
2280}
2281
2282impl IntoExpr for Expr {
2283 fn into_expr(self) -> Expr {
2284 self
2285 }
2286}
2287
2288impl IntoExpr for &str {
2289 fn into_expr(self) -> Expr {
2291 col(self)
2292 }
2293}
2294
2295impl IntoExpr for String {
2296 fn into_expr(self) -> Expr {
2298 col(&self)
2299 }
2300}
2301
2302impl IntoExpr for Expression {
2303 fn into_expr(self) -> Expr {
2305 Expr(self)
2306 }
2307}
2308
2309pub trait IntoLiteral {
2324 fn into_literal(self) -> Expr;
2326}
2327
2328impl IntoLiteral for &str {
2329 fn into_literal(self) -> Expr {
2331 Expr(Expression::Literal(Literal::String(self.to_string())))
2332 }
2333}
2334
2335impl IntoLiteral for String {
2336 fn into_literal(self) -> Expr {
2338 Expr(Expression::Literal(Literal::String(self)))
2339 }
2340}
2341
2342impl IntoLiteral for i64 {
2343 fn into_literal(self) -> Expr {
2345 Expr(Expression::Literal(Literal::Number(self.to_string())))
2346 }
2347}
2348
2349impl IntoLiteral for i32 {
2350 fn into_literal(self) -> Expr {
2352 Expr(Expression::Literal(Literal::Number(self.to_string())))
2353 }
2354}
2355
2356impl IntoLiteral for usize {
2357 fn into_literal(self) -> Expr {
2359 Expr(Expression::Literal(Literal::Number(self.to_string())))
2360 }
2361}
2362
2363impl IntoLiteral for f64 {
2364 fn into_literal(self) -> Expr {
2366 Expr(Expression::Literal(Literal::Number(self.to_string())))
2367 }
2368}
2369
2370impl IntoLiteral for bool {
2371 fn into_literal(self) -> Expr {
2373 Expr(Expression::Boolean(BooleanLiteral { value: self }))
2374 }
2375}
2376
2377fn binary_op(left: Expression, right: Expression) -> BinaryOp {
2382 BinaryOp {
2383 left,
2384 right,
2385 left_comments: Vec::new(),
2386 operator_comments: Vec::new(),
2387 trailing_comments: Vec::new(),
2388 inferred_type: None,
2389 }
2390}
2391
2392pub fn merge_into(target: &str) -> MergeBuilder {
2414 MergeBuilder {
2415 target: Expression::Table(builder_table_ref(target)),
2416 using: None,
2417 on: None,
2418 whens: Vec::new(),
2419 }
2420}
2421
2422pub struct MergeBuilder {
2426 target: Expression,
2427 using: Option<Expression>,
2428 on: Option<Expression>,
2429 whens: Vec<Expression>,
2430}
2431
2432impl MergeBuilder {
2433 pub fn using(mut self, source: &str, on: Expr) -> Self {
2435 self.using = Some(Expression::Table(builder_table_ref(source)));
2436 self.on = Some(on.0);
2437 self
2438 }
2439
2440 pub fn when_matched_update(mut self, assignments: Vec<(&str, Expr)>) -> Self {
2442 let eqs: Vec<Expression> = assignments
2443 .into_iter()
2444 .map(|(col_name, val)| {
2445 Expression::Eq(Box::new(BinaryOp {
2446 left: Expression::Column(Column {
2447 name: builder_identifier(col_name),
2448 table: None,
2449 join_mark: false,
2450 trailing_comments: Vec::new(),
2451 span: None,
2452 inferred_type: None,
2453 }),
2454 right: val.0,
2455 left_comments: Vec::new(),
2456 operator_comments: Vec::new(),
2457 trailing_comments: Vec::new(),
2458 inferred_type: None,
2459 }))
2460 })
2461 .collect();
2462
2463 let action = Expression::Tuple(Box::new(Tuple {
2464 expressions: vec![
2465 Expression::Var(Box::new(Var {
2466 this: "UPDATE".to_string(),
2467 })),
2468 Expression::Tuple(Box::new(Tuple { expressions: eqs })),
2469 ],
2470 }));
2471
2472 let when = Expression::When(Box::new(When {
2473 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2474 value: true,
2475 }))),
2476 source: None,
2477 condition: None,
2478 then: Box::new(action),
2479 }));
2480 self.whens.push(when);
2481 self
2482 }
2483
2484 pub fn when_matched_update_where(
2486 mut self,
2487 condition: Expr,
2488 assignments: Vec<(&str, Expr)>,
2489 ) -> Self {
2490 let eqs: Vec<Expression> = assignments
2491 .into_iter()
2492 .map(|(col_name, val)| {
2493 Expression::Eq(Box::new(BinaryOp {
2494 left: Expression::Column(Column {
2495 name: builder_identifier(col_name),
2496 table: None,
2497 join_mark: false,
2498 trailing_comments: Vec::new(),
2499 span: None,
2500 inferred_type: None,
2501 }),
2502 right: val.0,
2503 left_comments: Vec::new(),
2504 operator_comments: Vec::new(),
2505 trailing_comments: Vec::new(),
2506 inferred_type: None,
2507 }))
2508 })
2509 .collect();
2510
2511 let action = Expression::Tuple(Box::new(Tuple {
2512 expressions: vec![
2513 Expression::Var(Box::new(Var {
2514 this: "UPDATE".to_string(),
2515 })),
2516 Expression::Tuple(Box::new(Tuple { expressions: eqs })),
2517 ],
2518 }));
2519
2520 let when = Expression::When(Box::new(When {
2521 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2522 value: true,
2523 }))),
2524 source: None,
2525 condition: Some(Box::new(condition.0)),
2526 then: Box::new(action),
2527 }));
2528 self.whens.push(when);
2529 self
2530 }
2531
2532 pub fn when_matched_delete(mut self) -> Self {
2534 let action = Expression::Var(Box::new(Var {
2535 this: "DELETE".to_string(),
2536 }));
2537
2538 let when = Expression::When(Box::new(When {
2539 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2540 value: true,
2541 }))),
2542 source: None,
2543 condition: None,
2544 then: Box::new(action),
2545 }));
2546 self.whens.push(when);
2547 self
2548 }
2549
2550 pub fn when_not_matched_insert(mut self, columns: &[&str], values: Vec<Expr>) -> Self {
2552 let col_exprs: Vec<Expression> = columns
2553 .iter()
2554 .map(|c| {
2555 Expression::Column(Column {
2556 name: builder_identifier(c),
2557 table: None,
2558 join_mark: false,
2559 trailing_comments: Vec::new(),
2560 span: None,
2561 inferred_type: None,
2562 })
2563 })
2564 .collect();
2565 let val_exprs: Vec<Expression> = values.into_iter().map(|v| v.0).collect();
2566
2567 let action = Expression::Tuple(Box::new(Tuple {
2568 expressions: vec![
2569 Expression::Var(Box::new(Var {
2570 this: "INSERT".to_string(),
2571 })),
2572 Expression::Tuple(Box::new(Tuple {
2573 expressions: col_exprs,
2574 })),
2575 Expression::Tuple(Box::new(Tuple {
2576 expressions: val_exprs,
2577 })),
2578 ],
2579 }));
2580
2581 let when = Expression::When(Box::new(When {
2582 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2583 value: false,
2584 }))),
2585 source: None,
2586 condition: None,
2587 then: Box::new(action),
2588 }));
2589 self.whens.push(when);
2590 self
2591 }
2592
2593 pub fn build(self) -> Expression {
2595 let whens_expr = Expression::Whens(Box::new(Whens {
2596 expressions: self.whens,
2597 }));
2598
2599 Expression::Merge(Box::new(Merge {
2600 this: Box::new(self.target),
2601 using: Box::new(
2602 self.using
2603 .unwrap_or(Expression::Null(crate::expressions::Null)),
2604 ),
2605 on: self.on.map(Box::new),
2606 using_cond: None,
2607 whens: Some(Box::new(whens_expr)),
2608 with_: None,
2609 returning: None,
2610 }))
2611 }
2612
2613 pub fn to_sql(self) -> String {
2615 Generator::sql(&self.build()).unwrap_or_default()
2616 }
2617}
2618
2619fn parse_simple_data_type(name: &str) -> DataType {
2620 let upper = name.trim().to_uppercase();
2621 match upper.as_str() {
2622 "INT" | "INTEGER" => DataType::Int {
2623 length: None,
2624 integer_spelling: upper == "INTEGER",
2625 },
2626 "BIGINT" => DataType::BigInt { length: None },
2627 "SMALLINT" => DataType::SmallInt { length: None },
2628 "TINYINT" => DataType::TinyInt { length: None },
2629 "FLOAT" => DataType::Float {
2630 precision: None,
2631 scale: None,
2632 real_spelling: false,
2633 },
2634 "DOUBLE" => DataType::Double {
2635 precision: None,
2636 scale: None,
2637 },
2638 "BOOLEAN" | "BOOL" => DataType::Boolean,
2639 "TEXT" => DataType::Text,
2640 "DATE" => DataType::Date,
2641 "TIMESTAMP" => DataType::Timestamp {
2642 precision: None,
2643 timezone: false,
2644 },
2645 "VARCHAR" => DataType::VarChar {
2646 length: None,
2647 parenthesized_length: false,
2648 },
2649 "CHAR" => DataType::Char { length: None },
2650 _ => {
2651 if let Ok(ast) =
2653 crate::parser::Parser::parse_sql(&format!("SELECT CAST(x AS {})", name))
2654 {
2655 if let Expression::Select(s) = &ast[0] {
2656 if let Some(Expression::Cast(c)) = s.expressions.first() {
2657 return c.to.clone();
2658 }
2659 }
2660 }
2661 DataType::Custom {
2663 name: name.to_string(),
2664 }
2665 }
2666 }
2667}
2668
2669#[cfg(test)]
2670mod tests {
2671 use super::*;
2672
2673 #[test]
2674 fn test_simple_select() {
2675 let sql = select(["id", "name"]).from("users").to_sql();
2676 assert_eq!(sql, "SELECT id, name FROM users");
2677 }
2678
2679 #[test]
2680 fn test_builder_quotes_unsafe_identifier_tokens() {
2681 let sql = select(["Name; DROP TABLE titanic"]).to_sql();
2682 assert_eq!(sql, r#"SELECT "Name; DROP TABLE titanic""#);
2683 }
2684
2685 #[test]
2686 fn test_builder_string_literal_requires_lit() {
2687 let sql = select([lit("Name; DROP TABLE titanic")]).to_sql();
2688 assert_eq!(sql, "SELECT 'Name; DROP TABLE titanic'");
2689 }
2690
2691 #[test]
2692 fn test_builder_quotes_unsafe_table_name_tokens() {
2693 let sql = select(["id"]).from("users; DROP TABLE x").to_sql();
2694 assert_eq!(sql, r#"SELECT id FROM "users; DROP TABLE x""#);
2695 }
2696
2697 #[test]
2698 fn test_select_star() {
2699 let sql = select([star()]).from("users").to_sql();
2700 assert_eq!(sql, "SELECT * FROM users");
2701 }
2702
2703 #[test]
2704 fn test_select_with_where() {
2705 let sql = select(["id", "name"])
2706 .from("users")
2707 .where_(col("age").gt(lit(18)))
2708 .to_sql();
2709 assert_eq!(sql, "SELECT id, name FROM users WHERE age > 18");
2710 }
2711
2712 #[test]
2713 fn test_select_with_join() {
2714 let sql = select(["u.id", "o.amount"])
2715 .from("users")
2716 .join("orders", col("u.id").eq(col("o.user_id")))
2717 .to_sql();
2718 assert_eq!(
2719 sql,
2720 "SELECT u.id, o.amount FROM users JOIN orders ON u.id = o.user_id"
2721 );
2722 }
2723
2724 #[test]
2725 fn test_select_with_group_by_having() {
2726 let sql = select([col("dept"), func("COUNT", [star()]).alias("cnt")])
2727 .from("employees")
2728 .group_by(["dept"])
2729 .having(func("COUNT", [star()]).gt(lit(5)))
2730 .to_sql();
2731 assert_eq!(
2732 sql,
2733 "SELECT dept, COUNT(*) AS cnt FROM employees GROUP BY dept HAVING COUNT(*) > 5"
2734 );
2735 }
2736
2737 #[test]
2738 fn test_select_with_order_limit_offset() {
2739 let sql = select(["id", "name"])
2740 .from("users")
2741 .order_by(["name"])
2742 .limit(10)
2743 .offset(20)
2744 .to_sql();
2745 assert_eq!(
2746 sql,
2747 "SELECT id, name FROM users ORDER BY name LIMIT 10 OFFSET 20"
2748 );
2749 }
2750
2751 #[test]
2752 fn test_select_distinct() {
2753 let sql = select(["name"]).from("users").distinct().to_sql();
2754 assert_eq!(sql, "SELECT DISTINCT name FROM users");
2755 }
2756
2757 #[test]
2758 fn test_insert_values() {
2759 let sql = insert_into("users")
2760 .columns(["id", "name"])
2761 .values([lit(1), lit("Alice")])
2762 .values([lit(2), lit("Bob")])
2763 .to_sql();
2764 assert_eq!(
2765 sql,
2766 "INSERT INTO users (id, name) VALUES (1, 'Alice'), (2, 'Bob')"
2767 );
2768 }
2769
2770 #[test]
2771 fn test_insert_select() {
2772 let sql = insert_into("archive")
2773 .columns(["id", "name"])
2774 .query(select(["id", "name"]).from("users"))
2775 .to_sql();
2776 assert_eq!(
2777 sql,
2778 "INSERT INTO archive (id, name) SELECT id, name FROM users"
2779 );
2780 }
2781
2782 #[test]
2783 fn test_update() {
2784 let sql = update("users")
2785 .set("name", lit("Bob"))
2786 .set("age", lit(30))
2787 .where_(col("id").eq(lit(1)))
2788 .to_sql();
2789 assert_eq!(sql, "UPDATE users SET name = 'Bob', age = 30 WHERE id = 1");
2790 }
2791
2792 #[test]
2793 fn test_delete() {
2794 let sql = delete("users").where_(col("id").eq(lit(1))).to_sql();
2795 assert_eq!(sql, "DELETE FROM users WHERE id = 1");
2796 }
2797
2798 #[test]
2799 fn test_complex_where() {
2800 let sql = select(["id"])
2801 .from("users")
2802 .where_(
2803 col("age")
2804 .gte(lit(18))
2805 .and(col("active").eq(boolean(true)))
2806 .and(col("name").like(lit("%test%"))),
2807 )
2808 .to_sql();
2809 assert_eq!(
2810 sql,
2811 "SELECT id FROM users WHERE age >= 18 AND active = TRUE AND name LIKE '%test%'"
2812 );
2813 }
2814
2815 #[test]
2816 fn test_in_list() {
2817 let sql = select(["id"])
2818 .from("users")
2819 .where_(col("status").in_list([lit("active"), lit("pending")]))
2820 .to_sql();
2821 assert_eq!(
2822 sql,
2823 "SELECT id FROM users WHERE status IN ('active', 'pending')"
2824 );
2825 }
2826
2827 #[test]
2828 fn test_between() {
2829 let sql = select(["id"])
2830 .from("orders")
2831 .where_(col("amount").between(lit(100), lit(500)))
2832 .to_sql();
2833 assert_eq!(
2834 sql,
2835 "SELECT id FROM orders WHERE amount BETWEEN 100 AND 500"
2836 );
2837 }
2838
2839 #[test]
2840 fn test_is_null() {
2841 let sql = select(["id"])
2842 .from("users")
2843 .where_(col("email").is_null())
2844 .to_sql();
2845 assert_eq!(sql, "SELECT id FROM users WHERE email IS NULL");
2846 }
2847
2848 #[test]
2849 fn test_arithmetic() {
2850 let sql = select([col("price").mul(col("quantity")).alias("total")])
2851 .from("items")
2852 .to_sql();
2853 assert_eq!(sql, "SELECT price * quantity AS total FROM items");
2854 }
2855
2856 #[test]
2857 fn test_cast() {
2858 let sql = select([col("id").cast("VARCHAR")]).from("users").to_sql();
2859 assert_eq!(sql, "SELECT CAST(id AS VARCHAR) FROM users");
2860 }
2861
2862 #[test]
2863 fn test_from_starter() {
2864 let sql = from("users").select_cols(["id", "name"]).to_sql();
2865 assert_eq!(sql, "SELECT id, name FROM users");
2866 }
2867
2868 #[test]
2869 fn test_qualified_column() {
2870 let sql = select([col("u.id"), col("u.name")]).from("users").to_sql();
2871 assert_eq!(sql, "SELECT u.id, u.name FROM users");
2872 }
2873
2874 #[test]
2875 fn test_not_condition() {
2876 let sql = select(["id"])
2877 .from("users")
2878 .where_(not(col("active").eq(boolean(true))))
2879 .to_sql();
2880 assert_eq!(sql, "SELECT id FROM users WHERE NOT active = TRUE");
2881 }
2882
2883 #[test]
2884 fn test_order_by_desc() {
2885 let sql = select(["id", "name"])
2886 .from("users")
2887 .order_by([col("name").desc()])
2888 .to_sql();
2889 assert_eq!(sql, "SELECT id, name FROM users ORDER BY name DESC");
2890 }
2891
2892 #[test]
2893 fn test_left_join() {
2894 let sql = select(["u.id", "o.amount"])
2895 .from("users")
2896 .left_join("orders", col("u.id").eq(col("o.user_id")))
2897 .to_sql();
2898 assert_eq!(
2899 sql,
2900 "SELECT u.id, o.amount FROM users LEFT JOIN orders ON u.id = o.user_id"
2901 );
2902 }
2903
2904 #[test]
2905 fn test_build_returns_expression() {
2906 let expr = select(["id"]).from("users").build();
2907 assert!(matches!(expr, Expression::Select(_)));
2908 }
2909
2910 #[test]
2911 fn test_expr_interop() {
2912 let age_check = col("age").gt(lit(18));
2914 let sql = select([col("id"), age_check.alias("is_adult")])
2915 .from("users")
2916 .to_sql();
2917 assert_eq!(sql, "SELECT id, age > 18 AS is_adult FROM users");
2918 }
2919
2920 #[test]
2923 fn test_sql_expr_simple() {
2924 let expr = sql_expr("age > 18");
2925 let sql = select(["id"]).from("users").where_(expr).to_sql();
2926 assert_eq!(sql, "SELECT id FROM users WHERE age > 18");
2927 }
2928
2929 #[test]
2930 fn test_sql_expr_compound() {
2931 let expr = sql_expr("a > 1 AND b < 10");
2932 let sql = select(["*"]).from("t").where_(expr).to_sql();
2933 assert_eq!(sql, "SELECT * FROM t WHERE a > 1 AND b < 10");
2934 }
2935
2936 #[test]
2937 fn test_sql_expr_function() {
2938 let expr = sql_expr("COALESCE(a, b, 0)");
2939 let sql = select([expr.alias("val")]).from("t").to_sql();
2940 assert_eq!(sql, "SELECT COALESCE(a, b, 0) AS val FROM t");
2941 }
2942
2943 #[test]
2944 fn test_condition_alias() {
2945 let cond = condition("x > 0");
2946 let sql = select(["*"]).from("t").where_(cond).to_sql();
2947 assert_eq!(sql, "SELECT * FROM t WHERE x > 0");
2948 }
2949
2950 #[test]
2953 fn test_ilike() {
2954 let sql = select(["id"])
2955 .from("users")
2956 .where_(col("name").ilike(lit("%test%")))
2957 .to_sql();
2958 assert_eq!(sql, "SELECT id FROM users WHERE name ILIKE '%test%'");
2959 }
2960
2961 #[test]
2962 fn test_rlike() {
2963 let sql = select(["id"])
2964 .from("users")
2965 .where_(col("name").rlike(lit("^[A-Z]")))
2966 .to_sql();
2967 assert_eq!(
2968 sql,
2969 "SELECT id FROM users WHERE REGEXP_LIKE(name, '^[A-Z]')"
2970 );
2971 }
2972
2973 #[test]
2974 fn test_not_in() {
2975 let sql = select(["id"])
2976 .from("users")
2977 .where_(col("status").not_in([lit("deleted"), lit("banned")]))
2978 .to_sql();
2979 assert_eq!(
2980 sql,
2981 "SELECT id FROM users WHERE NOT status IN ('deleted', 'banned')"
2982 );
2983 }
2984
2985 #[test]
2988 fn test_case_searched() {
2989 let expr = case()
2990 .when(col("x").gt(lit(0)), lit("positive"))
2991 .when(col("x").eq(lit(0)), lit("zero"))
2992 .else_(lit("negative"))
2993 .build();
2994 let sql = select([expr.alias("label")]).from("t").to_sql();
2995 assert_eq!(
2996 sql,
2997 "SELECT CASE WHEN x > 0 THEN 'positive' WHEN x = 0 THEN 'zero' ELSE 'negative' END AS label FROM t"
2998 );
2999 }
3000
3001 #[test]
3002 fn test_case_simple() {
3003 let expr = case_of(col("status"))
3004 .when(lit(1), lit("active"))
3005 .when(lit(0), lit("inactive"))
3006 .build();
3007 let sql = select([expr.alias("status_label")]).from("t").to_sql();
3008 assert_eq!(
3009 sql,
3010 "SELECT CASE status WHEN 1 THEN 'active' WHEN 0 THEN 'inactive' END AS status_label FROM t"
3011 );
3012 }
3013
3014 #[test]
3015 fn test_case_no_else() {
3016 let expr = case().when(col("x").gt(lit(0)), lit("yes")).build();
3017 let sql = select([expr]).from("t").to_sql();
3018 assert_eq!(sql, "SELECT CASE WHEN x > 0 THEN 'yes' END FROM t");
3019 }
3020
3021 #[test]
3024 fn test_subquery_in_from() {
3025 let inner = select(["id", "name"])
3026 .from("users")
3027 .where_(col("active").eq(boolean(true)));
3028 let outer = select(["sub.id"])
3029 .from_expr(subquery(inner, "sub"))
3030 .to_sql();
3031 assert_eq!(
3032 outer,
3033 "SELECT sub.id FROM (SELECT id, name FROM users WHERE active = TRUE) AS sub"
3034 );
3035 }
3036
3037 #[test]
3038 fn test_subquery_in_join() {
3039 let inner = select([col("user_id"), func("SUM", [col("amount")]).alias("total")])
3040 .from("orders")
3041 .group_by(["user_id"]);
3042 let sql = select(["u.name", "o.total"])
3043 .from("users")
3044 .join("orders", col("u.id").eq(col("o.user_id")))
3045 .to_sql();
3046 assert!(sql.contains("JOIN"));
3047 let _sub = subquery(inner, "o");
3049 }
3050
3051 #[test]
3054 fn test_union() {
3055 let sql = union(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3056 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
3057 }
3058
3059 #[test]
3060 fn test_union_all() {
3061 let sql = union_all(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3062 assert_eq!(sql, "SELECT id FROM a UNION ALL SELECT id FROM b");
3063 }
3064
3065 #[test]
3066 fn test_intersect_builder() {
3067 let sql = intersect(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3068 assert_eq!(sql, "SELECT id FROM a INTERSECT SELECT id FROM b");
3069 }
3070
3071 #[test]
3072 fn test_except_builder() {
3073 let sql = except_(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3074 assert_eq!(sql, "SELECT id FROM a EXCEPT SELECT id FROM b");
3075 }
3076
3077 #[test]
3078 fn test_union_with_order_limit() {
3079 let sql = union(select(["id"]).from("a"), select(["id"]).from("b"))
3080 .order_by(["id"])
3081 .limit(10)
3082 .to_sql();
3083 assert!(sql.contains("UNION"));
3084 assert!(sql.contains("ORDER BY"));
3085 assert!(sql.contains("LIMIT"));
3086 }
3087
3088 #[test]
3089 fn test_select_builder_union() {
3090 let sql = select(["id"])
3091 .from("a")
3092 .union(select(["id"]).from("b"))
3093 .to_sql();
3094 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
3095 }
3096
3097 #[test]
3100 fn test_qualify() {
3101 let sql = select(["id", "name"])
3102 .from("users")
3103 .qualify(col("rn").eq(lit(1)))
3104 .to_sql();
3105 assert_eq!(sql, "SELECT id, name FROM users QUALIFY rn = 1");
3106 }
3107
3108 #[test]
3109 fn test_right_join() {
3110 let sql = select(["u.id", "o.amount"])
3111 .from("users")
3112 .right_join("orders", col("u.id").eq(col("o.user_id")))
3113 .to_sql();
3114 assert_eq!(
3115 sql,
3116 "SELECT u.id, o.amount FROM users RIGHT JOIN orders ON u.id = o.user_id"
3117 );
3118 }
3119
3120 #[test]
3121 fn test_cross_join() {
3122 let sql = select(["a.x", "b.y"]).from("a").cross_join("b").to_sql();
3123 assert_eq!(sql, "SELECT a.x, b.y FROM a CROSS JOIN b");
3124 }
3125
3126 #[test]
3127 fn test_lateral_view() {
3128 let sql = select(["id", "col_val"])
3129 .from("t")
3130 .lateral_view(func("EXPLODE", [col("arr")]), "lv", ["col_val"])
3131 .to_sql();
3132 assert!(sql.contains("LATERAL VIEW"));
3133 assert!(sql.contains("EXPLODE"));
3134 }
3135
3136 #[test]
3137 fn test_window_clause() {
3138 let sql = select(["id"])
3139 .from("t")
3140 .window(
3141 "w",
3142 WindowDefBuilder::new()
3143 .partition_by(["dept"])
3144 .order_by(["salary"]),
3145 )
3146 .to_sql();
3147 assert!(sql.contains("WINDOW"));
3148 assert!(sql.contains("PARTITION BY"));
3149 }
3150
3151 #[test]
3154 fn test_xor() {
3155 let sql = select(["*"])
3156 .from("t")
3157 .where_(col("a").xor(col("b")))
3158 .to_sql();
3159 assert_eq!(sql, "SELECT * FROM t WHERE a XOR b");
3160 }
3161
3162 #[test]
3165 fn test_for_update() {
3166 let sql = select(["id"]).from("t").for_update().to_sql();
3167 assert_eq!(sql, "SELECT id FROM t FOR UPDATE");
3168 }
3169
3170 #[test]
3171 fn test_for_share() {
3172 let sql = select(["id"]).from("t").for_share().to_sql();
3173 assert_eq!(sql, "SELECT id FROM t FOR SHARE");
3174 }
3175
3176 #[test]
3179 fn test_hint() {
3180 let sql = select(["*"]).from("t").hint("FULL(t)").to_sql();
3181 assert!(sql.contains("FULL(t)"), "Expected hint in: {}", sql);
3182 }
3183
3184 #[test]
3187 fn test_ctas() {
3188 let expr = select(["*"]).from("t").ctas("new_table");
3189 let sql = Generator::sql(&expr).unwrap();
3190 assert_eq!(sql, "CREATE TABLE new_table AS SELECT * FROM t");
3191 }
3192
3193 #[test]
3196 fn test_merge_update_insert() {
3197 let sql = merge_into("target")
3198 .using("source", col("target.id").eq(col("source.id")))
3199 .when_matched_update(vec![("name", col("source.name"))])
3200 .when_not_matched_insert(&["id", "name"], vec![col("source.id"), col("source.name")])
3201 .to_sql();
3202 assert!(
3203 sql.contains("MERGE INTO"),
3204 "Expected MERGE INTO in: {}",
3205 sql
3206 );
3207 assert!(sql.contains("USING"), "Expected USING in: {}", sql);
3208 assert!(
3209 sql.contains("WHEN MATCHED"),
3210 "Expected WHEN MATCHED in: {}",
3211 sql
3212 );
3213 assert!(
3214 sql.contains("UPDATE SET"),
3215 "Expected UPDATE SET in: {}",
3216 sql
3217 );
3218 assert!(
3219 sql.contains("WHEN NOT MATCHED"),
3220 "Expected WHEN NOT MATCHED in: {}",
3221 sql
3222 );
3223 assert!(sql.contains("INSERT"), "Expected INSERT in: {}", sql);
3224 }
3225
3226 #[test]
3227 fn test_merge_delete() {
3228 let sql = merge_into("target")
3229 .using("source", col("target.id").eq(col("source.id")))
3230 .when_matched_delete()
3231 .to_sql();
3232 assert!(
3233 sql.contains("MERGE INTO"),
3234 "Expected MERGE INTO in: {}",
3235 sql
3236 );
3237 assert!(
3238 sql.contains("WHEN MATCHED THEN DELETE"),
3239 "Expected WHEN MATCHED THEN DELETE in: {}",
3240 sql
3241 );
3242 }
3243
3244 #[test]
3245 fn test_merge_with_condition() {
3246 let sql = merge_into("target")
3247 .using("source", col("target.id").eq(col("source.id")))
3248 .when_matched_update_where(
3249 col("source.active").eq(boolean(true)),
3250 vec![("name", col("source.name"))],
3251 )
3252 .to_sql();
3253 assert!(
3254 sql.contains("MERGE INTO"),
3255 "Expected MERGE INTO in: {}",
3256 sql
3257 );
3258 assert!(
3259 sql.contains("AND source.active = TRUE"),
3260 "Expected condition in: {}",
3261 sql
3262 );
3263 }
3264}