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 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(Box::new(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(Box::new(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(Box::new(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(Box::new(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(Box::new(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(Box::new(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(Box::new(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 uuid: None,
1621 }))
1622 }
1623
1624 pub fn union(self, other: SelectBuilder) -> SetOpBuilder {
1628 SetOpBuilder::new(SetOpKind::Union, self, other, false)
1629 }
1630
1631 pub fn union_all(self, other: SelectBuilder) -> SetOpBuilder {
1635 SetOpBuilder::new(SetOpKind::Union, self, other, true)
1636 }
1637
1638 pub fn intersect(self, other: SelectBuilder) -> SetOpBuilder {
1642 SetOpBuilder::new(SetOpKind::Intersect, self, other, false)
1643 }
1644
1645 pub fn except_(self, other: SelectBuilder) -> SetOpBuilder {
1649 SetOpBuilder::new(SetOpKind::Except, self, other, false)
1650 }
1651
1652 pub fn build(self) -> Expression {
1654 Expression::Select(Box::new(self.select))
1655 }
1656
1657 pub fn to_sql(self) -> String {
1662 Generator::sql(&self.build()).unwrap_or_default()
1663 }
1664}
1665
1666pub struct DeleteBuilder {
1675 delete: Delete,
1676}
1677
1678impl DeleteBuilder {
1679 pub fn where_(mut self, condition: Expr) -> Self {
1681 self.delete.where_clause = Some(Where { this: condition.0 });
1682 self
1683 }
1684
1685 pub fn build(self) -> Expression {
1687 Expression::Delete(Box::new(self.delete))
1688 }
1689
1690 pub fn to_sql(self) -> String {
1692 Generator::sql(&self.build()).unwrap_or_default()
1693 }
1694}
1695
1696pub struct InsertBuilder {
1707 insert: Insert,
1708}
1709
1710impl InsertBuilder {
1711 pub fn columns<I, S>(mut self, columns: I) -> Self
1713 where
1714 I: IntoIterator<Item = S>,
1715 S: AsRef<str>,
1716 {
1717 self.insert.columns = columns
1718 .into_iter()
1719 .map(|c| builder_identifier(c.as_ref()))
1720 .collect();
1721 self
1722 }
1723
1724 pub fn values<I>(mut self, values: I) -> Self
1728 where
1729 I: IntoIterator<Item = Expr>,
1730 {
1731 self.insert
1732 .values
1733 .push(values.into_iter().map(|v| v.0).collect());
1734 self
1735 }
1736
1737 pub fn query(mut self, query: SelectBuilder) -> Self {
1741 self.insert.query = Some(query.build());
1742 self
1743 }
1744
1745 pub fn build(self) -> Expression {
1747 Expression::Insert(Box::new(self.insert))
1748 }
1749
1750 pub fn to_sql(self) -> String {
1752 Generator::sql(&self.build()).unwrap_or_default()
1753 }
1754}
1755
1756pub struct UpdateBuilder {
1766 update: Update,
1767}
1768
1769impl UpdateBuilder {
1770 pub fn set(mut self, column: &str, value: Expr) -> Self {
1774 self.update.set.push((builder_identifier(column), value.0));
1775 self
1776 }
1777
1778 pub fn where_(mut self, condition: Expr) -> Self {
1780 self.update.where_clause = Some(Where { this: condition.0 });
1781 self
1782 }
1783
1784 pub fn from(mut self, table_name: &str) -> Self {
1788 self.update.from_clause = Some(From {
1789 expressions: vec![Expression::Table(Box::new(builder_table_ref(table_name)))],
1790 });
1791 self
1792 }
1793
1794 pub fn build(self) -> Expression {
1796 Expression::Update(Box::new(self.update))
1797 }
1798
1799 pub fn to_sql(self) -> String {
1801 Generator::sql(&self.build()).unwrap_or_default()
1802 }
1803}
1804
1805pub fn case() -> CaseBuilder {
1830 CaseBuilder {
1831 operand: None,
1832 whens: Vec::new(),
1833 else_: None,
1834 }
1835}
1836
1837pub fn case_of(operand: Expr) -> CaseBuilder {
1858 CaseBuilder {
1859 operand: Some(operand.0),
1860 whens: Vec::new(),
1861 else_: None,
1862 }
1863}
1864
1865pub struct CaseBuilder {
1873 operand: Option<Expression>,
1874 whens: Vec<(Expression, Expression)>,
1875 else_: Option<Expression>,
1876}
1877
1878impl CaseBuilder {
1879 pub fn when(mut self, condition: Expr, result: Expr) -> Self {
1884 self.whens.push((condition.0, result.0));
1885 self
1886 }
1887
1888 pub fn else_(mut self, result: Expr) -> Self {
1893 self.else_ = Some(result.0);
1894 self
1895 }
1896
1897 pub fn build(self) -> Expr {
1899 Expr(self.build_expr())
1900 }
1901
1902 pub fn build_expr(self) -> Expression {
1907 Expression::Case(Box::new(Case {
1908 operand: self.operand,
1909 whens: self.whens,
1910 else_: self.else_,
1911 comments: Vec::new(),
1912 inferred_type: None,
1913 }))
1914 }
1915}
1916
1917pub fn subquery(query: SelectBuilder, alias_name: &str) -> Expr {
1941 subquery_expr(query.build(), alias_name)
1942}
1943
1944pub fn subquery_expr(expr: Expression, alias_name: &str) -> Expr {
1949 Expr(Expression::Subquery(Box::new(Subquery {
1950 this: expr,
1951 alias: Some(builder_identifier(alias_name)),
1952 column_aliases: Vec::new(),
1953 order_by: None,
1954 limit: None,
1955 offset: None,
1956 distribute_by: None,
1957 sort_by: None,
1958 cluster_by: None,
1959 lateral: false,
1960 modifiers_inside: true,
1961 trailing_comments: Vec::new(),
1962 inferred_type: None,
1963 })))
1964}
1965
1966#[derive(Debug, Clone, Copy)]
1972enum SetOpKind {
1973 Union,
1974 Intersect,
1975 Except,
1976}
1977
1978pub struct SetOpBuilder {
1999 kind: SetOpKind,
2000 left: Expression,
2001 right: Expression,
2002 all: bool,
2003 order_by: Option<OrderBy>,
2004 limit: Option<Box<Expression>>,
2005 offset: Option<Box<Expression>>,
2006}
2007
2008impl SetOpBuilder {
2009 fn new(kind: SetOpKind, left: SelectBuilder, right: SelectBuilder, all: bool) -> Self {
2010 SetOpBuilder {
2011 kind,
2012 left: left.build(),
2013 right: right.build(),
2014 all,
2015 order_by: None,
2016 limit: None,
2017 offset: None,
2018 }
2019 }
2020
2021 pub fn order_by<I, E>(mut self, expressions: I) -> Self
2026 where
2027 I: IntoIterator<Item = E>,
2028 E: IntoExpr,
2029 {
2030 self.order_by = Some(OrderBy {
2031 siblings: false,
2032 comments: Vec::new(),
2033 expressions: expressions
2034 .into_iter()
2035 .map(|e| {
2036 let expr = e.into_expr().0;
2037 match expr {
2038 Expression::Ordered(o) => *o,
2039 other => Ordered {
2040 this: other,
2041 desc: false,
2042 nulls_first: None,
2043 explicit_asc: false,
2044 with_fill: None,
2045 },
2046 }
2047 })
2048 .collect(),
2049 });
2050 self
2051 }
2052
2053 pub fn limit(mut self, count: usize) -> Self {
2055 self.limit = Some(Box::new(Expression::Literal(Box::new(Literal::Number(
2056 count.to_string(),
2057 )))));
2058 self
2059 }
2060
2061 pub fn offset(mut self, count: usize) -> Self {
2063 self.offset = Some(Box::new(Expression::Literal(Box::new(Literal::Number(
2064 count.to_string(),
2065 )))));
2066 self
2067 }
2068
2069 pub fn build(self) -> Expression {
2074 match self.kind {
2075 SetOpKind::Union => Expression::Union(Box::new(Union {
2076 left: self.left,
2077 right: self.right,
2078 all: self.all,
2079 distinct: false,
2080 with: None,
2081 order_by: self.order_by,
2082 limit: self.limit,
2083 offset: self.offset,
2084 distribute_by: None,
2085 sort_by: None,
2086 cluster_by: None,
2087 by_name: false,
2088 side: None,
2089 kind: None,
2090 corresponding: false,
2091 strict: false,
2092 on_columns: Vec::new(),
2093 })),
2094 SetOpKind::Intersect => Expression::Intersect(Box::new(Intersect {
2095 left: self.left,
2096 right: self.right,
2097 all: self.all,
2098 distinct: false,
2099 with: None,
2100 order_by: self.order_by,
2101 limit: self.limit,
2102 offset: self.offset,
2103 distribute_by: None,
2104 sort_by: None,
2105 cluster_by: None,
2106 by_name: false,
2107 side: None,
2108 kind: None,
2109 corresponding: false,
2110 strict: false,
2111 on_columns: Vec::new(),
2112 })),
2113 SetOpKind::Except => Expression::Except(Box::new(Except {
2114 left: self.left,
2115 right: self.right,
2116 all: self.all,
2117 distinct: false,
2118 with: None,
2119 order_by: self.order_by,
2120 limit: self.limit,
2121 offset: self.offset,
2122 distribute_by: None,
2123 sort_by: None,
2124 cluster_by: None,
2125 by_name: false,
2126 side: None,
2127 kind: None,
2128 corresponding: false,
2129 strict: false,
2130 on_columns: Vec::new(),
2131 })),
2132 }
2133 }
2134
2135 pub fn to_sql(self) -> String {
2137 Generator::sql(&self.build()).unwrap_or_default()
2138 }
2139}
2140
2141pub fn union(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2145 SetOpBuilder::new(SetOpKind::Union, left, right, false)
2146}
2147
2148pub fn union_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2152 SetOpBuilder::new(SetOpKind::Union, left, right, true)
2153}
2154
2155pub fn intersect(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2159 SetOpBuilder::new(SetOpKind::Intersect, left, right, false)
2160}
2161
2162pub fn intersect_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2166 SetOpBuilder::new(SetOpKind::Intersect, left, right, true)
2167}
2168
2169pub fn except_(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2173 SetOpBuilder::new(SetOpKind::Except, left, right, false)
2174}
2175
2176pub fn except_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2180 SetOpBuilder::new(SetOpKind::Except, left, right, true)
2181}
2182
2183pub struct WindowDefBuilder {
2208 partition_by: Vec<Expression>,
2209 order_by: Vec<Ordered>,
2210}
2211
2212impl WindowDefBuilder {
2213 pub fn new() -> Self {
2215 WindowDefBuilder {
2216 partition_by: Vec::new(),
2217 order_by: Vec::new(),
2218 }
2219 }
2220
2221 pub fn partition_by<I, E>(mut self, expressions: I) -> Self
2223 where
2224 I: IntoIterator<Item = E>,
2225 E: IntoExpr,
2226 {
2227 self.partition_by = expressions.into_iter().map(|e| e.into_expr().0).collect();
2228 self
2229 }
2230
2231 pub fn order_by<I, E>(mut self, expressions: I) -> Self
2236 where
2237 I: IntoIterator<Item = E>,
2238 E: IntoExpr,
2239 {
2240 self.order_by = expressions
2241 .into_iter()
2242 .map(|e| {
2243 let expr = e.into_expr().0;
2244 match expr {
2245 Expression::Ordered(o) => *o,
2246 other => Ordered {
2247 this: other,
2248 desc: false,
2249 nulls_first: None,
2250 explicit_asc: false,
2251 with_fill: None,
2252 },
2253 }
2254 })
2255 .collect();
2256 self
2257 }
2258}
2259
2260pub trait IntoExpr {
2279 fn into_expr(self) -> Expr;
2281}
2282
2283impl IntoExpr for Expr {
2284 fn into_expr(self) -> Expr {
2285 self
2286 }
2287}
2288
2289impl IntoExpr for &str {
2290 fn into_expr(self) -> Expr {
2292 col(self)
2293 }
2294}
2295
2296impl IntoExpr for String {
2297 fn into_expr(self) -> Expr {
2299 col(&self)
2300 }
2301}
2302
2303impl IntoExpr for Expression {
2304 fn into_expr(self) -> Expr {
2306 Expr(self)
2307 }
2308}
2309
2310pub trait IntoLiteral {
2325 fn into_literal(self) -> Expr;
2327}
2328
2329impl IntoLiteral for &str {
2330 fn into_literal(self) -> Expr {
2332 Expr(Expression::Literal(Box::new(Literal::String(
2333 self.to_string(),
2334 ))))
2335 }
2336}
2337
2338impl IntoLiteral for String {
2339 fn into_literal(self) -> Expr {
2341 Expr(Expression::Literal(Box::new(Literal::String(self))))
2342 }
2343}
2344
2345impl IntoLiteral for i64 {
2346 fn into_literal(self) -> Expr {
2348 Expr(Expression::Literal(Box::new(Literal::Number(
2349 self.to_string(),
2350 ))))
2351 }
2352}
2353
2354impl IntoLiteral for i32 {
2355 fn into_literal(self) -> Expr {
2357 Expr(Expression::Literal(Box::new(Literal::Number(
2358 self.to_string(),
2359 ))))
2360 }
2361}
2362
2363impl IntoLiteral for usize {
2364 fn into_literal(self) -> Expr {
2366 Expr(Expression::Literal(Box::new(Literal::Number(
2367 self.to_string(),
2368 ))))
2369 }
2370}
2371
2372impl IntoLiteral for f64 {
2373 fn into_literal(self) -> Expr {
2375 Expr(Expression::Literal(Box::new(Literal::Number(
2376 self.to_string(),
2377 ))))
2378 }
2379}
2380
2381impl IntoLiteral for bool {
2382 fn into_literal(self) -> Expr {
2384 Expr(Expression::Boolean(BooleanLiteral { value: self }))
2385 }
2386}
2387
2388fn binary_op(left: Expression, right: Expression) -> BinaryOp {
2393 BinaryOp {
2394 left,
2395 right,
2396 left_comments: Vec::new(),
2397 operator_comments: Vec::new(),
2398 trailing_comments: Vec::new(),
2399 inferred_type: None,
2400 }
2401}
2402
2403pub fn merge_into(target: &str) -> MergeBuilder {
2425 MergeBuilder {
2426 target: Expression::Table(Box::new(builder_table_ref(target))),
2427 using: None,
2428 on: None,
2429 whens: Vec::new(),
2430 }
2431}
2432
2433pub struct MergeBuilder {
2437 target: Expression,
2438 using: Option<Expression>,
2439 on: Option<Expression>,
2440 whens: Vec<Expression>,
2441}
2442
2443impl MergeBuilder {
2444 pub fn using(mut self, source: &str, on: Expr) -> Self {
2446 self.using = Some(Expression::Table(Box::new(builder_table_ref(source))));
2447 self.on = Some(on.0);
2448 self
2449 }
2450
2451 pub fn when_matched_update(mut self, assignments: Vec<(&str, Expr)>) -> Self {
2453 let eqs: Vec<Expression> = assignments
2454 .into_iter()
2455 .map(|(col_name, val)| {
2456 Expression::Eq(Box::new(BinaryOp {
2457 left: Expression::boxed_column(Column {
2458 name: builder_identifier(col_name),
2459 table: None,
2460 join_mark: false,
2461 trailing_comments: Vec::new(),
2462 span: None,
2463 inferred_type: None,
2464 }),
2465 right: val.0,
2466 left_comments: Vec::new(),
2467 operator_comments: Vec::new(),
2468 trailing_comments: Vec::new(),
2469 inferred_type: None,
2470 }))
2471 })
2472 .collect();
2473
2474 let action = Expression::Tuple(Box::new(Tuple {
2475 expressions: vec![
2476 Expression::Var(Box::new(Var {
2477 this: "UPDATE".to_string(),
2478 })),
2479 Expression::Tuple(Box::new(Tuple { expressions: eqs })),
2480 ],
2481 }));
2482
2483 let when = Expression::When(Box::new(When {
2484 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2485 value: true,
2486 }))),
2487 source: None,
2488 condition: None,
2489 then: Box::new(action),
2490 }));
2491 self.whens.push(when);
2492 self
2493 }
2494
2495 pub fn when_matched_update_where(
2497 mut self,
2498 condition: Expr,
2499 assignments: Vec<(&str, Expr)>,
2500 ) -> Self {
2501 let eqs: Vec<Expression> = assignments
2502 .into_iter()
2503 .map(|(col_name, val)| {
2504 Expression::Eq(Box::new(BinaryOp {
2505 left: Expression::boxed_column(Column {
2506 name: builder_identifier(col_name),
2507 table: None,
2508 join_mark: false,
2509 trailing_comments: Vec::new(),
2510 span: None,
2511 inferred_type: None,
2512 }),
2513 right: val.0,
2514 left_comments: Vec::new(),
2515 operator_comments: Vec::new(),
2516 trailing_comments: Vec::new(),
2517 inferred_type: None,
2518 }))
2519 })
2520 .collect();
2521
2522 let action = Expression::Tuple(Box::new(Tuple {
2523 expressions: vec![
2524 Expression::Var(Box::new(Var {
2525 this: "UPDATE".to_string(),
2526 })),
2527 Expression::Tuple(Box::new(Tuple { expressions: eqs })),
2528 ],
2529 }));
2530
2531 let when = Expression::When(Box::new(When {
2532 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2533 value: true,
2534 }))),
2535 source: None,
2536 condition: Some(Box::new(condition.0)),
2537 then: Box::new(action),
2538 }));
2539 self.whens.push(when);
2540 self
2541 }
2542
2543 pub fn when_matched_delete(mut self) -> Self {
2545 let action = Expression::Var(Box::new(Var {
2546 this: "DELETE".to_string(),
2547 }));
2548
2549 let when = Expression::When(Box::new(When {
2550 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2551 value: true,
2552 }))),
2553 source: None,
2554 condition: None,
2555 then: Box::new(action),
2556 }));
2557 self.whens.push(when);
2558 self
2559 }
2560
2561 pub fn when_not_matched_insert(mut self, columns: &[&str], values: Vec<Expr>) -> Self {
2563 let col_exprs: Vec<Expression> = columns
2564 .iter()
2565 .map(|c| {
2566 Expression::boxed_column(Column {
2567 name: builder_identifier(c),
2568 table: None,
2569 join_mark: false,
2570 trailing_comments: Vec::new(),
2571 span: None,
2572 inferred_type: None,
2573 })
2574 })
2575 .collect();
2576 let val_exprs: Vec<Expression> = values.into_iter().map(|v| v.0).collect();
2577
2578 let action = Expression::Tuple(Box::new(Tuple {
2579 expressions: vec![
2580 Expression::Var(Box::new(Var {
2581 this: "INSERT".to_string(),
2582 })),
2583 Expression::Tuple(Box::new(Tuple {
2584 expressions: col_exprs,
2585 })),
2586 Expression::Tuple(Box::new(Tuple {
2587 expressions: val_exprs,
2588 })),
2589 ],
2590 }));
2591
2592 let when = Expression::When(Box::new(When {
2593 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2594 value: false,
2595 }))),
2596 source: None,
2597 condition: None,
2598 then: Box::new(action),
2599 }));
2600 self.whens.push(when);
2601 self
2602 }
2603
2604 pub fn build(self) -> Expression {
2606 let whens_expr = Expression::Whens(Box::new(Whens {
2607 expressions: self.whens,
2608 }));
2609
2610 Expression::Merge(Box::new(Merge {
2611 this: Box::new(self.target),
2612 using: Box::new(
2613 self.using
2614 .unwrap_or(Expression::Null(crate::expressions::Null)),
2615 ),
2616 on: self.on.map(Box::new),
2617 using_cond: None,
2618 whens: Some(Box::new(whens_expr)),
2619 with_: None,
2620 returning: None,
2621 }))
2622 }
2623
2624 pub fn to_sql(self) -> String {
2626 Generator::sql(&self.build()).unwrap_or_default()
2627 }
2628}
2629
2630fn parse_simple_data_type(name: &str) -> DataType {
2631 let upper = name.trim().to_uppercase();
2632 match upper.as_str() {
2633 "INT" | "INTEGER" => DataType::Int {
2634 length: None,
2635 integer_spelling: upper == "INTEGER",
2636 },
2637 "BIGINT" => DataType::BigInt { length: None },
2638 "SMALLINT" => DataType::SmallInt { length: None },
2639 "TINYINT" => DataType::TinyInt { length: None },
2640 "FLOAT" => DataType::Float {
2641 precision: None,
2642 scale: None,
2643 real_spelling: false,
2644 },
2645 "DOUBLE" => DataType::Double {
2646 precision: None,
2647 scale: None,
2648 },
2649 "BOOLEAN" | "BOOL" => DataType::Boolean,
2650 "TEXT" => DataType::Text,
2651 "DATE" => DataType::Date,
2652 "TIMESTAMP" => DataType::Timestamp {
2653 precision: None,
2654 timezone: false,
2655 },
2656 "VARCHAR" => DataType::VarChar {
2657 length: None,
2658 parenthesized_length: false,
2659 },
2660 "CHAR" => DataType::Char { length: None },
2661 _ => {
2662 if let Ok(ast) =
2664 crate::parser::Parser::parse_sql(&format!("SELECT CAST(x AS {})", name))
2665 {
2666 if let Expression::Select(s) = &ast[0] {
2667 if let Some(Expression::Cast(c)) = s.expressions.first() {
2668 return c.to.clone();
2669 }
2670 }
2671 }
2672 DataType::Custom {
2674 name: name.to_string(),
2675 }
2676 }
2677 }
2678}
2679
2680#[cfg(test)]
2681mod tests {
2682 use super::*;
2683
2684 #[test]
2685 fn test_simple_select() {
2686 let sql = select(["id", "name"]).from("users").to_sql();
2687 assert_eq!(sql, "SELECT id, name FROM users");
2688 }
2689
2690 #[test]
2691 fn test_builder_quotes_unsafe_identifier_tokens() {
2692 let sql = select(["Name; DROP TABLE titanic"]).to_sql();
2693 assert_eq!(sql, r#"SELECT "Name; DROP TABLE titanic""#);
2694 }
2695
2696 #[test]
2697 fn test_builder_string_literal_requires_lit() {
2698 let sql = select([lit("Name; DROP TABLE titanic")]).to_sql();
2699 assert_eq!(sql, "SELECT 'Name; DROP TABLE titanic'");
2700 }
2701
2702 #[test]
2703 fn test_builder_quotes_unsafe_table_name_tokens() {
2704 let sql = select(["id"]).from("users; DROP TABLE x").to_sql();
2705 assert_eq!(sql, r#"SELECT id FROM "users; DROP TABLE x""#);
2706 }
2707
2708 #[test]
2709 fn test_select_star() {
2710 let sql = select([star()]).from("users").to_sql();
2711 assert_eq!(sql, "SELECT * FROM users");
2712 }
2713
2714 #[test]
2715 fn test_select_with_where() {
2716 let sql = select(["id", "name"])
2717 .from("users")
2718 .where_(col("age").gt(lit(18)))
2719 .to_sql();
2720 assert_eq!(sql, "SELECT id, name FROM users WHERE age > 18");
2721 }
2722
2723 #[test]
2724 fn test_select_with_join() {
2725 let sql = select(["u.id", "o.amount"])
2726 .from("users")
2727 .join("orders", col("u.id").eq(col("o.user_id")))
2728 .to_sql();
2729 assert_eq!(
2730 sql,
2731 "SELECT u.id, o.amount FROM users JOIN orders ON u.id = o.user_id"
2732 );
2733 }
2734
2735 #[test]
2736 fn test_select_with_group_by_having() {
2737 let sql = select([col("dept"), func("COUNT", [star()]).alias("cnt")])
2738 .from("employees")
2739 .group_by(["dept"])
2740 .having(func("COUNT", [star()]).gt(lit(5)))
2741 .to_sql();
2742 assert_eq!(
2743 sql,
2744 "SELECT dept, COUNT(*) AS cnt FROM employees GROUP BY dept HAVING COUNT(*) > 5"
2745 );
2746 }
2747
2748 #[test]
2749 fn test_select_with_order_limit_offset() {
2750 let sql = select(["id", "name"])
2751 .from("users")
2752 .order_by(["name"])
2753 .limit(10)
2754 .offset(20)
2755 .to_sql();
2756 assert_eq!(
2757 sql,
2758 "SELECT id, name FROM users ORDER BY name LIMIT 10 OFFSET 20"
2759 );
2760 }
2761
2762 #[test]
2763 fn test_select_distinct() {
2764 let sql = select(["name"]).from("users").distinct().to_sql();
2765 assert_eq!(sql, "SELECT DISTINCT name FROM users");
2766 }
2767
2768 #[test]
2769 fn test_insert_values() {
2770 let sql = insert_into("users")
2771 .columns(["id", "name"])
2772 .values([lit(1), lit("Alice")])
2773 .values([lit(2), lit("Bob")])
2774 .to_sql();
2775 assert_eq!(
2776 sql,
2777 "INSERT INTO users (id, name) VALUES (1, 'Alice'), (2, 'Bob')"
2778 );
2779 }
2780
2781 #[test]
2782 fn test_insert_select() {
2783 let sql = insert_into("archive")
2784 .columns(["id", "name"])
2785 .query(select(["id", "name"]).from("users"))
2786 .to_sql();
2787 assert_eq!(
2788 sql,
2789 "INSERT INTO archive (id, name) SELECT id, name FROM users"
2790 );
2791 }
2792
2793 #[test]
2794 fn test_update() {
2795 let sql = update("users")
2796 .set("name", lit("Bob"))
2797 .set("age", lit(30))
2798 .where_(col("id").eq(lit(1)))
2799 .to_sql();
2800 assert_eq!(sql, "UPDATE users SET name = 'Bob', age = 30 WHERE id = 1");
2801 }
2802
2803 #[test]
2804 fn test_delete() {
2805 let sql = delete("users").where_(col("id").eq(lit(1))).to_sql();
2806 assert_eq!(sql, "DELETE FROM users WHERE id = 1");
2807 }
2808
2809 #[test]
2810 fn test_complex_where() {
2811 let sql = select(["id"])
2812 .from("users")
2813 .where_(
2814 col("age")
2815 .gte(lit(18))
2816 .and(col("active").eq(boolean(true)))
2817 .and(col("name").like(lit("%test%"))),
2818 )
2819 .to_sql();
2820 assert_eq!(
2821 sql,
2822 "SELECT id FROM users WHERE age >= 18 AND active = TRUE AND name LIKE '%test%'"
2823 );
2824 }
2825
2826 #[test]
2827 fn test_in_list() {
2828 let sql = select(["id"])
2829 .from("users")
2830 .where_(col("status").in_list([lit("active"), lit("pending")]))
2831 .to_sql();
2832 assert_eq!(
2833 sql,
2834 "SELECT id FROM users WHERE status IN ('active', 'pending')"
2835 );
2836 }
2837
2838 #[test]
2839 fn test_between() {
2840 let sql = select(["id"])
2841 .from("orders")
2842 .where_(col("amount").between(lit(100), lit(500)))
2843 .to_sql();
2844 assert_eq!(
2845 sql,
2846 "SELECT id FROM orders WHERE amount BETWEEN 100 AND 500"
2847 );
2848 }
2849
2850 #[test]
2851 fn test_is_null() {
2852 let sql = select(["id"])
2853 .from("users")
2854 .where_(col("email").is_null())
2855 .to_sql();
2856 assert_eq!(sql, "SELECT id FROM users WHERE email IS NULL");
2857 }
2858
2859 #[test]
2860 fn test_arithmetic() {
2861 let sql = select([col("price").mul(col("quantity")).alias("total")])
2862 .from("items")
2863 .to_sql();
2864 assert_eq!(sql, "SELECT price * quantity AS total FROM items");
2865 }
2866
2867 #[test]
2868 fn test_cast() {
2869 let sql = select([col("id").cast("VARCHAR")]).from("users").to_sql();
2870 assert_eq!(sql, "SELECT CAST(id AS VARCHAR) FROM users");
2871 }
2872
2873 #[test]
2874 fn test_from_starter() {
2875 let sql = from("users").select_cols(["id", "name"]).to_sql();
2876 assert_eq!(sql, "SELECT id, name FROM users");
2877 }
2878
2879 #[test]
2880 fn test_qualified_column() {
2881 let sql = select([col("u.id"), col("u.name")]).from("users").to_sql();
2882 assert_eq!(sql, "SELECT u.id, u.name FROM users");
2883 }
2884
2885 #[test]
2886 fn test_not_condition() {
2887 let sql = select(["id"])
2888 .from("users")
2889 .where_(not(col("active").eq(boolean(true))))
2890 .to_sql();
2891 assert_eq!(sql, "SELECT id FROM users WHERE NOT active = TRUE");
2892 }
2893
2894 #[test]
2895 fn test_order_by_desc() {
2896 let sql = select(["id", "name"])
2897 .from("users")
2898 .order_by([col("name").desc()])
2899 .to_sql();
2900 assert_eq!(sql, "SELECT id, name FROM users ORDER BY name DESC");
2901 }
2902
2903 #[test]
2904 fn test_left_join() {
2905 let sql = select(["u.id", "o.amount"])
2906 .from("users")
2907 .left_join("orders", col("u.id").eq(col("o.user_id")))
2908 .to_sql();
2909 assert_eq!(
2910 sql,
2911 "SELECT u.id, o.amount FROM users LEFT JOIN orders ON u.id = o.user_id"
2912 );
2913 }
2914
2915 #[test]
2916 fn test_build_returns_expression() {
2917 let expr = select(["id"]).from("users").build();
2918 assert!(matches!(expr, Expression::Select(_)));
2919 }
2920
2921 #[test]
2922 fn test_expr_interop() {
2923 let age_check = col("age").gt(lit(18));
2925 let sql = select([col("id"), age_check.alias("is_adult")])
2926 .from("users")
2927 .to_sql();
2928 assert_eq!(sql, "SELECT id, age > 18 AS is_adult FROM users");
2929 }
2930
2931 #[test]
2934 fn test_sql_expr_simple() {
2935 let expr = sql_expr("age > 18");
2936 let sql = select(["id"]).from("users").where_(expr).to_sql();
2937 assert_eq!(sql, "SELECT id FROM users WHERE age > 18");
2938 }
2939
2940 #[test]
2941 fn test_sql_expr_compound() {
2942 let expr = sql_expr("a > 1 AND b < 10");
2943 let sql = select(["*"]).from("t").where_(expr).to_sql();
2944 assert_eq!(sql, "SELECT * FROM t WHERE a > 1 AND b < 10");
2945 }
2946
2947 #[test]
2948 fn test_sql_expr_function() {
2949 let expr = sql_expr("COALESCE(a, b, 0)");
2950 let sql = select([expr.alias("val")]).from("t").to_sql();
2951 assert_eq!(sql, "SELECT COALESCE(a, b, 0) AS val FROM t");
2952 }
2953
2954 #[test]
2955 fn test_condition_alias() {
2956 let cond = condition("x > 0");
2957 let sql = select(["*"]).from("t").where_(cond).to_sql();
2958 assert_eq!(sql, "SELECT * FROM t WHERE x > 0");
2959 }
2960
2961 #[test]
2964 fn test_ilike() {
2965 let sql = select(["id"])
2966 .from("users")
2967 .where_(col("name").ilike(lit("%test%")))
2968 .to_sql();
2969 assert_eq!(sql, "SELECT id FROM users WHERE name ILIKE '%test%'");
2970 }
2971
2972 #[test]
2973 fn test_rlike() {
2974 let sql = select(["id"])
2975 .from("users")
2976 .where_(col("name").rlike(lit("^[A-Z]")))
2977 .to_sql();
2978 assert_eq!(
2979 sql,
2980 "SELECT id FROM users WHERE REGEXP_LIKE(name, '^[A-Z]')"
2981 );
2982 }
2983
2984 #[test]
2985 fn test_not_in() {
2986 let sql = select(["id"])
2987 .from("users")
2988 .where_(col("status").not_in([lit("deleted"), lit("banned")]))
2989 .to_sql();
2990 assert_eq!(
2991 sql,
2992 "SELECT id FROM users WHERE NOT status IN ('deleted', 'banned')"
2993 );
2994 }
2995
2996 #[test]
2999 fn test_case_searched() {
3000 let expr = case()
3001 .when(col("x").gt(lit(0)), lit("positive"))
3002 .when(col("x").eq(lit(0)), lit("zero"))
3003 .else_(lit("negative"))
3004 .build();
3005 let sql = select([expr.alias("label")]).from("t").to_sql();
3006 assert_eq!(
3007 sql,
3008 "SELECT CASE WHEN x > 0 THEN 'positive' WHEN x = 0 THEN 'zero' ELSE 'negative' END AS label FROM t"
3009 );
3010 }
3011
3012 #[test]
3013 fn test_case_simple() {
3014 let expr = case_of(col("status"))
3015 .when(lit(1), lit("active"))
3016 .when(lit(0), lit("inactive"))
3017 .build();
3018 let sql = select([expr.alias("status_label")]).from("t").to_sql();
3019 assert_eq!(
3020 sql,
3021 "SELECT CASE status WHEN 1 THEN 'active' WHEN 0 THEN 'inactive' END AS status_label FROM t"
3022 );
3023 }
3024
3025 #[test]
3026 fn test_case_no_else() {
3027 let expr = case().when(col("x").gt(lit(0)), lit("yes")).build();
3028 let sql = select([expr]).from("t").to_sql();
3029 assert_eq!(sql, "SELECT CASE WHEN x > 0 THEN 'yes' END FROM t");
3030 }
3031
3032 #[test]
3035 fn test_subquery_in_from() {
3036 let inner = select(["id", "name"])
3037 .from("users")
3038 .where_(col("active").eq(boolean(true)));
3039 let outer = select(["sub.id"])
3040 .from_expr(subquery(inner, "sub"))
3041 .to_sql();
3042 assert_eq!(
3043 outer,
3044 "SELECT sub.id FROM (SELECT id, name FROM users WHERE active = TRUE) AS sub"
3045 );
3046 }
3047
3048 #[test]
3049 fn test_subquery_in_join() {
3050 let inner = select([col("user_id"), func("SUM", [col("amount")]).alias("total")])
3051 .from("orders")
3052 .group_by(["user_id"]);
3053 let sql = select(["u.name", "o.total"])
3054 .from("users")
3055 .join("orders", col("u.id").eq(col("o.user_id")))
3056 .to_sql();
3057 assert!(sql.contains("JOIN"));
3058 let _sub = subquery(inner, "o");
3060 }
3061
3062 #[test]
3065 fn test_union() {
3066 let sql = union(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3067 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
3068 }
3069
3070 #[test]
3071 fn test_union_all() {
3072 let sql = union_all(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3073 assert_eq!(sql, "SELECT id FROM a UNION ALL SELECT id FROM b");
3074 }
3075
3076 #[test]
3077 fn test_intersect_builder() {
3078 let sql = intersect(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3079 assert_eq!(sql, "SELECT id FROM a INTERSECT SELECT id FROM b");
3080 }
3081
3082 #[test]
3083 fn test_except_builder() {
3084 let sql = except_(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3085 assert_eq!(sql, "SELECT id FROM a EXCEPT SELECT id FROM b");
3086 }
3087
3088 #[test]
3089 fn test_union_with_order_limit() {
3090 let sql = union(select(["id"]).from("a"), select(["id"]).from("b"))
3091 .order_by(["id"])
3092 .limit(10)
3093 .to_sql();
3094 assert!(sql.contains("UNION"));
3095 assert!(sql.contains("ORDER BY"));
3096 assert!(sql.contains("LIMIT"));
3097 }
3098
3099 #[test]
3100 fn test_select_builder_union() {
3101 let sql = select(["id"])
3102 .from("a")
3103 .union(select(["id"]).from("b"))
3104 .to_sql();
3105 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
3106 }
3107
3108 #[test]
3111 fn test_qualify() {
3112 let sql = select(["id", "name"])
3113 .from("users")
3114 .qualify(col("rn").eq(lit(1)))
3115 .to_sql();
3116 assert_eq!(sql, "SELECT id, name FROM users QUALIFY rn = 1");
3117 }
3118
3119 #[test]
3120 fn test_right_join() {
3121 let sql = select(["u.id", "o.amount"])
3122 .from("users")
3123 .right_join("orders", col("u.id").eq(col("o.user_id")))
3124 .to_sql();
3125 assert_eq!(
3126 sql,
3127 "SELECT u.id, o.amount FROM users RIGHT JOIN orders ON u.id = o.user_id"
3128 );
3129 }
3130
3131 #[test]
3132 fn test_cross_join() {
3133 let sql = select(["a.x", "b.y"]).from("a").cross_join("b").to_sql();
3134 assert_eq!(sql, "SELECT a.x, b.y FROM a CROSS JOIN b");
3135 }
3136
3137 #[test]
3138 fn test_lateral_view() {
3139 let sql = select(["id", "col_val"])
3140 .from("t")
3141 .lateral_view(func("EXPLODE", [col("arr")]), "lv", ["col_val"])
3142 .to_sql();
3143 assert!(sql.contains("LATERAL VIEW"));
3144 assert!(sql.contains("EXPLODE"));
3145 }
3146
3147 #[test]
3148 fn test_window_clause() {
3149 let sql = select(["id"])
3150 .from("t")
3151 .window(
3152 "w",
3153 WindowDefBuilder::new()
3154 .partition_by(["dept"])
3155 .order_by(["salary"]),
3156 )
3157 .to_sql();
3158 assert!(sql.contains("WINDOW"));
3159 assert!(sql.contains("PARTITION BY"));
3160 }
3161
3162 #[test]
3165 fn test_xor() {
3166 let sql = select(["*"])
3167 .from("t")
3168 .where_(col("a").xor(col("b")))
3169 .to_sql();
3170 assert_eq!(sql, "SELECT * FROM t WHERE a XOR b");
3171 }
3172
3173 #[test]
3176 fn test_for_update() {
3177 let sql = select(["id"]).from("t").for_update().to_sql();
3178 assert_eq!(sql, "SELECT id FROM t FOR UPDATE");
3179 }
3180
3181 #[test]
3182 fn test_for_share() {
3183 let sql = select(["id"]).from("t").for_share().to_sql();
3184 assert_eq!(sql, "SELECT id FROM t FOR SHARE");
3185 }
3186
3187 #[test]
3190 fn test_hint() {
3191 let sql = select(["*"]).from("t").hint("FULL(t)").to_sql();
3192 assert!(sql.contains("FULL(t)"), "Expected hint in: {}", sql);
3193 }
3194
3195 #[test]
3198 fn test_ctas() {
3199 let expr = select(["*"]).from("t").ctas("new_table");
3200 let sql = Generator::sql(&expr).unwrap();
3201 assert_eq!(sql, "CREATE TABLE new_table AS SELECT * FROM t");
3202 }
3203
3204 #[test]
3207 fn test_merge_update_insert() {
3208 let sql = merge_into("target")
3209 .using("source", col("target.id").eq(col("source.id")))
3210 .when_matched_update(vec![("name", col("source.name"))])
3211 .when_not_matched_insert(&["id", "name"], vec![col("source.id"), col("source.name")])
3212 .to_sql();
3213 assert!(
3214 sql.contains("MERGE INTO"),
3215 "Expected MERGE INTO in: {}",
3216 sql
3217 );
3218 assert!(sql.contains("USING"), "Expected USING in: {}", sql);
3219 assert!(
3220 sql.contains("WHEN MATCHED"),
3221 "Expected WHEN MATCHED in: {}",
3222 sql
3223 );
3224 assert!(
3225 sql.contains("UPDATE SET"),
3226 "Expected UPDATE SET in: {}",
3227 sql
3228 );
3229 assert!(
3230 sql.contains("WHEN NOT MATCHED"),
3231 "Expected WHEN NOT MATCHED in: {}",
3232 sql
3233 );
3234 assert!(sql.contains("INSERT"), "Expected INSERT in: {}", sql);
3235 }
3236
3237 #[test]
3238 fn test_merge_delete() {
3239 let sql = merge_into("target")
3240 .using("source", col("target.id").eq(col("source.id")))
3241 .when_matched_delete()
3242 .to_sql();
3243 assert!(
3244 sql.contains("MERGE INTO"),
3245 "Expected MERGE INTO in: {}",
3246 sql
3247 );
3248 assert!(
3249 sql.contains("WHEN MATCHED THEN DELETE"),
3250 "Expected WHEN MATCHED THEN DELETE in: {}",
3251 sql
3252 );
3253 }
3254
3255 #[test]
3256 fn test_merge_with_condition() {
3257 let sql = merge_into("target")
3258 .using("source", col("target.id").eq(col("source.id")))
3259 .when_matched_update_where(
3260 col("source.active").eq(boolean(true)),
3261 vec![("name", col("source.name"))],
3262 )
3263 .to_sql();
3264 assert!(
3265 sql.contains("MERGE INTO"),
3266 "Expected MERGE INTO in: {}",
3267 sql
3268 );
3269 assert!(
3270 sql.contains("AND source.active = TRUE"),
3271 "Expected condition in: {}",
3272 sql
3273 );
3274 }
3275}