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 alias_explicit_as: false,
298 alias_keyword: None,
299 pre_alias_comments: Vec::new(),
300 trailing_comments: Vec::new(),
301 inferred_type: None,
302 })))
303}
304
305pub fn sql_expr(sql: &str) -> Expr {
329 let wrapped = format!("SELECT {}", sql);
330 let ast = Parser::parse_sql(&wrapped).expect("sql_expr: failed to parse SQL expression");
331 if let Expression::Select(s) = &ast[0] {
332 if let Some(first) = s.expressions.first() {
333 return Expr(first.clone());
334 }
335 }
336 panic!("sql_expr: failed to extract expression from parsed SQL");
337}
338
339pub fn condition(sql: &str) -> Expr {
348 sql_expr(sql)
349}
350
351pub fn count(expr: Expr) -> Expr {
359 Expr(Expression::Count(Box::new(CountFunc {
360 this: Some(expr.0),
361 star: false,
362 distinct: false,
363 filter: None,
364 ignore_nulls: None,
365 original_name: None,
366 inferred_type: None,
367 })))
368}
369
370pub fn count_star() -> Expr {
372 Expr(Expression::Count(Box::new(CountFunc {
373 this: None,
374 star: true,
375 distinct: false,
376 filter: None,
377 ignore_nulls: None,
378 original_name: None,
379 inferred_type: None,
380 })))
381}
382
383pub fn count_distinct(expr: Expr) -> Expr {
385 Expr(Expression::Count(Box::new(CountFunc {
386 this: Some(expr.0),
387 star: false,
388 distinct: true,
389 filter: None,
390 ignore_nulls: None,
391 original_name: None,
392 inferred_type: None,
393 })))
394}
395
396pub fn sum(expr: Expr) -> Expr {
398 Expr(Expression::Sum(Box::new(AggFunc {
399 this: expr.0,
400 distinct: false,
401 filter: None,
402 order_by: vec![],
403 name: None,
404 ignore_nulls: None,
405 having_max: None,
406 limit: None,
407 inferred_type: None,
408 })))
409}
410
411pub fn avg(expr: Expr) -> Expr {
413 Expr(Expression::Avg(Box::new(AggFunc {
414 this: expr.0,
415 distinct: false,
416 filter: None,
417 order_by: vec![],
418 name: None,
419 ignore_nulls: None,
420 having_max: None,
421 limit: None,
422 inferred_type: None,
423 })))
424}
425
426pub fn min_(expr: Expr) -> Expr {
428 Expr(Expression::Min(Box::new(AggFunc {
429 this: expr.0,
430 distinct: false,
431 filter: None,
432 order_by: vec![],
433 name: None,
434 ignore_nulls: None,
435 having_max: None,
436 limit: None,
437 inferred_type: None,
438 })))
439}
440
441pub fn max_(expr: Expr) -> Expr {
443 Expr(Expression::Max(Box::new(AggFunc {
444 this: expr.0,
445 distinct: false,
446 filter: None,
447 order_by: vec![],
448 name: None,
449 ignore_nulls: None,
450 having_max: None,
451 limit: None,
452 inferred_type: None,
453 })))
454}
455
456pub fn approx_distinct(expr: Expr) -> Expr {
458 Expr(Expression::ApproxDistinct(Box::new(AggFunc {
459 this: expr.0,
460 distinct: false,
461 filter: None,
462 order_by: vec![],
463 name: None,
464 ignore_nulls: None,
465 having_max: None,
466 limit: None,
467 inferred_type: None,
468 })))
469}
470
471pub fn upper(expr: Expr) -> Expr {
475 Expr(Expression::Upper(Box::new(UnaryFunc::new(expr.0))))
476}
477
478pub fn lower(expr: Expr) -> Expr {
480 Expr(Expression::Lower(Box::new(UnaryFunc::new(expr.0))))
481}
482
483pub fn length(expr: Expr) -> Expr {
485 Expr(Expression::Length(Box::new(UnaryFunc::new(expr.0))))
486}
487
488pub fn trim(expr: Expr) -> Expr {
490 Expr(Expression::Trim(Box::new(TrimFunc {
491 this: expr.0,
492 characters: None,
493 position: TrimPosition::Both,
494 sql_standard_syntax: false,
495 position_explicit: false,
496 })))
497}
498
499pub fn ltrim(expr: Expr) -> Expr {
501 Expr(Expression::LTrim(Box::new(UnaryFunc::new(expr.0))))
502}
503
504pub fn rtrim(expr: Expr) -> Expr {
506 Expr(Expression::RTrim(Box::new(UnaryFunc::new(expr.0))))
507}
508
509pub fn reverse(expr: Expr) -> Expr {
511 Expr(Expression::Reverse(Box::new(UnaryFunc::new(expr.0))))
512}
513
514pub fn initcap(expr: Expr) -> Expr {
516 Expr(Expression::Initcap(Box::new(UnaryFunc::new(expr.0))))
517}
518
519pub fn substring(expr: Expr, start: Expr, len: Option<Expr>) -> Expr {
521 Expr(Expression::Substring(Box::new(SubstringFunc {
522 this: expr.0,
523 start: start.0,
524 length: len.map(|l| l.0),
525 from_for_syntax: false,
526 })))
527}
528
529pub fn replace_(expr: Expr, old: Expr, new: Expr) -> Expr {
532 Expr(Expression::Replace(Box::new(ReplaceFunc {
533 this: expr.0,
534 old: old.0,
535 new: new.0,
536 })))
537}
538
539pub fn concat_ws(separator: Expr, exprs: impl IntoIterator<Item = Expr>) -> Expr {
541 Expr(Expression::ConcatWs(Box::new(ConcatWs {
542 separator: separator.0,
543 expressions: exprs.into_iter().map(|e| e.0).collect(),
544 })))
545}
546
547pub fn coalesce(exprs: impl IntoIterator<Item = Expr>) -> Expr {
551 Expr(Expression::Coalesce(Box::new(VarArgFunc {
552 expressions: exprs.into_iter().map(|e| e.0).collect(),
553 original_name: None,
554 inferred_type: None,
555 })))
556}
557
558pub fn null_if(expr1: Expr, expr2: Expr) -> Expr {
560 Expr(Expression::NullIf(Box::new(BinaryFunc {
561 this: expr1.0,
562 expression: expr2.0,
563 original_name: None,
564 inferred_type: None,
565 })))
566}
567
568pub fn if_null(expr: Expr, fallback: Expr) -> Expr {
570 Expr(Expression::IfNull(Box::new(BinaryFunc {
571 this: expr.0,
572 expression: fallback.0,
573 original_name: None,
574 inferred_type: None,
575 })))
576}
577
578pub fn abs(expr: Expr) -> Expr {
582 Expr(Expression::Abs(Box::new(UnaryFunc::new(expr.0))))
583}
584
585pub fn round(expr: Expr, decimals: Option<Expr>) -> Expr {
587 Expr(Expression::Round(Box::new(RoundFunc {
588 this: expr.0,
589 decimals: decimals.map(|d| d.0),
590 })))
591}
592
593pub fn floor(expr: Expr) -> Expr {
595 Expr(Expression::Floor(Box::new(FloorFunc {
596 this: expr.0,
597 scale: None,
598 to: None,
599 })))
600}
601
602pub fn ceil(expr: Expr) -> Expr {
604 Expr(Expression::Ceil(Box::new(CeilFunc {
605 this: expr.0,
606 decimals: None,
607 to: None,
608 })))
609}
610
611pub fn power(base: Expr, exponent: Expr) -> Expr {
613 Expr(Expression::Power(Box::new(BinaryFunc {
614 this: base.0,
615 expression: exponent.0,
616 original_name: None,
617 inferred_type: None,
618 })))
619}
620
621pub fn sqrt(expr: Expr) -> Expr {
623 Expr(Expression::Sqrt(Box::new(UnaryFunc::new(expr.0))))
624}
625
626pub fn ln(expr: Expr) -> Expr {
628 Expr(Expression::Ln(Box::new(UnaryFunc::new(expr.0))))
629}
630
631pub fn exp_(expr: Expr) -> Expr {
633 Expr(Expression::Exp(Box::new(UnaryFunc::new(expr.0))))
634}
635
636pub fn sign(expr: Expr) -> Expr {
638 Expr(Expression::Sign(Box::new(UnaryFunc::new(expr.0))))
639}
640
641pub fn greatest(exprs: impl IntoIterator<Item = Expr>) -> Expr {
643 Expr(Expression::Greatest(Box::new(VarArgFunc {
644 expressions: exprs.into_iter().map(|e| e.0).collect(),
645 original_name: None,
646 inferred_type: None,
647 })))
648}
649
650pub fn least(exprs: impl IntoIterator<Item = Expr>) -> Expr {
652 Expr(Expression::Least(Box::new(VarArgFunc {
653 expressions: exprs.into_iter().map(|e| e.0).collect(),
654 original_name: None,
655 inferred_type: None,
656 })))
657}
658
659pub fn current_date_() -> Expr {
663 Expr(Expression::CurrentDate(CurrentDate))
664}
665
666pub fn current_time_() -> Expr {
668 Expr(Expression::CurrentTime(CurrentTime { precision: None }))
669}
670
671pub fn current_timestamp_() -> Expr {
673 Expr(Expression::CurrentTimestamp(CurrentTimestamp {
674 precision: None,
675 sysdate: false,
676 }))
677}
678
679pub fn extract_(field: &str, expr: Expr) -> Expr {
681 Expr(Expression::Extract(Box::new(ExtractFunc {
682 this: expr.0,
683 field: parse_datetime_field(field),
684 })))
685}
686
687fn parse_datetime_field(field: &str) -> DateTimeField {
689 match field.to_uppercase().as_str() {
690 "YEAR" => DateTimeField::Year,
691 "MONTH" => DateTimeField::Month,
692 "DAY" => DateTimeField::Day,
693 "HOUR" => DateTimeField::Hour,
694 "MINUTE" => DateTimeField::Minute,
695 "SECOND" => DateTimeField::Second,
696 "MILLISECOND" => DateTimeField::Millisecond,
697 "MICROSECOND" => DateTimeField::Microsecond,
698 "DOW" | "DAYOFWEEK" => DateTimeField::DayOfWeek,
699 "DOY" | "DAYOFYEAR" => DateTimeField::DayOfYear,
700 "WEEK" => DateTimeField::Week,
701 "QUARTER" => DateTimeField::Quarter,
702 "EPOCH" => DateTimeField::Epoch,
703 "TIMEZONE" => DateTimeField::Timezone,
704 "TIMEZONE_HOUR" => DateTimeField::TimezoneHour,
705 "TIMEZONE_MINUTE" => DateTimeField::TimezoneMinute,
706 "DATE" => DateTimeField::Date,
707 "TIME" => DateTimeField::Time,
708 other => DateTimeField::Custom(other.to_string()),
709 }
710}
711
712pub fn row_number() -> Expr {
716 Expr(Expression::RowNumber(RowNumber))
717}
718
719pub fn rank_() -> Expr {
721 Expr(Expression::Rank(Rank {
722 order_by: None,
723 args: vec![],
724 }))
725}
726
727pub fn dense_rank() -> Expr {
729 Expr(Expression::DenseRank(DenseRank { args: vec![] }))
730}
731
732pub fn select<I, E>(expressions: I) -> SelectBuilder
759where
760 I: IntoIterator<Item = E>,
761 E: IntoExpr,
762{
763 let mut builder = SelectBuilder::new();
764 for expr in expressions {
765 builder.select = builder.select.column(expr.into_expr().0);
766 }
767 builder
768}
769
770pub fn from(table_name: &str) -> SelectBuilder {
785 let mut builder = SelectBuilder::new();
786 builder.select.from = Some(From {
787 expressions: vec![Expression::Table(Box::new(builder_table_ref(table_name)))],
788 });
789 builder
790}
791
792pub fn delete(table_name: &str) -> DeleteBuilder {
805 DeleteBuilder {
806 delete: Delete {
807 table: builder_table_ref(table_name),
808 hint: None,
809 on_cluster: None,
810 alias: None,
811 alias_explicit_as: false,
812 using: Vec::new(),
813 where_clause: None,
814 output: None,
815 leading_comments: Vec::new(),
816 with: None,
817 limit: None,
818 order_by: None,
819 returning: Vec::new(),
820 tables: Vec::new(),
821 tables_from_using: false,
822 joins: Vec::new(),
823 force_index: None,
824 no_from: false,
825 },
826 }
827}
828
829pub fn insert_into(table_name: &str) -> InsertBuilder {
846 InsertBuilder {
847 insert: Insert {
848 table: builder_table_ref(table_name),
849 columns: Vec::new(),
850 values: Vec::new(),
851 query: None,
852 overwrite: false,
853 partition: Vec::new(),
854 directory: None,
855 returning: Vec::new(),
856 output: None,
857 on_conflict: None,
858 leading_comments: Vec::new(),
859 if_exists: false,
860 with: None,
861 ignore: false,
862 source_alias: None,
863 alias: None,
864 alias_explicit_as: false,
865 default_values: false,
866 by_name: false,
867 conflict_action: None,
868 is_replace: false,
869 hint: None,
870 replace_where: None,
871 source: None,
872 function_target: None,
873 partition_by: None,
874 settings: Vec::new(),
875 },
876 }
877}
878
879pub fn update(table_name: &str) -> UpdateBuilder {
897 UpdateBuilder {
898 update: Update {
899 table: builder_table_ref(table_name),
900 hint: None,
901 extra_tables: Vec::new(),
902 table_joins: Vec::new(),
903 set: Vec::new(),
904 from_clause: None,
905 from_joins: Vec::new(),
906 where_clause: None,
907 returning: Vec::new(),
908 output: None,
909 with: None,
910 leading_comments: Vec::new(),
911 limit: None,
912 order_by: None,
913 from_before_set: false,
914 },
915 }
916}
917
918#[derive(Debug, Clone)]
943pub struct Expr(pub Expression);
944
945impl Expr {
946 pub fn into_inner(self) -> Expression {
948 self.0
949 }
950
951 pub fn to_sql(&self) -> String {
955 Generator::sql(&self.0).unwrap_or_default()
956 }
957
958 pub fn eq(self, other: Expr) -> Expr {
962 Expr(Expression::Eq(Box::new(binary_op(self.0, other.0))))
963 }
964
965 pub fn neq(self, other: Expr) -> Expr {
967 Expr(Expression::Neq(Box::new(binary_op(self.0, other.0))))
968 }
969
970 pub fn lt(self, other: Expr) -> Expr {
972 Expr(Expression::Lt(Box::new(binary_op(self.0, other.0))))
973 }
974
975 pub fn lte(self, other: Expr) -> Expr {
977 Expr(Expression::Lte(Box::new(binary_op(self.0, other.0))))
978 }
979
980 pub fn gt(self, other: Expr) -> Expr {
982 Expr(Expression::Gt(Box::new(binary_op(self.0, other.0))))
983 }
984
985 pub fn gte(self, other: Expr) -> Expr {
987 Expr(Expression::Gte(Box::new(binary_op(self.0, other.0))))
988 }
989
990 pub fn and(self, other: Expr) -> Expr {
994 Expr(Expression::And(Box::new(binary_op(self.0, other.0))))
995 }
996
997 pub fn or(self, other: Expr) -> Expr {
999 Expr(Expression::Or(Box::new(binary_op(self.0, other.0))))
1000 }
1001
1002 pub fn not(self) -> Expr {
1004 Expr(Expression::Not(Box::new(UnaryOp::new(self.0))))
1005 }
1006
1007 pub fn xor(self, other: Expr) -> Expr {
1009 Expr(Expression::Xor(Box::new(Xor {
1010 this: Some(Box::new(self.0)),
1011 expression: Some(Box::new(other.0)),
1012 expressions: vec![],
1013 })))
1014 }
1015
1016 pub fn add(self, other: Expr) -> Expr {
1020 Expr(Expression::Add(Box::new(binary_op(self.0, other.0))))
1021 }
1022
1023 pub fn sub(self, other: Expr) -> Expr {
1025 Expr(Expression::Sub(Box::new(binary_op(self.0, other.0))))
1026 }
1027
1028 pub fn mul(self, other: Expr) -> Expr {
1030 Expr(Expression::Mul(Box::new(binary_op(self.0, other.0))))
1031 }
1032
1033 pub fn div(self, other: Expr) -> Expr {
1035 Expr(Expression::Div(Box::new(binary_op(self.0, other.0))))
1036 }
1037
1038 pub fn is_null(self) -> Expr {
1042 Expr(Expression::Is(Box::new(BinaryOp {
1043 left: self.0,
1044 right: Expression::Null(Null),
1045 left_comments: Vec::new(),
1046 operator_comments: Vec::new(),
1047 trailing_comments: Vec::new(),
1048 inferred_type: None,
1049 })))
1050 }
1051
1052 pub fn is_not_null(self) -> Expr {
1054 Expr(Expression::Not(Box::new(UnaryOp::new(Expression::Is(
1055 Box::new(BinaryOp {
1056 left: self.0,
1057 right: Expression::Null(Null),
1058 left_comments: Vec::new(),
1059 operator_comments: Vec::new(),
1060 trailing_comments: Vec::new(),
1061 inferred_type: None,
1062 }),
1063 )))))
1064 }
1065
1066 pub fn in_list(self, values: impl IntoIterator<Item = Expr>) -> Expr {
1070 Expr(Expression::In(Box::new(In {
1071 this: self.0,
1072 expressions: values.into_iter().map(|v| v.0).collect(),
1073 query: None,
1074 not: false,
1075 global: false,
1076 unnest: None,
1077 is_field: false,
1078 })))
1079 }
1080
1081 pub fn between(self, low: Expr, high: Expr) -> Expr {
1083 Expr(Expression::Between(Box::new(Between {
1084 this: self.0,
1085 low: low.0,
1086 high: high.0,
1087 not: false,
1088 symmetric: None,
1089 })))
1090 }
1091
1092 pub fn like(self, pattern: Expr) -> Expr {
1094 Expr(Expression::Like(Box::new(LikeOp {
1095 left: self.0,
1096 right: pattern.0,
1097 escape: None,
1098 quantifier: None,
1099 inferred_type: None,
1100 })))
1101 }
1102
1103 pub fn alias(self, name: &str) -> Expr {
1105 alias(self, name)
1106 }
1107
1108 pub fn cast(self, to: &str) -> Expr {
1112 cast(self, to)
1113 }
1114
1115 pub fn asc(self) -> Expr {
1120 Expr(Expression::Ordered(Box::new(Ordered {
1121 this: self.0,
1122 desc: false,
1123 nulls_first: None,
1124 explicit_asc: true,
1125 with_fill: None,
1126 })))
1127 }
1128
1129 pub fn desc(self) -> Expr {
1133 Expr(Expression::Ordered(Box::new(Ordered {
1134 this: self.0,
1135 desc: true,
1136 nulls_first: None,
1137 explicit_asc: false,
1138 with_fill: None,
1139 })))
1140 }
1141
1142 pub fn ilike(self, pattern: Expr) -> Expr {
1147 Expr(Expression::ILike(Box::new(LikeOp {
1148 left: self.0,
1149 right: pattern.0,
1150 escape: None,
1151 quantifier: None,
1152 inferred_type: None,
1153 })))
1154 }
1155
1156 pub fn rlike(self, pattern: Expr) -> Expr {
1161 Expr(Expression::RegexpLike(Box::new(RegexpFunc {
1162 this: self.0,
1163 pattern: pattern.0,
1164 flags: None,
1165 })))
1166 }
1167
1168 pub fn not_in(self, values: impl IntoIterator<Item = Expr>) -> Expr {
1172 Expr(Expression::In(Box::new(In {
1173 this: self.0,
1174 expressions: values.into_iter().map(|v| v.0).collect(),
1175 query: None,
1176 not: true,
1177 global: false,
1178 unnest: None,
1179 is_field: false,
1180 })))
1181 }
1182}
1183
1184pub struct SelectBuilder {
1210 select: Select,
1211}
1212
1213impl SelectBuilder {
1214 fn new() -> Self {
1215 SelectBuilder {
1216 select: Select::new(),
1217 }
1218 }
1219
1220 pub fn select_cols<I, E>(mut self, expressions: I) -> Self
1225 where
1226 I: IntoIterator<Item = E>,
1227 E: IntoExpr,
1228 {
1229 for expr in expressions {
1230 self.select.expressions.push(expr.into_expr().0);
1231 }
1232 self
1233 }
1234
1235 pub fn from(mut self, table_name: &str) -> Self {
1237 self.select.from = Some(From {
1238 expressions: vec![Expression::Table(Box::new(builder_table_ref(table_name)))],
1239 });
1240 self
1241 }
1242
1243 pub fn from_expr(mut self, expr: Expr) -> Self {
1248 self.select.from = Some(From {
1249 expressions: vec![expr.0],
1250 });
1251 self
1252 }
1253
1254 pub fn join(mut self, table_name: &str, on: Expr) -> Self {
1256 self.select.joins.push(Join {
1257 kind: JoinKind::Inner,
1258 this: Expression::Table(Box::new(builder_table_ref(table_name))),
1259 on: Some(on.0),
1260 using: Vec::new(),
1261 use_inner_keyword: false,
1262 use_outer_keyword: false,
1263 deferred_condition: false,
1264 join_hint: None,
1265 match_condition: None,
1266 pivots: Vec::new(),
1267 comments: Vec::new(),
1268 nesting_group: 0,
1269 directed: false,
1270 });
1271 self
1272 }
1273
1274 pub fn left_join(mut self, table_name: &str, on: Expr) -> Self {
1276 self.select.joins.push(Join {
1277 kind: JoinKind::Left,
1278 this: Expression::Table(Box::new(builder_table_ref(table_name))),
1279 on: Some(on.0),
1280 using: Vec::new(),
1281 use_inner_keyword: false,
1282 use_outer_keyword: false,
1283 deferred_condition: false,
1284 join_hint: None,
1285 match_condition: None,
1286 pivots: Vec::new(),
1287 comments: Vec::new(),
1288 nesting_group: 0,
1289 directed: false,
1290 });
1291 self
1292 }
1293
1294 pub fn where_(mut self, condition: Expr) -> Self {
1300 self.select.where_clause = Some(Where { this: condition.0 });
1301 self
1302 }
1303
1304 pub fn group_by<I, E>(mut self, expressions: I) -> Self
1306 where
1307 I: IntoIterator<Item = E>,
1308 E: IntoExpr,
1309 {
1310 self.select.group_by = Some(GroupBy {
1311 expressions: expressions.into_iter().map(|e| e.into_expr().0).collect(),
1312 all: None,
1313 totals: false,
1314 comments: Vec::new(),
1315 });
1316 self
1317 }
1318
1319 pub fn having(mut self, condition: Expr) -> Self {
1321 self.select.having = Some(Having {
1322 this: condition.0,
1323 comments: Vec::new(),
1324 });
1325 self
1326 }
1327
1328 pub fn order_by<I, E>(mut self, expressions: I) -> Self
1334 where
1335 I: IntoIterator<Item = E>,
1336 E: IntoExpr,
1337 {
1338 self.select.order_by = Some(OrderBy {
1339 siblings: false,
1340 comments: Vec::new(),
1341 expressions: expressions
1342 .into_iter()
1343 .map(|e| {
1344 let expr = e.into_expr().0;
1345 match expr {
1346 Expression::Ordered(_) => expr,
1347 other => Expression::Ordered(Box::new(Ordered {
1348 this: other,
1349 desc: false,
1350 nulls_first: None,
1351 explicit_asc: false,
1352 with_fill: None,
1353 })),
1354 }
1355 })
1356 .collect::<Vec<_>>()
1357 .into_iter()
1358 .map(|e| {
1359 if let Expression::Ordered(o) = e {
1360 *o
1361 } else {
1362 Ordered {
1363 this: e,
1364 desc: false,
1365 nulls_first: None,
1366 explicit_asc: false,
1367 with_fill: None,
1368 }
1369 }
1370 })
1371 .collect(),
1372 });
1373 self
1374 }
1375
1376 pub fn sort_by<I, E>(mut self, expressions: I) -> Self
1383 where
1384 I: IntoIterator<Item = E>,
1385 E: IntoExpr,
1386 {
1387 self.select.sort_by = Some(SortBy {
1388 expressions: expressions
1389 .into_iter()
1390 .map(|e| {
1391 let expr = e.into_expr().0;
1392 match expr {
1393 Expression::Ordered(o) => *o,
1394 other => Ordered {
1395 this: other,
1396 desc: false,
1397 nulls_first: None,
1398 explicit_asc: false,
1399 with_fill: None,
1400 },
1401 }
1402 })
1403 .collect(),
1404 });
1405 self
1406 }
1407
1408 pub fn limit(mut self, count: usize) -> Self {
1410 self.select.limit = Some(Limit {
1411 this: Expression::Literal(Box::new(Literal::Number(count.to_string()))),
1412 percent: false,
1413 comments: Vec::new(),
1414 });
1415 self
1416 }
1417
1418 pub fn offset(mut self, count: usize) -> Self {
1420 self.select.offset = Some(Offset {
1421 this: Expression::Literal(Box::new(Literal::Number(count.to_string()))),
1422 rows: None,
1423 });
1424 self
1425 }
1426
1427 pub fn distinct(mut self) -> Self {
1429 self.select.distinct = true;
1430 self
1431 }
1432
1433 pub fn qualify(mut self, condition: Expr) -> Self {
1438 self.select.qualify = Some(Qualify { this: condition.0 });
1439 self
1440 }
1441
1442 pub fn right_join(mut self, table_name: &str, on: Expr) -> Self {
1444 self.select.joins.push(Join {
1445 kind: JoinKind::Right,
1446 this: Expression::Table(Box::new(builder_table_ref(table_name))),
1447 on: Some(on.0),
1448 using: Vec::new(),
1449 use_inner_keyword: false,
1450 use_outer_keyword: false,
1451 deferred_condition: false,
1452 join_hint: None,
1453 match_condition: None,
1454 pivots: Vec::new(),
1455 comments: Vec::new(),
1456 nesting_group: 0,
1457 directed: false,
1458 });
1459 self
1460 }
1461
1462 pub fn cross_join(mut self, table_name: &str) -> Self {
1464 self.select.joins.push(Join {
1465 kind: JoinKind::Cross,
1466 this: Expression::Table(Box::new(builder_table_ref(table_name))),
1467 on: None,
1468 using: Vec::new(),
1469 use_inner_keyword: false,
1470 use_outer_keyword: false,
1471 deferred_condition: false,
1472 join_hint: None,
1473 match_condition: None,
1474 pivots: Vec::new(),
1475 comments: Vec::new(),
1476 nesting_group: 0,
1477 directed: false,
1478 });
1479 self
1480 }
1481
1482 pub fn lateral_view<S: AsRef<str>>(
1489 mut self,
1490 table_function: Expr,
1491 table_alias: &str,
1492 column_aliases: impl IntoIterator<Item = S>,
1493 ) -> Self {
1494 self.select.lateral_views.push(LateralView {
1495 this: table_function.0,
1496 table_alias: Some(builder_identifier(table_alias)),
1497 column_aliases: column_aliases
1498 .into_iter()
1499 .map(|c| builder_identifier(c.as_ref()))
1500 .collect(),
1501 outer: false,
1502 });
1503 self
1504 }
1505
1506 pub fn window(mut self, name: &str, def: WindowDefBuilder) -> Self {
1512 let named_window = NamedWindow {
1513 name: builder_identifier(name),
1514 spec: Over {
1515 window_name: None,
1516 partition_by: def.partition_by,
1517 order_by: def.order_by,
1518 frame: None,
1519 alias: None,
1520 },
1521 };
1522 match self.select.windows {
1523 Some(ref mut windows) => windows.push(named_window),
1524 None => self.select.windows = Some(vec![named_window]),
1525 }
1526 self
1527 }
1528
1529 pub fn for_update(mut self) -> Self {
1534 self.select.locks.push(Lock {
1535 update: Some(Box::new(Expression::Boolean(BooleanLiteral {
1536 value: true,
1537 }))),
1538 expressions: vec![],
1539 wait: None,
1540 key: None,
1541 });
1542 self
1543 }
1544
1545 pub fn for_share(mut self) -> Self {
1550 self.select.locks.push(Lock {
1551 update: None,
1552 expressions: vec![],
1553 wait: None,
1554 key: None,
1555 });
1556 self
1557 }
1558
1559 pub fn hint(mut self, hint_text: &str) -> Self {
1564 let hint_expr = HintExpression::Raw(hint_text.to_string());
1565 match &mut self.select.hint {
1566 Some(h) => h.expressions.push(hint_expr),
1567 None => {
1568 self.select.hint = Some(Hint {
1569 expressions: vec![hint_expr],
1570 })
1571 }
1572 }
1573 self
1574 }
1575
1576 pub fn ctas(self, table_name: &str) -> Expression {
1592 Expression::CreateTable(Box::new(CreateTable {
1593 name: builder_table_ref(table_name),
1594 on_cluster: None,
1595 columns: vec![],
1596 constraints: vec![],
1597 if_not_exists: false,
1598 temporary: false,
1599 or_replace: false,
1600 table_modifier: None,
1601 as_select: Some(self.build()),
1602 as_select_parenthesized: false,
1603 on_commit: None,
1604 clone_source: None,
1605 clone_at_clause: None,
1606 is_copy: false,
1607 shallow_clone: false,
1608 deep_clone: false,
1609 leading_comments: vec![],
1610 with_properties: vec![],
1611 teradata_post_name_options: vec![],
1612 with_data: None,
1613 with_statistics: None,
1614 teradata_indexes: vec![],
1615 with_cte: None,
1616 properties: vec![],
1617 partition_of: None,
1618 post_table_properties: vec![],
1619 mysql_table_options: vec![],
1620 inherits: vec![],
1621 on_property: None,
1622 copy_grants: false,
1623 using_template: None,
1624 rollup: None,
1625 uuid: None,
1626 with_partition_columns: vec![],
1627 with_connection: None,
1628 }))
1629 }
1630
1631 pub fn union(self, other: SelectBuilder) -> SetOpBuilder {
1635 SetOpBuilder::new(SetOpKind::Union, self, other, false)
1636 }
1637
1638 pub fn union_all(self, other: SelectBuilder) -> SetOpBuilder {
1642 SetOpBuilder::new(SetOpKind::Union, self, other, true)
1643 }
1644
1645 pub fn intersect(self, other: SelectBuilder) -> SetOpBuilder {
1649 SetOpBuilder::new(SetOpKind::Intersect, self, other, false)
1650 }
1651
1652 pub fn except_(self, other: SelectBuilder) -> SetOpBuilder {
1656 SetOpBuilder::new(SetOpKind::Except, self, other, false)
1657 }
1658
1659 pub fn build(self) -> Expression {
1661 Expression::Select(Box::new(self.select))
1662 }
1663
1664 pub fn to_sql(self) -> String {
1669 Generator::sql(&self.build()).unwrap_or_default()
1670 }
1671}
1672
1673pub struct DeleteBuilder {
1682 delete: Delete,
1683}
1684
1685impl DeleteBuilder {
1686 pub fn where_(mut self, condition: Expr) -> Self {
1688 self.delete.where_clause = Some(Where { this: condition.0 });
1689 self
1690 }
1691
1692 pub fn build(self) -> Expression {
1694 Expression::Delete(Box::new(self.delete))
1695 }
1696
1697 pub fn to_sql(self) -> String {
1699 Generator::sql(&self.build()).unwrap_or_default()
1700 }
1701}
1702
1703pub struct InsertBuilder {
1714 insert: Insert,
1715}
1716
1717impl InsertBuilder {
1718 pub fn columns<I, S>(mut self, columns: I) -> Self
1720 where
1721 I: IntoIterator<Item = S>,
1722 S: AsRef<str>,
1723 {
1724 self.insert.columns = columns
1725 .into_iter()
1726 .map(|c| builder_identifier(c.as_ref()))
1727 .collect();
1728 self
1729 }
1730
1731 pub fn values<I>(mut self, values: I) -> Self
1735 where
1736 I: IntoIterator<Item = Expr>,
1737 {
1738 self.insert
1739 .values
1740 .push(values.into_iter().map(|v| v.0).collect());
1741 self
1742 }
1743
1744 pub fn query(mut self, query: SelectBuilder) -> Self {
1748 self.insert.query = Some(query.build());
1749 self
1750 }
1751
1752 pub fn build(self) -> Expression {
1754 Expression::Insert(Box::new(self.insert))
1755 }
1756
1757 pub fn to_sql(self) -> String {
1759 Generator::sql(&self.build()).unwrap_or_default()
1760 }
1761}
1762
1763pub struct UpdateBuilder {
1773 update: Update,
1774}
1775
1776impl UpdateBuilder {
1777 pub fn set(mut self, column: &str, value: Expr) -> Self {
1781 self.update.set.push((builder_identifier(column), value.0));
1782 self
1783 }
1784
1785 pub fn where_(mut self, condition: Expr) -> Self {
1787 self.update.where_clause = Some(Where { this: condition.0 });
1788 self
1789 }
1790
1791 pub fn from(mut self, table_name: &str) -> Self {
1795 self.update.from_clause = Some(From {
1796 expressions: vec![Expression::Table(Box::new(builder_table_ref(table_name)))],
1797 });
1798 self
1799 }
1800
1801 pub fn build(self) -> Expression {
1803 Expression::Update(Box::new(self.update))
1804 }
1805
1806 pub fn to_sql(self) -> String {
1808 Generator::sql(&self.build()).unwrap_or_default()
1809 }
1810}
1811
1812pub fn case() -> CaseBuilder {
1837 CaseBuilder {
1838 operand: None,
1839 whens: Vec::new(),
1840 else_: None,
1841 }
1842}
1843
1844pub fn case_of(operand: Expr) -> CaseBuilder {
1865 CaseBuilder {
1866 operand: Some(operand.0),
1867 whens: Vec::new(),
1868 else_: None,
1869 }
1870}
1871
1872pub struct CaseBuilder {
1880 operand: Option<Expression>,
1881 whens: Vec<(Expression, Expression)>,
1882 else_: Option<Expression>,
1883}
1884
1885impl CaseBuilder {
1886 pub fn when(mut self, condition: Expr, result: Expr) -> Self {
1891 self.whens.push((condition.0, result.0));
1892 self
1893 }
1894
1895 pub fn else_(mut self, result: Expr) -> Self {
1900 self.else_ = Some(result.0);
1901 self
1902 }
1903
1904 pub fn build(self) -> Expr {
1906 Expr(self.build_expr())
1907 }
1908
1909 pub fn build_expr(self) -> Expression {
1914 Expression::Case(Box::new(Case {
1915 operand: self.operand,
1916 whens: self.whens,
1917 else_: self.else_,
1918 comments: Vec::new(),
1919 inferred_type: None,
1920 }))
1921 }
1922}
1923
1924pub fn subquery(query: SelectBuilder, alias_name: &str) -> Expr {
1948 subquery_expr(query.build(), alias_name)
1949}
1950
1951pub fn subquery_expr(expr: Expression, alias_name: &str) -> Expr {
1956 Expr(Expression::Subquery(Box::new(Subquery {
1957 this: expr,
1958 alias: Some(builder_identifier(alias_name)),
1959 column_aliases: Vec::new(),
1960 alias_explicit_as: false,
1961 alias_keyword: None,
1962 order_by: None,
1963 limit: None,
1964 offset: None,
1965 distribute_by: None,
1966 sort_by: None,
1967 cluster_by: None,
1968 lateral: false,
1969 modifiers_inside: true,
1970 trailing_comments: Vec::new(),
1971 inferred_type: None,
1972 })))
1973}
1974
1975#[derive(Debug, Clone, Copy)]
1981enum SetOpKind {
1982 Union,
1983 Intersect,
1984 Except,
1985}
1986
1987pub struct SetOpBuilder {
2008 kind: SetOpKind,
2009 left: Expression,
2010 right: Expression,
2011 all: bool,
2012 order_by: Option<OrderBy>,
2013 limit: Option<Box<Expression>>,
2014 offset: Option<Box<Expression>>,
2015}
2016
2017impl SetOpBuilder {
2018 fn new(kind: SetOpKind, left: SelectBuilder, right: SelectBuilder, all: bool) -> Self {
2019 SetOpBuilder {
2020 kind,
2021 left: left.build(),
2022 right: right.build(),
2023 all,
2024 order_by: None,
2025 limit: None,
2026 offset: None,
2027 }
2028 }
2029
2030 pub fn order_by<I, E>(mut self, expressions: I) -> Self
2035 where
2036 I: IntoIterator<Item = E>,
2037 E: IntoExpr,
2038 {
2039 self.order_by = Some(OrderBy {
2040 siblings: false,
2041 comments: Vec::new(),
2042 expressions: expressions
2043 .into_iter()
2044 .map(|e| {
2045 let expr = e.into_expr().0;
2046 match expr {
2047 Expression::Ordered(o) => *o,
2048 other => Ordered {
2049 this: other,
2050 desc: false,
2051 nulls_first: None,
2052 explicit_asc: false,
2053 with_fill: None,
2054 },
2055 }
2056 })
2057 .collect(),
2058 });
2059 self
2060 }
2061
2062 pub fn limit(mut self, count: usize) -> Self {
2064 self.limit = Some(Box::new(Expression::Literal(Box::new(Literal::Number(
2065 count.to_string(),
2066 )))));
2067 self
2068 }
2069
2070 pub fn offset(mut self, count: usize) -> Self {
2072 self.offset = Some(Box::new(Expression::Literal(Box::new(Literal::Number(
2073 count.to_string(),
2074 )))));
2075 self
2076 }
2077
2078 pub fn build(self) -> Expression {
2083 match self.kind {
2084 SetOpKind::Union => Expression::Union(Box::new(Union {
2085 left: self.left,
2086 right: self.right,
2087 all: self.all,
2088 distinct: false,
2089 with: None,
2090 order_by: self.order_by,
2091 limit: self.limit,
2092 offset: self.offset,
2093 distribute_by: None,
2094 sort_by: None,
2095 cluster_by: None,
2096 by_name: false,
2097 side: None,
2098 kind: None,
2099 corresponding: false,
2100 strict: false,
2101 on_columns: Vec::new(),
2102 })),
2103 SetOpKind::Intersect => Expression::Intersect(Box::new(Intersect {
2104 left: self.left,
2105 right: self.right,
2106 all: self.all,
2107 distinct: false,
2108 with: None,
2109 order_by: self.order_by,
2110 limit: self.limit,
2111 offset: self.offset,
2112 distribute_by: None,
2113 sort_by: None,
2114 cluster_by: None,
2115 by_name: false,
2116 side: None,
2117 kind: None,
2118 corresponding: false,
2119 strict: false,
2120 on_columns: Vec::new(),
2121 })),
2122 SetOpKind::Except => Expression::Except(Box::new(Except {
2123 left: self.left,
2124 right: self.right,
2125 all: self.all,
2126 distinct: false,
2127 with: None,
2128 order_by: self.order_by,
2129 limit: self.limit,
2130 offset: self.offset,
2131 distribute_by: None,
2132 sort_by: None,
2133 cluster_by: None,
2134 by_name: false,
2135 side: None,
2136 kind: None,
2137 corresponding: false,
2138 strict: false,
2139 on_columns: Vec::new(),
2140 })),
2141 }
2142 }
2143
2144 pub fn to_sql(self) -> String {
2146 Generator::sql(&self.build()).unwrap_or_default()
2147 }
2148}
2149
2150pub fn union(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2154 SetOpBuilder::new(SetOpKind::Union, left, right, false)
2155}
2156
2157pub fn union_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2161 SetOpBuilder::new(SetOpKind::Union, left, right, true)
2162}
2163
2164pub fn intersect(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2168 SetOpBuilder::new(SetOpKind::Intersect, left, right, false)
2169}
2170
2171pub fn intersect_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2175 SetOpBuilder::new(SetOpKind::Intersect, left, right, true)
2176}
2177
2178pub fn except_(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2182 SetOpBuilder::new(SetOpKind::Except, left, right, false)
2183}
2184
2185pub fn except_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2189 SetOpBuilder::new(SetOpKind::Except, left, right, true)
2190}
2191
2192pub struct WindowDefBuilder {
2217 partition_by: Vec<Expression>,
2218 order_by: Vec<Ordered>,
2219}
2220
2221impl WindowDefBuilder {
2222 pub fn new() -> Self {
2224 WindowDefBuilder {
2225 partition_by: Vec::new(),
2226 order_by: Vec::new(),
2227 }
2228 }
2229
2230 pub fn partition_by<I, E>(mut self, expressions: I) -> Self
2232 where
2233 I: IntoIterator<Item = E>,
2234 E: IntoExpr,
2235 {
2236 self.partition_by = expressions.into_iter().map(|e| e.into_expr().0).collect();
2237 self
2238 }
2239
2240 pub fn order_by<I, E>(mut self, expressions: I) -> Self
2245 where
2246 I: IntoIterator<Item = E>,
2247 E: IntoExpr,
2248 {
2249 self.order_by = expressions
2250 .into_iter()
2251 .map(|e| {
2252 let expr = e.into_expr().0;
2253 match expr {
2254 Expression::Ordered(o) => *o,
2255 other => Ordered {
2256 this: other,
2257 desc: false,
2258 nulls_first: None,
2259 explicit_asc: false,
2260 with_fill: None,
2261 },
2262 }
2263 })
2264 .collect();
2265 self
2266 }
2267}
2268
2269pub trait IntoExpr {
2288 fn into_expr(self) -> Expr;
2290}
2291
2292impl IntoExpr for Expr {
2293 fn into_expr(self) -> Expr {
2294 self
2295 }
2296}
2297
2298impl IntoExpr for &str {
2299 fn into_expr(self) -> Expr {
2301 col(self)
2302 }
2303}
2304
2305impl IntoExpr for String {
2306 fn into_expr(self) -> Expr {
2308 col(&self)
2309 }
2310}
2311
2312impl IntoExpr for Expression {
2313 fn into_expr(self) -> Expr {
2315 Expr(self)
2316 }
2317}
2318
2319pub trait IntoLiteral {
2334 fn into_literal(self) -> Expr;
2336}
2337
2338impl IntoLiteral for &str {
2339 fn into_literal(self) -> Expr {
2341 Expr(Expression::Literal(Box::new(Literal::String(
2342 self.to_string(),
2343 ))))
2344 }
2345}
2346
2347impl IntoLiteral for String {
2348 fn into_literal(self) -> Expr {
2350 Expr(Expression::Literal(Box::new(Literal::String(self))))
2351 }
2352}
2353
2354impl IntoLiteral for i64 {
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 i32 {
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 usize {
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 f64 {
2382 fn into_literal(self) -> Expr {
2384 Expr(Expression::Literal(Box::new(Literal::Number(
2385 self.to_string(),
2386 ))))
2387 }
2388}
2389
2390impl IntoLiteral for bool {
2391 fn into_literal(self) -> Expr {
2393 Expr(Expression::Boolean(BooleanLiteral { value: self }))
2394 }
2395}
2396
2397fn binary_op(left: Expression, right: Expression) -> BinaryOp {
2402 BinaryOp {
2403 left,
2404 right,
2405 left_comments: Vec::new(),
2406 operator_comments: Vec::new(),
2407 trailing_comments: Vec::new(),
2408 inferred_type: None,
2409 }
2410}
2411
2412pub fn merge_into(target: &str) -> MergeBuilder {
2434 MergeBuilder {
2435 target: Expression::Table(Box::new(builder_table_ref(target))),
2436 using: None,
2437 on: None,
2438 whens: Vec::new(),
2439 }
2440}
2441
2442pub struct MergeBuilder {
2446 target: Expression,
2447 using: Option<Expression>,
2448 on: Option<Expression>,
2449 whens: Vec<Expression>,
2450}
2451
2452impl MergeBuilder {
2453 pub fn using(mut self, source: &str, on: Expr) -> Self {
2455 self.using = Some(Expression::Table(Box::new(builder_table_ref(source))));
2456 self.on = Some(on.0);
2457 self
2458 }
2459
2460 pub fn when_matched_update(mut self, assignments: Vec<(&str, Expr)>) -> Self {
2462 let eqs: Vec<Expression> = assignments
2463 .into_iter()
2464 .map(|(col_name, val)| {
2465 Expression::Eq(Box::new(BinaryOp {
2466 left: Expression::boxed_column(Column {
2467 name: builder_identifier(col_name),
2468 table: None,
2469 join_mark: false,
2470 trailing_comments: Vec::new(),
2471 span: None,
2472 inferred_type: None,
2473 }),
2474 right: val.0,
2475 left_comments: Vec::new(),
2476 operator_comments: Vec::new(),
2477 trailing_comments: Vec::new(),
2478 inferred_type: None,
2479 }))
2480 })
2481 .collect();
2482
2483 let action = Expression::Tuple(Box::new(Tuple {
2484 expressions: vec![
2485 Expression::Var(Box::new(Var {
2486 this: "UPDATE".to_string(),
2487 })),
2488 Expression::Tuple(Box::new(Tuple { expressions: eqs })),
2489 ],
2490 }));
2491
2492 let when = Expression::When(Box::new(When {
2493 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2494 value: true,
2495 }))),
2496 source: None,
2497 condition: None,
2498 then: Box::new(action),
2499 }));
2500 self.whens.push(when);
2501 self
2502 }
2503
2504 pub fn when_matched_update_where(
2506 mut self,
2507 condition: Expr,
2508 assignments: Vec<(&str, Expr)>,
2509 ) -> Self {
2510 let eqs: Vec<Expression> = assignments
2511 .into_iter()
2512 .map(|(col_name, val)| {
2513 Expression::Eq(Box::new(BinaryOp {
2514 left: Expression::boxed_column(Column {
2515 name: builder_identifier(col_name),
2516 table: None,
2517 join_mark: false,
2518 trailing_comments: Vec::new(),
2519 span: None,
2520 inferred_type: None,
2521 }),
2522 right: val.0,
2523 left_comments: Vec::new(),
2524 operator_comments: Vec::new(),
2525 trailing_comments: Vec::new(),
2526 inferred_type: None,
2527 }))
2528 })
2529 .collect();
2530
2531 let action = Expression::Tuple(Box::new(Tuple {
2532 expressions: vec![
2533 Expression::Var(Box::new(Var {
2534 this: "UPDATE".to_string(),
2535 })),
2536 Expression::Tuple(Box::new(Tuple { expressions: eqs })),
2537 ],
2538 }));
2539
2540 let when = Expression::When(Box::new(When {
2541 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2542 value: true,
2543 }))),
2544 source: None,
2545 condition: Some(Box::new(condition.0)),
2546 then: Box::new(action),
2547 }));
2548 self.whens.push(when);
2549 self
2550 }
2551
2552 pub fn when_matched_delete(mut self) -> Self {
2554 let action = Expression::Var(Box::new(Var {
2555 this: "DELETE".to_string(),
2556 }));
2557
2558 let when = Expression::When(Box::new(When {
2559 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2560 value: true,
2561 }))),
2562 source: None,
2563 condition: None,
2564 then: Box::new(action),
2565 }));
2566 self.whens.push(when);
2567 self
2568 }
2569
2570 pub fn when_not_matched_insert(mut self, columns: &[&str], values: Vec<Expr>) -> Self {
2572 let col_exprs: Vec<Expression> = columns
2573 .iter()
2574 .map(|c| {
2575 Expression::boxed_column(Column {
2576 name: builder_identifier(c),
2577 table: None,
2578 join_mark: false,
2579 trailing_comments: Vec::new(),
2580 span: None,
2581 inferred_type: None,
2582 })
2583 })
2584 .collect();
2585 let val_exprs: Vec<Expression> = values.into_iter().map(|v| v.0).collect();
2586
2587 let action = Expression::Tuple(Box::new(Tuple {
2588 expressions: vec![
2589 Expression::Var(Box::new(Var {
2590 this: "INSERT".to_string(),
2591 })),
2592 Expression::Tuple(Box::new(Tuple {
2593 expressions: col_exprs,
2594 })),
2595 Expression::Tuple(Box::new(Tuple {
2596 expressions: val_exprs,
2597 })),
2598 ],
2599 }));
2600
2601 let when = Expression::When(Box::new(When {
2602 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2603 value: false,
2604 }))),
2605 source: None,
2606 condition: None,
2607 then: Box::new(action),
2608 }));
2609 self.whens.push(when);
2610 self
2611 }
2612
2613 pub fn build(self) -> Expression {
2615 let whens_expr = Expression::Whens(Box::new(Whens {
2616 expressions: self.whens,
2617 }));
2618
2619 Expression::Merge(Box::new(Merge {
2620 this: Box::new(self.target),
2621 using: Box::new(
2622 self.using
2623 .unwrap_or(Expression::Null(crate::expressions::Null)),
2624 ),
2625 on: self.on.map(Box::new),
2626 using_cond: None,
2627 whens: Some(Box::new(whens_expr)),
2628 with_: None,
2629 returning: None,
2630 }))
2631 }
2632
2633 pub fn to_sql(self) -> String {
2635 Generator::sql(&self.build()).unwrap_or_default()
2636 }
2637}
2638
2639fn parse_simple_data_type(name: &str) -> DataType {
2640 let upper = name.trim().to_uppercase();
2641 match upper.as_str() {
2642 "INT" | "INTEGER" => DataType::Int {
2643 length: None,
2644 integer_spelling: upper == "INTEGER",
2645 },
2646 "BIGINT" => DataType::BigInt { length: None },
2647 "SMALLINT" => DataType::SmallInt { length: None },
2648 "TINYINT" => DataType::TinyInt { length: None },
2649 "FLOAT" => DataType::Float {
2650 precision: None,
2651 scale: None,
2652 real_spelling: false,
2653 },
2654 "DOUBLE" => DataType::Double {
2655 precision: None,
2656 scale: None,
2657 },
2658 "BOOLEAN" | "BOOL" => DataType::Boolean,
2659 "TEXT" => DataType::Text,
2660 "DATE" => DataType::Date,
2661 "TIMESTAMP" => DataType::Timestamp {
2662 precision: None,
2663 timezone: false,
2664 },
2665 "VARCHAR" => DataType::VarChar {
2666 length: None,
2667 parenthesized_length: false,
2668 },
2669 "CHAR" => DataType::Char { length: None },
2670 _ => {
2671 if let Ok(ast) =
2673 crate::parser::Parser::parse_sql(&format!("SELECT CAST(x AS {})", name))
2674 {
2675 if let Expression::Select(s) = &ast[0] {
2676 if let Some(Expression::Cast(c)) = s.expressions.first() {
2677 return c.to.clone();
2678 }
2679 }
2680 }
2681 DataType::Custom {
2683 name: name.to_string(),
2684 }
2685 }
2686 }
2687}
2688
2689#[cfg(test)]
2690mod tests {
2691 use super::*;
2692
2693 #[test]
2694 fn test_simple_select() {
2695 let sql = select(["id", "name"]).from("users").to_sql();
2696 assert_eq!(sql, "SELECT id, name FROM users");
2697 }
2698
2699 #[test]
2700 fn test_builder_quotes_unsafe_identifier_tokens() {
2701 let sql = select(["Name; DROP TABLE titanic"]).to_sql();
2702 assert_eq!(sql, r#"SELECT "Name; DROP TABLE titanic""#);
2703 }
2704
2705 #[test]
2706 fn test_builder_string_literal_requires_lit() {
2707 let sql = select([lit("Name; DROP TABLE titanic")]).to_sql();
2708 assert_eq!(sql, "SELECT 'Name; DROP TABLE titanic'");
2709 }
2710
2711 #[test]
2712 fn test_builder_quotes_unsafe_table_name_tokens() {
2713 let sql = select(["id"]).from("users; DROP TABLE x").to_sql();
2714 assert_eq!(sql, r#"SELECT id FROM "users; DROP TABLE x""#);
2715 }
2716
2717 #[test]
2718 fn test_select_star() {
2719 let sql = select([star()]).from("users").to_sql();
2720 assert_eq!(sql, "SELECT * FROM users");
2721 }
2722
2723 #[test]
2724 fn test_select_with_where() {
2725 let sql = select(["id", "name"])
2726 .from("users")
2727 .where_(col("age").gt(lit(18)))
2728 .to_sql();
2729 assert_eq!(sql, "SELECT id, name FROM users WHERE age > 18");
2730 }
2731
2732 #[test]
2733 fn test_select_with_join() {
2734 let sql = select(["u.id", "o.amount"])
2735 .from("users")
2736 .join("orders", col("u.id").eq(col("o.user_id")))
2737 .to_sql();
2738 assert_eq!(
2739 sql,
2740 "SELECT u.id, o.amount FROM users JOIN orders ON u.id = o.user_id"
2741 );
2742 }
2743
2744 #[test]
2745 fn test_select_with_group_by_having() {
2746 let sql = select([col("dept"), func("COUNT", [star()]).alias("cnt")])
2747 .from("employees")
2748 .group_by(["dept"])
2749 .having(func("COUNT", [star()]).gt(lit(5)))
2750 .to_sql();
2751 assert_eq!(
2752 sql,
2753 "SELECT dept, COUNT(*) AS cnt FROM employees GROUP BY dept HAVING COUNT(*) > 5"
2754 );
2755 }
2756
2757 #[test]
2758 fn test_select_with_order_limit_offset() {
2759 let sql = select(["id", "name"])
2760 .from("users")
2761 .order_by(["name"])
2762 .limit(10)
2763 .offset(20)
2764 .to_sql();
2765 assert_eq!(
2766 sql,
2767 "SELECT id, name FROM users ORDER BY name LIMIT 10 OFFSET 20"
2768 );
2769 }
2770
2771 #[test]
2772 fn test_select_distinct() {
2773 let sql = select(["name"]).from("users").distinct().to_sql();
2774 assert_eq!(sql, "SELECT DISTINCT name FROM users");
2775 }
2776
2777 #[test]
2778 fn test_insert_values() {
2779 let sql = insert_into("users")
2780 .columns(["id", "name"])
2781 .values([lit(1), lit("Alice")])
2782 .values([lit(2), lit("Bob")])
2783 .to_sql();
2784 assert_eq!(
2785 sql,
2786 "INSERT INTO users (id, name) VALUES (1, 'Alice'), (2, 'Bob')"
2787 );
2788 }
2789
2790 #[test]
2791 fn test_insert_select() {
2792 let sql = insert_into("archive")
2793 .columns(["id", "name"])
2794 .query(select(["id", "name"]).from("users"))
2795 .to_sql();
2796 assert_eq!(
2797 sql,
2798 "INSERT INTO archive (id, name) SELECT id, name FROM users"
2799 );
2800 }
2801
2802 #[test]
2803 fn test_update() {
2804 let sql = update("users")
2805 .set("name", lit("Bob"))
2806 .set("age", lit(30))
2807 .where_(col("id").eq(lit(1)))
2808 .to_sql();
2809 assert_eq!(sql, "UPDATE users SET name = 'Bob', age = 30 WHERE id = 1");
2810 }
2811
2812 #[test]
2813 fn test_delete() {
2814 let sql = delete("users").where_(col("id").eq(lit(1))).to_sql();
2815 assert_eq!(sql, "DELETE FROM users WHERE id = 1");
2816 }
2817
2818 #[test]
2819 fn test_complex_where() {
2820 let sql = select(["id"])
2821 .from("users")
2822 .where_(
2823 col("age")
2824 .gte(lit(18))
2825 .and(col("active").eq(boolean(true)))
2826 .and(col("name").like(lit("%test%"))),
2827 )
2828 .to_sql();
2829 assert_eq!(
2830 sql,
2831 "SELECT id FROM users WHERE age >= 18 AND active = TRUE AND name LIKE '%test%'"
2832 );
2833 }
2834
2835 #[test]
2836 fn test_in_list() {
2837 let sql = select(["id"])
2838 .from("users")
2839 .where_(col("status").in_list([lit("active"), lit("pending")]))
2840 .to_sql();
2841 assert_eq!(
2842 sql,
2843 "SELECT id FROM users WHERE status IN ('active', 'pending')"
2844 );
2845 }
2846
2847 #[test]
2848 fn test_between() {
2849 let sql = select(["id"])
2850 .from("orders")
2851 .where_(col("amount").between(lit(100), lit(500)))
2852 .to_sql();
2853 assert_eq!(
2854 sql,
2855 "SELECT id FROM orders WHERE amount BETWEEN 100 AND 500"
2856 );
2857 }
2858
2859 #[test]
2860 fn test_is_null() {
2861 let sql = select(["id"])
2862 .from("users")
2863 .where_(col("email").is_null())
2864 .to_sql();
2865 assert_eq!(sql, "SELECT id FROM users WHERE email IS NULL");
2866 }
2867
2868 #[test]
2869 fn test_arithmetic() {
2870 let sql = select([col("price").mul(col("quantity")).alias("total")])
2871 .from("items")
2872 .to_sql();
2873 assert_eq!(sql, "SELECT price * quantity AS total FROM items");
2874 }
2875
2876 #[test]
2877 fn test_cast() {
2878 let sql = select([col("id").cast("VARCHAR")]).from("users").to_sql();
2879 assert_eq!(sql, "SELECT CAST(id AS VARCHAR) FROM users");
2880 }
2881
2882 #[test]
2883 fn test_from_starter() {
2884 let sql = from("users").select_cols(["id", "name"]).to_sql();
2885 assert_eq!(sql, "SELECT id, name FROM users");
2886 }
2887
2888 #[test]
2889 fn test_qualified_column() {
2890 let sql = select([col("u.id"), col("u.name")]).from("users").to_sql();
2891 assert_eq!(sql, "SELECT u.id, u.name FROM users");
2892 }
2893
2894 #[test]
2895 fn test_not_condition() {
2896 let sql = select(["id"])
2897 .from("users")
2898 .where_(not(col("active").eq(boolean(true))))
2899 .to_sql();
2900 assert_eq!(sql, "SELECT id FROM users WHERE NOT active = TRUE");
2901 }
2902
2903 #[test]
2904 fn test_order_by_desc() {
2905 let sql = select(["id", "name"])
2906 .from("users")
2907 .order_by([col("name").desc()])
2908 .to_sql();
2909 assert_eq!(sql, "SELECT id, name FROM users ORDER BY name DESC");
2910 }
2911
2912 #[test]
2913 fn test_left_join() {
2914 let sql = select(["u.id", "o.amount"])
2915 .from("users")
2916 .left_join("orders", col("u.id").eq(col("o.user_id")))
2917 .to_sql();
2918 assert_eq!(
2919 sql,
2920 "SELECT u.id, o.amount FROM users LEFT JOIN orders ON u.id = o.user_id"
2921 );
2922 }
2923
2924 #[test]
2925 fn test_build_returns_expression() {
2926 let expr = select(["id"]).from("users").build();
2927 assert!(matches!(expr, Expression::Select(_)));
2928 }
2929
2930 #[test]
2931 fn test_expr_interop() {
2932 let age_check = col("age").gt(lit(18));
2934 let sql = select([col("id"), age_check.alias("is_adult")])
2935 .from("users")
2936 .to_sql();
2937 assert_eq!(sql, "SELECT id, age > 18 AS is_adult FROM users");
2938 }
2939
2940 #[test]
2943 fn test_sql_expr_simple() {
2944 let expr = sql_expr("age > 18");
2945 let sql = select(["id"]).from("users").where_(expr).to_sql();
2946 assert_eq!(sql, "SELECT id FROM users WHERE age > 18");
2947 }
2948
2949 #[test]
2950 fn test_sql_expr_compound() {
2951 let expr = sql_expr("a > 1 AND b < 10");
2952 let sql = select(["*"]).from("t").where_(expr).to_sql();
2953 assert_eq!(sql, "SELECT * FROM t WHERE a > 1 AND b < 10");
2954 }
2955
2956 #[test]
2957 fn test_sql_expr_function() {
2958 let expr = sql_expr("COALESCE(a, b, 0)");
2959 let sql = select([expr.alias("val")]).from("t").to_sql();
2960 assert_eq!(sql, "SELECT COALESCE(a, b, 0) AS val FROM t");
2961 }
2962
2963 #[test]
2964 fn test_condition_alias() {
2965 let cond = condition("x > 0");
2966 let sql = select(["*"]).from("t").where_(cond).to_sql();
2967 assert_eq!(sql, "SELECT * FROM t WHERE x > 0");
2968 }
2969
2970 #[test]
2973 fn test_ilike() {
2974 let sql = select(["id"])
2975 .from("users")
2976 .where_(col("name").ilike(lit("%test%")))
2977 .to_sql();
2978 assert_eq!(sql, "SELECT id FROM users WHERE name ILIKE '%test%'");
2979 }
2980
2981 #[test]
2982 fn test_rlike() {
2983 let sql = select(["id"])
2984 .from("users")
2985 .where_(col("name").rlike(lit("^[A-Z]")))
2986 .to_sql();
2987 assert_eq!(
2988 sql,
2989 "SELECT id FROM users WHERE REGEXP_LIKE(name, '^[A-Z]')"
2990 );
2991 }
2992
2993 #[test]
2994 fn test_not_in() {
2995 let sql = select(["id"])
2996 .from("users")
2997 .where_(col("status").not_in([lit("deleted"), lit("banned")]))
2998 .to_sql();
2999 assert_eq!(
3000 sql,
3001 "SELECT id FROM users WHERE NOT status IN ('deleted', 'banned')"
3002 );
3003 }
3004
3005 #[test]
3008 fn test_case_searched() {
3009 let expr = case()
3010 .when(col("x").gt(lit(0)), lit("positive"))
3011 .when(col("x").eq(lit(0)), lit("zero"))
3012 .else_(lit("negative"))
3013 .build();
3014 let sql = select([expr.alias("label")]).from("t").to_sql();
3015 assert_eq!(
3016 sql,
3017 "SELECT CASE WHEN x > 0 THEN 'positive' WHEN x = 0 THEN 'zero' ELSE 'negative' END AS label FROM t"
3018 );
3019 }
3020
3021 #[test]
3022 fn test_case_simple() {
3023 let expr = case_of(col("status"))
3024 .when(lit(1), lit("active"))
3025 .when(lit(0), lit("inactive"))
3026 .build();
3027 let sql = select([expr.alias("status_label")]).from("t").to_sql();
3028 assert_eq!(
3029 sql,
3030 "SELECT CASE status WHEN 1 THEN 'active' WHEN 0 THEN 'inactive' END AS status_label FROM t"
3031 );
3032 }
3033
3034 #[test]
3035 fn test_case_no_else() {
3036 let expr = case().when(col("x").gt(lit(0)), lit("yes")).build();
3037 let sql = select([expr]).from("t").to_sql();
3038 assert_eq!(sql, "SELECT CASE WHEN x > 0 THEN 'yes' END FROM t");
3039 }
3040
3041 #[test]
3044 fn test_subquery_in_from() {
3045 let inner = select(["id", "name"])
3046 .from("users")
3047 .where_(col("active").eq(boolean(true)));
3048 let outer = select(["sub.id"])
3049 .from_expr(subquery(inner, "sub"))
3050 .to_sql();
3051 assert_eq!(
3052 outer,
3053 "SELECT sub.id FROM (SELECT id, name FROM users WHERE active = TRUE) AS sub"
3054 );
3055 }
3056
3057 #[test]
3058 fn test_subquery_in_join() {
3059 let inner = select([col("user_id"), func("SUM", [col("amount")]).alias("total")])
3060 .from("orders")
3061 .group_by(["user_id"]);
3062 let sql = select(["u.name", "o.total"])
3063 .from("users")
3064 .join("orders", col("u.id").eq(col("o.user_id")))
3065 .to_sql();
3066 assert!(sql.contains("JOIN"));
3067 let _sub = subquery(inner, "o");
3069 }
3070
3071 #[test]
3074 fn test_union() {
3075 let sql = union(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3076 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
3077 }
3078
3079 #[test]
3080 fn test_union_all() {
3081 let sql = union_all(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3082 assert_eq!(sql, "SELECT id FROM a UNION ALL SELECT id FROM b");
3083 }
3084
3085 #[test]
3086 fn test_intersect_builder() {
3087 let sql = intersect(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3088 assert_eq!(sql, "SELECT id FROM a INTERSECT SELECT id FROM b");
3089 }
3090
3091 #[test]
3092 fn test_except_builder() {
3093 let sql = except_(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3094 assert_eq!(sql, "SELECT id FROM a EXCEPT SELECT id FROM b");
3095 }
3096
3097 #[test]
3098 fn test_union_with_order_limit() {
3099 let sql = union(select(["id"]).from("a"), select(["id"]).from("b"))
3100 .order_by(["id"])
3101 .limit(10)
3102 .to_sql();
3103 assert!(sql.contains("UNION"));
3104 assert!(sql.contains("ORDER BY"));
3105 assert!(sql.contains("LIMIT"));
3106 }
3107
3108 #[test]
3109 fn test_select_builder_union() {
3110 let sql = select(["id"])
3111 .from("a")
3112 .union(select(["id"]).from("b"))
3113 .to_sql();
3114 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
3115 }
3116
3117 #[test]
3120 fn test_qualify() {
3121 let sql = select(["id", "name"])
3122 .from("users")
3123 .qualify(col("rn").eq(lit(1)))
3124 .to_sql();
3125 assert_eq!(sql, "SELECT id, name FROM users QUALIFY rn = 1");
3126 }
3127
3128 #[test]
3129 fn test_right_join() {
3130 let sql = select(["u.id", "o.amount"])
3131 .from("users")
3132 .right_join("orders", col("u.id").eq(col("o.user_id")))
3133 .to_sql();
3134 assert_eq!(
3135 sql,
3136 "SELECT u.id, o.amount FROM users RIGHT JOIN orders ON u.id = o.user_id"
3137 );
3138 }
3139
3140 #[test]
3141 fn test_cross_join() {
3142 let sql = select(["a.x", "b.y"]).from("a").cross_join("b").to_sql();
3143 assert_eq!(sql, "SELECT a.x, b.y FROM a CROSS JOIN b");
3144 }
3145
3146 #[test]
3147 fn test_lateral_view() {
3148 let sql = select(["id", "col_val"])
3149 .from("t")
3150 .lateral_view(func("EXPLODE", [col("arr")]), "lv", ["col_val"])
3151 .to_sql();
3152 assert!(sql.contains("LATERAL VIEW"));
3153 assert!(sql.contains("EXPLODE"));
3154 }
3155
3156 #[test]
3157 fn test_window_clause() {
3158 let sql = select(["id"])
3159 .from("t")
3160 .window(
3161 "w",
3162 WindowDefBuilder::new()
3163 .partition_by(["dept"])
3164 .order_by(["salary"]),
3165 )
3166 .to_sql();
3167 assert!(sql.contains("WINDOW"));
3168 assert!(sql.contains("PARTITION BY"));
3169 }
3170
3171 #[test]
3174 fn test_xor() {
3175 let sql = select(["*"])
3176 .from("t")
3177 .where_(col("a").xor(col("b")))
3178 .to_sql();
3179 assert_eq!(sql, "SELECT * FROM t WHERE a XOR b");
3180 }
3181
3182 #[test]
3185 fn test_for_update() {
3186 let sql = select(["id"]).from("t").for_update().to_sql();
3187 assert_eq!(sql, "SELECT id FROM t FOR UPDATE");
3188 }
3189
3190 #[test]
3191 fn test_for_share() {
3192 let sql = select(["id"]).from("t").for_share().to_sql();
3193 assert_eq!(sql, "SELECT id FROM t FOR SHARE");
3194 }
3195
3196 #[test]
3199 fn test_hint() {
3200 let sql = select(["*"]).from("t").hint("FULL(t)").to_sql();
3201 assert!(sql.contains("FULL(t)"), "Expected hint in: {}", sql);
3202 }
3203
3204 #[test]
3207 fn test_ctas() {
3208 let expr = select(["*"]).from("t").ctas("new_table");
3209 let sql = Generator::sql(&expr).unwrap();
3210 assert_eq!(sql, "CREATE TABLE new_table AS SELECT * FROM t");
3211 }
3212
3213 #[test]
3216 fn test_merge_update_insert() {
3217 let sql = merge_into("target")
3218 .using("source", col("target.id").eq(col("source.id")))
3219 .when_matched_update(vec![("name", col("source.name"))])
3220 .when_not_matched_insert(&["id", "name"], vec![col("source.id"), col("source.name")])
3221 .to_sql();
3222 assert!(
3223 sql.contains("MERGE INTO"),
3224 "Expected MERGE INTO in: {}",
3225 sql
3226 );
3227 assert!(sql.contains("USING"), "Expected USING in: {}", sql);
3228 assert!(
3229 sql.contains("WHEN MATCHED"),
3230 "Expected WHEN MATCHED in: {}",
3231 sql
3232 );
3233 assert!(
3234 sql.contains("UPDATE SET"),
3235 "Expected UPDATE SET in: {}",
3236 sql
3237 );
3238 assert!(
3239 sql.contains("WHEN NOT MATCHED"),
3240 "Expected WHEN NOT MATCHED in: {}",
3241 sql
3242 );
3243 assert!(sql.contains("INSERT"), "Expected INSERT in: {}", sql);
3244 }
3245
3246 #[test]
3247 fn test_merge_delete() {
3248 let sql = merge_into("target")
3249 .using("source", col("target.id").eq(col("source.id")))
3250 .when_matched_delete()
3251 .to_sql();
3252 assert!(
3253 sql.contains("MERGE INTO"),
3254 "Expected MERGE INTO in: {}",
3255 sql
3256 );
3257 assert!(
3258 sql.contains("WHEN MATCHED THEN DELETE"),
3259 "Expected WHEN MATCHED THEN DELETE in: {}",
3260 sql
3261 );
3262 }
3263
3264 #[test]
3265 fn test_merge_with_condition() {
3266 let sql = merge_into("target")
3267 .using("source", col("target.id").eq(col("source.id")))
3268 .when_matched_update_where(
3269 col("source.active").eq(boolean(true)),
3270 vec![("name", col("source.name"))],
3271 )
3272 .to_sql();
3273 assert!(
3274 sql.contains("MERGE INTO"),
3275 "Expected MERGE INTO in: {}",
3276 sql
3277 );
3278 assert!(
3279 sql.contains("AND source.active = TRUE"),
3280 "Expected condition in: {}",
3281 sql
3282 );
3283 }
3284}