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