1use crate::expressions::*;
59use crate::generator::Generator;
60use crate::parser::Parser;
61
62fn is_safe_identifier_name(name: &str) -> bool {
63 if name.is_empty() {
64 return false;
65 }
66
67 let mut chars = name.chars();
68 let Some(first) = chars.next() else {
69 return false;
70 };
71
72 if !(first == '_' || first.is_ascii_alphabetic()) {
73 return false;
74 }
75
76 chars.all(|c| c == '_' || c.is_ascii_alphanumeric())
77}
78
79fn builder_identifier(name: &str) -> Identifier {
80 if name == "*" || is_safe_identifier_name(name) {
81 Identifier::new(name)
82 } else {
83 Identifier::quoted(name)
84 }
85}
86
87fn builder_table_ref(name: &str) -> TableRef {
88 let parts: Vec<&str> = name.split('.').collect();
89
90 match parts.len() {
91 3 => {
92 let mut t = TableRef::new(parts[2]);
93 t.name = builder_identifier(parts[2]);
94 t.schema = Some(builder_identifier(parts[1]));
95 t.catalog = Some(builder_identifier(parts[0]));
96 t
97 }
98 2 => {
99 let mut t = TableRef::new(parts[1]);
100 t.name = builder_identifier(parts[1]);
101 t.schema = Some(builder_identifier(parts[0]));
102 t
103 }
104 _ => {
105 let first = parts.first().copied().unwrap_or("");
106 let mut t = TableRef::new(first);
107 t.name = builder_identifier(first);
108 t
109 }
110 }
111}
112
113pub fn col(name: &str) -> Expr {
137 if let Some((table, column)) = name.rsplit_once('.') {
138 Expr(Expression::Column(Column {
139 name: builder_identifier(column),
140 table: Some(builder_identifier(table)),
141 join_mark: false,
142 trailing_comments: Vec::new(),
143 span: None,
144 inferred_type: None,
145 }))
146 } else {
147 Expr(Expression::Column(Column {
148 name: builder_identifier(name),
149 table: None,
150 join_mark: false,
151 trailing_comments: Vec::new(),
152 span: None,
153 inferred_type: None,
154 }))
155 }
156}
157
158pub fn lit<V: IntoLiteral>(value: V) -> Expr {
174 value.into_literal()
175}
176
177pub fn star() -> Expr {
179 Expr(Expression::star())
180}
181
182pub fn null() -> Expr {
184 Expr(Expression::Null(Null))
185}
186
187pub fn boolean(value: bool) -> Expr {
189 Expr(Expression::Boolean(BooleanLiteral { value }))
190}
191
192pub fn table(name: &str) -> Expr {
209 Expr(Expression::Table(builder_table_ref(name)))
210}
211
212pub fn func(name: &str, args: impl IntoIterator<Item = Expr>) -> Expr {
229 Expr(Expression::Function(Box::new(Function {
230 name: name.to_string(),
231 args: args.into_iter().map(|a| a.0).collect(),
232 ..Function::default()
233 })))
234}
235
236pub fn cast(expr: Expr, to: &str) -> Expr {
252 let data_type = parse_simple_data_type(to);
253 Expr(Expression::Cast(Box::new(Cast {
254 this: expr.0,
255 to: data_type,
256 trailing_comments: Vec::new(),
257 double_colon_syntax: false,
258 format: None,
259 default: None,
260 inferred_type: None,
261 })))
262}
263
264pub fn not(expr: Expr) -> Expr {
269 Expr(Expression::Not(Box::new(UnaryOp::new(expr.0))))
270}
271
272pub fn and(left: Expr, right: Expr) -> Expr {
277 left.and(right)
278}
279
280pub fn or(left: Expr, right: Expr) -> Expr {
285 left.or(right)
286}
287
288pub fn alias(expr: Expr, name: &str) -> Expr {
293 Expr(Expression::Alias(Box::new(Alias {
294 this: expr.0,
295 alias: builder_identifier(name),
296 column_aliases: Vec::new(),
297 pre_alias_comments: Vec::new(),
298 trailing_comments: Vec::new(),
299 inferred_type: None,
300 })))
301}
302
303pub fn sql_expr(sql: &str) -> Expr {
327 let wrapped = format!("SELECT {}", sql);
328 let ast = Parser::parse_sql(&wrapped).expect("sql_expr: failed to parse SQL expression");
329 if let Expression::Select(s) = &ast[0] {
330 if let Some(first) = s.expressions.first() {
331 return Expr(first.clone());
332 }
333 }
334 panic!("sql_expr: failed to extract expression from parsed SQL");
335}
336
337pub fn condition(sql: &str) -> Expr {
346 sql_expr(sql)
347}
348
349pub fn count(expr: Expr) -> Expr {
357 Expr(Expression::Count(Box::new(CountFunc {
358 this: Some(expr.0),
359 star: false,
360 distinct: false,
361 filter: None,
362 ignore_nulls: None,
363 original_name: None,
364 })))
365}
366
367pub fn count_star() -> Expr {
369 Expr(Expression::Count(Box::new(CountFunc {
370 this: None,
371 star: true,
372 distinct: false,
373 filter: None,
374 ignore_nulls: None,
375 original_name: None,
376 })))
377}
378
379pub fn count_distinct(expr: Expr) -> Expr {
381 Expr(Expression::Count(Box::new(CountFunc {
382 this: Some(expr.0),
383 star: false,
384 distinct: true,
385 filter: None,
386 ignore_nulls: None,
387 original_name: None,
388 })))
389}
390
391pub fn sum(expr: Expr) -> Expr {
393 Expr(Expression::Sum(Box::new(AggFunc {
394 this: expr.0,
395 distinct: false,
396 filter: None,
397 order_by: vec![],
398 name: None,
399 ignore_nulls: None,
400 having_max: None,
401 limit: None,
402 inferred_type: None,
403 })))
404}
405
406pub fn avg(expr: Expr) -> Expr {
408 Expr(Expression::Avg(Box::new(AggFunc {
409 this: expr.0,
410 distinct: false,
411 filter: None,
412 order_by: vec![],
413 name: None,
414 ignore_nulls: None,
415 having_max: None,
416 limit: None,
417 inferred_type: None,
418 })))
419}
420
421pub fn min_(expr: Expr) -> Expr {
423 Expr(Expression::Min(Box::new(AggFunc {
424 this: expr.0,
425 distinct: false,
426 filter: None,
427 order_by: vec![],
428 name: None,
429 ignore_nulls: None,
430 having_max: None,
431 limit: None,
432 inferred_type: None,
433 })))
434}
435
436pub fn max_(expr: Expr) -> Expr {
438 Expr(Expression::Max(Box::new(AggFunc {
439 this: expr.0,
440 distinct: false,
441 filter: None,
442 order_by: vec![],
443 name: None,
444 ignore_nulls: None,
445 having_max: None,
446 limit: None,
447 inferred_type: None,
448 })))
449}
450
451pub fn approx_distinct(expr: Expr) -> Expr {
453 Expr(Expression::ApproxDistinct(Box::new(AggFunc {
454 this: expr.0,
455 distinct: false,
456 filter: None,
457 order_by: vec![],
458 name: None,
459 ignore_nulls: None,
460 having_max: None,
461 limit: None,
462 inferred_type: None,
463 })))
464}
465
466pub fn upper(expr: Expr) -> Expr {
470 Expr(Expression::Upper(Box::new(UnaryFunc::new(expr.0))))
471}
472
473pub fn lower(expr: Expr) -> Expr {
475 Expr(Expression::Lower(Box::new(UnaryFunc::new(expr.0))))
476}
477
478pub fn length(expr: Expr) -> Expr {
480 Expr(Expression::Length(Box::new(UnaryFunc::new(expr.0))))
481}
482
483pub fn trim(expr: Expr) -> Expr {
485 Expr(Expression::Trim(Box::new(TrimFunc {
486 this: expr.0,
487 characters: None,
488 position: TrimPosition::Both,
489 sql_standard_syntax: false,
490 position_explicit: false,
491 })))
492}
493
494pub fn ltrim(expr: Expr) -> Expr {
496 Expr(Expression::LTrim(Box::new(UnaryFunc::new(expr.0))))
497}
498
499pub fn rtrim(expr: Expr) -> Expr {
501 Expr(Expression::RTrim(Box::new(UnaryFunc::new(expr.0))))
502}
503
504pub fn reverse(expr: Expr) -> Expr {
506 Expr(Expression::Reverse(Box::new(UnaryFunc::new(expr.0))))
507}
508
509pub fn initcap(expr: Expr) -> Expr {
511 Expr(Expression::Initcap(Box::new(UnaryFunc::new(expr.0))))
512}
513
514pub fn substring(expr: Expr, start: Expr, len: Option<Expr>) -> Expr {
516 Expr(Expression::Substring(Box::new(SubstringFunc {
517 this: expr.0,
518 start: start.0,
519 length: len.map(|l| l.0),
520 from_for_syntax: false,
521 })))
522}
523
524pub fn replace_(expr: Expr, old: Expr, new: Expr) -> Expr {
527 Expr(Expression::Replace(Box::new(ReplaceFunc {
528 this: expr.0,
529 old: old.0,
530 new: new.0,
531 })))
532}
533
534pub fn concat_ws(separator: Expr, exprs: impl IntoIterator<Item = Expr>) -> Expr {
536 Expr(Expression::ConcatWs(Box::new(ConcatWs {
537 separator: separator.0,
538 expressions: exprs.into_iter().map(|e| e.0).collect(),
539 })))
540}
541
542pub fn coalesce(exprs: impl IntoIterator<Item = Expr>) -> Expr {
546 Expr(Expression::Coalesce(Box::new(VarArgFunc {
547 expressions: exprs.into_iter().map(|e| e.0).collect(),
548 original_name: None,
549 inferred_type: None,
550 })))
551}
552
553pub fn null_if(expr1: Expr, expr2: Expr) -> Expr {
555 Expr(Expression::NullIf(Box::new(BinaryFunc {
556 this: expr1.0,
557 expression: expr2.0,
558 original_name: None,
559 inferred_type: None,
560 })))
561}
562
563pub fn if_null(expr: Expr, fallback: Expr) -> Expr {
565 Expr(Expression::IfNull(Box::new(BinaryFunc {
566 this: expr.0,
567 expression: fallback.0,
568 original_name: None,
569 inferred_type: None,
570 })))
571}
572
573pub fn abs(expr: Expr) -> Expr {
577 Expr(Expression::Abs(Box::new(UnaryFunc::new(expr.0))))
578}
579
580pub fn round(expr: Expr, decimals: Option<Expr>) -> Expr {
582 Expr(Expression::Round(Box::new(RoundFunc {
583 this: expr.0,
584 decimals: decimals.map(|d| d.0),
585 })))
586}
587
588pub fn floor(expr: Expr) -> Expr {
590 Expr(Expression::Floor(Box::new(FloorFunc {
591 this: expr.0,
592 scale: None,
593 to: None,
594 })))
595}
596
597pub fn ceil(expr: Expr) -> Expr {
599 Expr(Expression::Ceil(Box::new(CeilFunc {
600 this: expr.0,
601 decimals: None,
602 to: None,
603 })))
604}
605
606pub fn power(base: Expr, exponent: Expr) -> Expr {
608 Expr(Expression::Power(Box::new(BinaryFunc {
609 this: base.0,
610 expression: exponent.0,
611 original_name: None,
612 inferred_type: None,
613 })))
614}
615
616pub fn sqrt(expr: Expr) -> Expr {
618 Expr(Expression::Sqrt(Box::new(UnaryFunc::new(expr.0))))
619}
620
621pub fn ln(expr: Expr) -> Expr {
623 Expr(Expression::Ln(Box::new(UnaryFunc::new(expr.0))))
624}
625
626pub fn exp_(expr: Expr) -> Expr {
628 Expr(Expression::Exp(Box::new(UnaryFunc::new(expr.0))))
629}
630
631pub fn sign(expr: Expr) -> Expr {
633 Expr(Expression::Sign(Box::new(UnaryFunc::new(expr.0))))
634}
635
636pub fn greatest(exprs: impl IntoIterator<Item = Expr>) -> Expr {
638 Expr(Expression::Greatest(Box::new(VarArgFunc {
639 expressions: exprs.into_iter().map(|e| e.0).collect(),
640 original_name: None,
641 inferred_type: None,
642 })))
643}
644
645pub fn least(exprs: impl IntoIterator<Item = Expr>) -> Expr {
647 Expr(Expression::Least(Box::new(VarArgFunc {
648 expressions: exprs.into_iter().map(|e| e.0).collect(),
649 original_name: None,
650 inferred_type: None,
651 })))
652}
653
654pub fn current_date_() -> Expr {
658 Expr(Expression::CurrentDate(CurrentDate))
659}
660
661pub fn current_time_() -> Expr {
663 Expr(Expression::CurrentTime(CurrentTime { precision: None }))
664}
665
666pub fn current_timestamp_() -> Expr {
668 Expr(Expression::CurrentTimestamp(CurrentTimestamp {
669 precision: None,
670 sysdate: false,
671 }))
672}
673
674pub fn extract_(field: &str, expr: Expr) -> Expr {
676 Expr(Expression::Extract(Box::new(ExtractFunc {
677 this: expr.0,
678 field: parse_datetime_field(field),
679 })))
680}
681
682fn parse_datetime_field(field: &str) -> DateTimeField {
684 match field.to_uppercase().as_str() {
685 "YEAR" => DateTimeField::Year,
686 "MONTH" => DateTimeField::Month,
687 "DAY" => DateTimeField::Day,
688 "HOUR" => DateTimeField::Hour,
689 "MINUTE" => DateTimeField::Minute,
690 "SECOND" => DateTimeField::Second,
691 "MILLISECOND" => DateTimeField::Millisecond,
692 "MICROSECOND" => DateTimeField::Microsecond,
693 "DOW" | "DAYOFWEEK" => DateTimeField::DayOfWeek,
694 "DOY" | "DAYOFYEAR" => DateTimeField::DayOfYear,
695 "WEEK" => DateTimeField::Week,
696 "QUARTER" => DateTimeField::Quarter,
697 "EPOCH" => DateTimeField::Epoch,
698 "TIMEZONE" => DateTimeField::Timezone,
699 "TIMEZONE_HOUR" => DateTimeField::TimezoneHour,
700 "TIMEZONE_MINUTE" => DateTimeField::TimezoneMinute,
701 "DATE" => DateTimeField::Date,
702 "TIME" => DateTimeField::Time,
703 other => DateTimeField::Custom(other.to_string()),
704 }
705}
706
707pub fn row_number() -> Expr {
711 Expr(Expression::RowNumber(RowNumber))
712}
713
714pub fn rank_() -> Expr {
716 Expr(Expression::Rank(Rank {
717 order_by: None,
718 args: vec![],
719 }))
720}
721
722pub fn dense_rank() -> Expr {
724 Expr(Expression::DenseRank(DenseRank { args: vec![] }))
725}
726
727pub fn select<I, E>(expressions: I) -> SelectBuilder
754where
755 I: IntoIterator<Item = E>,
756 E: IntoExpr,
757{
758 let mut builder = SelectBuilder::new();
759 for expr in expressions {
760 builder.select = builder.select.column(expr.into_expr().0);
761 }
762 builder
763}
764
765pub fn from(table_name: &str) -> SelectBuilder {
780 let mut builder = SelectBuilder::new();
781 builder.select.from = Some(From {
782 expressions: vec![Expression::Table(builder_table_ref(table_name))],
783 });
784 builder
785}
786
787pub fn delete(table_name: &str) -> DeleteBuilder {
800 DeleteBuilder {
801 delete: Delete {
802 table: builder_table_ref(table_name),
803 on_cluster: None,
804 alias: None,
805 alias_explicit_as: false,
806 using: Vec::new(),
807 where_clause: None,
808 output: None,
809 leading_comments: Vec::new(),
810 with: None,
811 limit: None,
812 order_by: None,
813 returning: Vec::new(),
814 tables: Vec::new(),
815 tables_from_using: false,
816 joins: Vec::new(),
817 force_index: None,
818 no_from: false,
819 },
820 }
821}
822
823pub fn insert_into(table_name: &str) -> InsertBuilder {
840 InsertBuilder {
841 insert: Insert {
842 table: builder_table_ref(table_name),
843 columns: Vec::new(),
844 values: Vec::new(),
845 query: None,
846 overwrite: false,
847 partition: Vec::new(),
848 directory: None,
849 returning: Vec::new(),
850 output: None,
851 on_conflict: None,
852 leading_comments: Vec::new(),
853 if_exists: false,
854 with: None,
855 ignore: false,
856 source_alias: None,
857 alias: None,
858 alias_explicit_as: false,
859 default_values: false,
860 by_name: false,
861 conflict_action: None,
862 is_replace: false,
863 hint: None,
864 replace_where: None,
865 source: None,
866 function_target: None,
867 partition_by: None,
868 settings: Vec::new(),
869 },
870 }
871}
872
873pub fn update(table_name: &str) -> UpdateBuilder {
891 UpdateBuilder {
892 update: Update {
893 table: builder_table_ref(table_name),
894 extra_tables: Vec::new(),
895 table_joins: Vec::new(),
896 set: Vec::new(),
897 from_clause: None,
898 from_joins: Vec::new(),
899 where_clause: None,
900 returning: Vec::new(),
901 output: None,
902 with: None,
903 leading_comments: Vec::new(),
904 limit: None,
905 order_by: None,
906 from_before_set: false,
907 },
908 }
909}
910
911#[derive(Debug, Clone)]
936pub struct Expr(pub Expression);
937
938impl Expr {
939 pub fn into_inner(self) -> Expression {
941 self.0
942 }
943
944 pub fn to_sql(&self) -> String {
948 Generator::sql(&self.0).unwrap_or_default()
949 }
950
951 pub fn eq(self, other: Expr) -> Expr {
955 Expr(Expression::Eq(Box::new(binary_op(self.0, other.0))))
956 }
957
958 pub fn neq(self, other: Expr) -> Expr {
960 Expr(Expression::Neq(Box::new(binary_op(self.0, other.0))))
961 }
962
963 pub fn lt(self, other: Expr) -> Expr {
965 Expr(Expression::Lt(Box::new(binary_op(self.0, other.0))))
966 }
967
968 pub fn lte(self, other: Expr) -> Expr {
970 Expr(Expression::Lte(Box::new(binary_op(self.0, other.0))))
971 }
972
973 pub fn gt(self, other: Expr) -> Expr {
975 Expr(Expression::Gt(Box::new(binary_op(self.0, other.0))))
976 }
977
978 pub fn gte(self, other: Expr) -> Expr {
980 Expr(Expression::Gte(Box::new(binary_op(self.0, other.0))))
981 }
982
983 pub fn and(self, other: Expr) -> Expr {
987 Expr(Expression::And(Box::new(binary_op(self.0, other.0))))
988 }
989
990 pub fn or(self, other: Expr) -> Expr {
992 Expr(Expression::Or(Box::new(binary_op(self.0, other.0))))
993 }
994
995 pub fn not(self) -> Expr {
997 Expr(Expression::Not(Box::new(UnaryOp::new(self.0))))
998 }
999
1000 pub fn xor(self, other: Expr) -> Expr {
1002 Expr(Expression::Xor(Box::new(Xor {
1003 this: Some(Box::new(self.0)),
1004 expression: Some(Box::new(other.0)),
1005 expressions: vec![],
1006 })))
1007 }
1008
1009 pub fn add(self, other: Expr) -> Expr {
1013 Expr(Expression::Add(Box::new(binary_op(self.0, other.0))))
1014 }
1015
1016 pub fn sub(self, other: Expr) -> Expr {
1018 Expr(Expression::Sub(Box::new(binary_op(self.0, other.0))))
1019 }
1020
1021 pub fn mul(self, other: Expr) -> Expr {
1023 Expr(Expression::Mul(Box::new(binary_op(self.0, other.0))))
1024 }
1025
1026 pub fn div(self, other: Expr) -> Expr {
1028 Expr(Expression::Div(Box::new(binary_op(self.0, other.0))))
1029 }
1030
1031 pub fn is_null(self) -> Expr {
1035 Expr(Expression::Is(Box::new(BinaryOp {
1036 left: self.0,
1037 right: Expression::Null(Null),
1038 left_comments: Vec::new(),
1039 operator_comments: Vec::new(),
1040 trailing_comments: Vec::new(),
1041 inferred_type: None,
1042 })))
1043 }
1044
1045 pub fn is_not_null(self) -> Expr {
1047 Expr(Expression::Not(Box::new(UnaryOp::new(Expression::Is(
1048 Box::new(BinaryOp {
1049 left: self.0,
1050 right: Expression::Null(Null),
1051 left_comments: Vec::new(),
1052 operator_comments: Vec::new(),
1053 trailing_comments: Vec::new(),
1054 inferred_type: None,
1055 }),
1056 )))))
1057 }
1058
1059 pub fn in_list(self, values: impl IntoIterator<Item = Expr>) -> Expr {
1063 Expr(Expression::In(Box::new(In {
1064 this: self.0,
1065 expressions: values.into_iter().map(|v| v.0).collect(),
1066 query: None,
1067 not: false,
1068 global: false,
1069 unnest: None,
1070 is_field: false,
1071 })))
1072 }
1073
1074 pub fn between(self, low: Expr, high: Expr) -> Expr {
1076 Expr(Expression::Between(Box::new(Between {
1077 this: self.0,
1078 low: low.0,
1079 high: high.0,
1080 not: false,
1081 symmetric: None,
1082 })))
1083 }
1084
1085 pub fn like(self, pattern: Expr) -> Expr {
1087 Expr(Expression::Like(Box::new(LikeOp {
1088 left: self.0,
1089 right: pattern.0,
1090 escape: None,
1091 quantifier: None,
1092 inferred_type: None,
1093 })))
1094 }
1095
1096 pub fn alias(self, name: &str) -> Expr {
1098 alias(self, name)
1099 }
1100
1101 pub fn cast(self, to: &str) -> Expr {
1105 cast(self, to)
1106 }
1107
1108 pub fn asc(self) -> Expr {
1113 Expr(Expression::Ordered(Box::new(Ordered {
1114 this: self.0,
1115 desc: false,
1116 nulls_first: None,
1117 explicit_asc: true,
1118 with_fill: None,
1119 })))
1120 }
1121
1122 pub fn desc(self) -> Expr {
1126 Expr(Expression::Ordered(Box::new(Ordered {
1127 this: self.0,
1128 desc: true,
1129 nulls_first: None,
1130 explicit_asc: false,
1131 with_fill: None,
1132 })))
1133 }
1134
1135 pub fn ilike(self, pattern: Expr) -> Expr {
1140 Expr(Expression::ILike(Box::new(LikeOp {
1141 left: self.0,
1142 right: pattern.0,
1143 escape: None,
1144 quantifier: None,
1145 inferred_type: None,
1146 })))
1147 }
1148
1149 pub fn rlike(self, pattern: Expr) -> Expr {
1154 Expr(Expression::RegexpLike(Box::new(RegexpFunc {
1155 this: self.0,
1156 pattern: pattern.0,
1157 flags: None,
1158 })))
1159 }
1160
1161 pub fn not_in(self, values: impl IntoIterator<Item = Expr>) -> Expr {
1165 Expr(Expression::In(Box::new(In {
1166 this: self.0,
1167 expressions: values.into_iter().map(|v| v.0).collect(),
1168 query: None,
1169 not: true,
1170 global: false,
1171 unnest: None,
1172 is_field: false,
1173 })))
1174 }
1175}
1176
1177pub struct SelectBuilder {
1203 select: Select,
1204}
1205
1206impl SelectBuilder {
1207 fn new() -> Self {
1208 SelectBuilder {
1209 select: Select::new(),
1210 }
1211 }
1212
1213 pub fn select_cols<I, E>(mut self, expressions: I) -> Self
1218 where
1219 I: IntoIterator<Item = E>,
1220 E: IntoExpr,
1221 {
1222 for expr in expressions {
1223 self.select.expressions.push(expr.into_expr().0);
1224 }
1225 self
1226 }
1227
1228 pub fn from(mut self, table_name: &str) -> Self {
1230 self.select.from = Some(From {
1231 expressions: vec![Expression::Table(builder_table_ref(table_name))],
1232 });
1233 self
1234 }
1235
1236 pub fn from_expr(mut self, expr: Expr) -> Self {
1241 self.select.from = Some(From {
1242 expressions: vec![expr.0],
1243 });
1244 self
1245 }
1246
1247 pub fn join(mut self, table_name: &str, on: Expr) -> Self {
1249 self.select.joins.push(Join {
1250 kind: JoinKind::Inner,
1251 this: Expression::Table(builder_table_ref(table_name)),
1252 on: Some(on.0),
1253 using: Vec::new(),
1254 use_inner_keyword: false,
1255 use_outer_keyword: false,
1256 deferred_condition: false,
1257 join_hint: None,
1258 match_condition: None,
1259 pivots: Vec::new(),
1260 comments: Vec::new(),
1261 nesting_group: 0,
1262 directed: false,
1263 });
1264 self
1265 }
1266
1267 pub fn left_join(mut self, table_name: &str, on: Expr) -> Self {
1269 self.select.joins.push(Join {
1270 kind: JoinKind::Left,
1271 this: Expression::Table(builder_table_ref(table_name)),
1272 on: Some(on.0),
1273 using: Vec::new(),
1274 use_inner_keyword: false,
1275 use_outer_keyword: false,
1276 deferred_condition: false,
1277 join_hint: None,
1278 match_condition: None,
1279 pivots: Vec::new(),
1280 comments: Vec::new(),
1281 nesting_group: 0,
1282 directed: false,
1283 });
1284 self
1285 }
1286
1287 pub fn where_(mut self, condition: Expr) -> Self {
1293 self.select.where_clause = Some(Where { this: condition.0 });
1294 self
1295 }
1296
1297 pub fn group_by<I, E>(mut self, expressions: I) -> Self
1299 where
1300 I: IntoIterator<Item = E>,
1301 E: IntoExpr,
1302 {
1303 self.select.group_by = Some(GroupBy {
1304 expressions: expressions.into_iter().map(|e| e.into_expr().0).collect(),
1305 all: None,
1306 totals: false,
1307 comments: Vec::new(),
1308 });
1309 self
1310 }
1311
1312 pub fn having(mut self, condition: Expr) -> Self {
1314 self.select.having = Some(Having {
1315 this: condition.0,
1316 comments: Vec::new(),
1317 });
1318 self
1319 }
1320
1321 pub fn order_by<I, E>(mut self, expressions: I) -> Self
1327 where
1328 I: IntoIterator<Item = E>,
1329 E: IntoExpr,
1330 {
1331 self.select.order_by = Some(OrderBy {
1332 siblings: false,
1333 comments: Vec::new(),
1334 expressions: expressions
1335 .into_iter()
1336 .map(|e| {
1337 let expr = e.into_expr().0;
1338 match expr {
1339 Expression::Ordered(_) => expr,
1340 other => Expression::Ordered(Box::new(Ordered {
1341 this: other,
1342 desc: false,
1343 nulls_first: None,
1344 explicit_asc: false,
1345 with_fill: None,
1346 })),
1347 }
1348 })
1349 .collect::<Vec<_>>()
1350 .into_iter()
1351 .map(|e| {
1352 if let Expression::Ordered(o) = e {
1353 *o
1354 } else {
1355 Ordered {
1356 this: e,
1357 desc: false,
1358 nulls_first: None,
1359 explicit_asc: false,
1360 with_fill: None,
1361 }
1362 }
1363 })
1364 .collect(),
1365 });
1366 self
1367 }
1368
1369 pub fn sort_by<I, E>(mut self, expressions: I) -> Self
1376 where
1377 I: IntoIterator<Item = E>,
1378 E: IntoExpr,
1379 {
1380 self.select.sort_by = Some(SortBy {
1381 expressions: expressions
1382 .into_iter()
1383 .map(|e| {
1384 let expr = e.into_expr().0;
1385 match expr {
1386 Expression::Ordered(o) => *o,
1387 other => Ordered {
1388 this: other,
1389 desc: false,
1390 nulls_first: None,
1391 explicit_asc: false,
1392 with_fill: None,
1393 },
1394 }
1395 })
1396 .collect(),
1397 });
1398 self
1399 }
1400
1401 pub fn limit(mut self, count: usize) -> Self {
1403 self.select.limit = Some(Limit {
1404 this: Expression::Literal(Literal::Number(count.to_string())),
1405 percent: false,
1406 comments: Vec::new(),
1407 });
1408 self
1409 }
1410
1411 pub fn offset(mut self, count: usize) -> Self {
1413 self.select.offset = Some(Offset {
1414 this: Expression::Literal(Literal::Number(count.to_string())),
1415 rows: None,
1416 });
1417 self
1418 }
1419
1420 pub fn distinct(mut self) -> Self {
1422 self.select.distinct = true;
1423 self
1424 }
1425
1426 pub fn qualify(mut self, condition: Expr) -> Self {
1431 self.select.qualify = Some(Qualify { this: condition.0 });
1432 self
1433 }
1434
1435 pub fn right_join(mut self, table_name: &str, on: Expr) -> Self {
1437 self.select.joins.push(Join {
1438 kind: JoinKind::Right,
1439 this: Expression::Table(builder_table_ref(table_name)),
1440 on: Some(on.0),
1441 using: Vec::new(),
1442 use_inner_keyword: false,
1443 use_outer_keyword: false,
1444 deferred_condition: false,
1445 join_hint: None,
1446 match_condition: None,
1447 pivots: Vec::new(),
1448 comments: Vec::new(),
1449 nesting_group: 0,
1450 directed: false,
1451 });
1452 self
1453 }
1454
1455 pub fn cross_join(mut self, table_name: &str) -> Self {
1457 self.select.joins.push(Join {
1458 kind: JoinKind::Cross,
1459 this: Expression::Table(builder_table_ref(table_name)),
1460 on: None,
1461 using: Vec::new(),
1462 use_inner_keyword: false,
1463 use_outer_keyword: false,
1464 deferred_condition: false,
1465 join_hint: None,
1466 match_condition: None,
1467 pivots: Vec::new(),
1468 comments: Vec::new(),
1469 nesting_group: 0,
1470 directed: false,
1471 });
1472 self
1473 }
1474
1475 pub fn lateral_view<S: AsRef<str>>(
1482 mut self,
1483 table_function: Expr,
1484 table_alias: &str,
1485 column_aliases: impl IntoIterator<Item = S>,
1486 ) -> Self {
1487 self.select.lateral_views.push(LateralView {
1488 this: table_function.0,
1489 table_alias: Some(builder_identifier(table_alias)),
1490 column_aliases: column_aliases
1491 .into_iter()
1492 .map(|c| builder_identifier(c.as_ref()))
1493 .collect(),
1494 outer: false,
1495 });
1496 self
1497 }
1498
1499 pub fn window(mut self, name: &str, def: WindowDefBuilder) -> Self {
1505 let named_window = NamedWindow {
1506 name: builder_identifier(name),
1507 spec: Over {
1508 window_name: None,
1509 partition_by: def.partition_by,
1510 order_by: def.order_by,
1511 frame: None,
1512 alias: None,
1513 },
1514 };
1515 match self.select.windows {
1516 Some(ref mut windows) => windows.push(named_window),
1517 None => self.select.windows = Some(vec![named_window]),
1518 }
1519 self
1520 }
1521
1522 pub fn for_update(mut self) -> Self {
1527 self.select.locks.push(Lock {
1528 update: Some(Box::new(Expression::Boolean(BooleanLiteral {
1529 value: true,
1530 }))),
1531 expressions: vec![],
1532 wait: None,
1533 key: None,
1534 });
1535 self
1536 }
1537
1538 pub fn for_share(mut self) -> Self {
1543 self.select.locks.push(Lock {
1544 update: None,
1545 expressions: vec![],
1546 wait: None,
1547 key: None,
1548 });
1549 self
1550 }
1551
1552 pub fn hint(mut self, hint_text: &str) -> Self {
1557 let hint_expr = HintExpression::Raw(hint_text.to_string());
1558 match &mut self.select.hint {
1559 Some(h) => h.expressions.push(hint_expr),
1560 None => {
1561 self.select.hint = Some(Hint {
1562 expressions: vec![hint_expr],
1563 })
1564 }
1565 }
1566 self
1567 }
1568
1569 pub fn ctas(self, table_name: &str) -> Expression {
1585 Expression::CreateTable(Box::new(CreateTable {
1586 name: builder_table_ref(table_name),
1587 on_cluster: None,
1588 columns: vec![],
1589 constraints: vec![],
1590 if_not_exists: false,
1591 temporary: false,
1592 or_replace: false,
1593 table_modifier: None,
1594 as_select: Some(self.build()),
1595 as_select_parenthesized: false,
1596 on_commit: None,
1597 clone_source: None,
1598 clone_at_clause: None,
1599 is_copy: false,
1600 shallow_clone: false,
1601 leading_comments: vec![],
1602 with_properties: vec![],
1603 teradata_post_name_options: vec![],
1604 with_data: None,
1605 with_statistics: None,
1606 teradata_indexes: vec![],
1607 with_cte: None,
1608 properties: vec![],
1609 partition_of: None,
1610 post_table_properties: vec![],
1611 mysql_table_options: vec![],
1612 inherits: vec![],
1613 on_property: None,
1614 copy_grants: false,
1615 using_template: None,
1616 rollup: None,
1617 }))
1618 }
1619
1620 pub fn union(self, other: SelectBuilder) -> SetOpBuilder {
1624 SetOpBuilder::new(SetOpKind::Union, self, other, false)
1625 }
1626
1627 pub fn union_all(self, other: SelectBuilder) -> SetOpBuilder {
1631 SetOpBuilder::new(SetOpKind::Union, self, other, true)
1632 }
1633
1634 pub fn intersect(self, other: SelectBuilder) -> SetOpBuilder {
1638 SetOpBuilder::new(SetOpKind::Intersect, self, other, false)
1639 }
1640
1641 pub fn except_(self, other: SelectBuilder) -> SetOpBuilder {
1645 SetOpBuilder::new(SetOpKind::Except, self, other, false)
1646 }
1647
1648 pub fn build(self) -> Expression {
1650 Expression::Select(Box::new(self.select))
1651 }
1652
1653 pub fn to_sql(self) -> String {
1658 Generator::sql(&self.build()).unwrap_or_default()
1659 }
1660}
1661
1662pub struct DeleteBuilder {
1671 delete: Delete,
1672}
1673
1674impl DeleteBuilder {
1675 pub fn where_(mut self, condition: Expr) -> Self {
1677 self.delete.where_clause = Some(Where { this: condition.0 });
1678 self
1679 }
1680
1681 pub fn build(self) -> Expression {
1683 Expression::Delete(Box::new(self.delete))
1684 }
1685
1686 pub fn to_sql(self) -> String {
1688 Generator::sql(&self.build()).unwrap_or_default()
1689 }
1690}
1691
1692pub struct InsertBuilder {
1703 insert: Insert,
1704}
1705
1706impl InsertBuilder {
1707 pub fn columns<I, S>(mut self, columns: I) -> Self
1709 where
1710 I: IntoIterator<Item = S>,
1711 S: AsRef<str>,
1712 {
1713 self.insert.columns = columns
1714 .into_iter()
1715 .map(|c| builder_identifier(c.as_ref()))
1716 .collect();
1717 self
1718 }
1719
1720 pub fn values<I>(mut self, values: I) -> Self
1724 where
1725 I: IntoIterator<Item = Expr>,
1726 {
1727 self.insert
1728 .values
1729 .push(values.into_iter().map(|v| v.0).collect());
1730 self
1731 }
1732
1733 pub fn query(mut self, query: SelectBuilder) -> Self {
1737 self.insert.query = Some(query.build());
1738 self
1739 }
1740
1741 pub fn build(self) -> Expression {
1743 Expression::Insert(Box::new(self.insert))
1744 }
1745
1746 pub fn to_sql(self) -> String {
1748 Generator::sql(&self.build()).unwrap_or_default()
1749 }
1750}
1751
1752pub struct UpdateBuilder {
1762 update: Update,
1763}
1764
1765impl UpdateBuilder {
1766 pub fn set(mut self, column: &str, value: Expr) -> Self {
1770 self.update.set.push((builder_identifier(column), value.0));
1771 self
1772 }
1773
1774 pub fn where_(mut self, condition: Expr) -> Self {
1776 self.update.where_clause = Some(Where { this: condition.0 });
1777 self
1778 }
1779
1780 pub fn from(mut self, table_name: &str) -> Self {
1784 self.update.from_clause = Some(From {
1785 expressions: vec![Expression::Table(builder_table_ref(table_name))],
1786 });
1787 self
1788 }
1789
1790 pub fn build(self) -> Expression {
1792 Expression::Update(Box::new(self.update))
1793 }
1794
1795 pub fn to_sql(self) -> String {
1797 Generator::sql(&self.build()).unwrap_or_default()
1798 }
1799}
1800
1801pub fn case() -> CaseBuilder {
1826 CaseBuilder {
1827 operand: None,
1828 whens: Vec::new(),
1829 else_: None,
1830 }
1831}
1832
1833pub fn case_of(operand: Expr) -> CaseBuilder {
1854 CaseBuilder {
1855 operand: Some(operand.0),
1856 whens: Vec::new(),
1857 else_: None,
1858 }
1859}
1860
1861pub struct CaseBuilder {
1869 operand: Option<Expression>,
1870 whens: Vec<(Expression, Expression)>,
1871 else_: Option<Expression>,
1872}
1873
1874impl CaseBuilder {
1875 pub fn when(mut self, condition: Expr, result: Expr) -> Self {
1880 self.whens.push((condition.0, result.0));
1881 self
1882 }
1883
1884 pub fn else_(mut self, result: Expr) -> Self {
1889 self.else_ = Some(result.0);
1890 self
1891 }
1892
1893 pub fn build(self) -> Expr {
1895 Expr(self.build_expr())
1896 }
1897
1898 pub fn build_expr(self) -> Expression {
1903 Expression::Case(Box::new(Case {
1904 operand: self.operand,
1905 whens: self.whens,
1906 else_: self.else_,
1907 comments: Vec::new(),
1908 inferred_type: None,
1909 }))
1910 }
1911}
1912
1913pub fn subquery(query: SelectBuilder, alias_name: &str) -> Expr {
1937 subquery_expr(query.build(), alias_name)
1938}
1939
1940pub fn subquery_expr(expr: Expression, alias_name: &str) -> Expr {
1945 Expr(Expression::Subquery(Box::new(Subquery {
1946 this: expr,
1947 alias: Some(builder_identifier(alias_name)),
1948 column_aliases: Vec::new(),
1949 order_by: None,
1950 limit: None,
1951 offset: None,
1952 distribute_by: None,
1953 sort_by: None,
1954 cluster_by: None,
1955 lateral: false,
1956 modifiers_inside: true,
1957 trailing_comments: Vec::new(),
1958 inferred_type: None,
1959 })))
1960}
1961
1962#[derive(Debug, Clone, Copy)]
1968enum SetOpKind {
1969 Union,
1970 Intersect,
1971 Except,
1972}
1973
1974pub struct SetOpBuilder {
1995 kind: SetOpKind,
1996 left: Expression,
1997 right: Expression,
1998 all: bool,
1999 order_by: Option<OrderBy>,
2000 limit: Option<Box<Expression>>,
2001 offset: Option<Box<Expression>>,
2002}
2003
2004impl SetOpBuilder {
2005 fn new(kind: SetOpKind, left: SelectBuilder, right: SelectBuilder, all: bool) -> Self {
2006 SetOpBuilder {
2007 kind,
2008 left: left.build(),
2009 right: right.build(),
2010 all,
2011 order_by: None,
2012 limit: None,
2013 offset: None,
2014 }
2015 }
2016
2017 pub fn order_by<I, E>(mut self, expressions: I) -> Self
2022 where
2023 I: IntoIterator<Item = E>,
2024 E: IntoExpr,
2025 {
2026 self.order_by = Some(OrderBy {
2027 siblings: false,
2028 comments: Vec::new(),
2029 expressions: expressions
2030 .into_iter()
2031 .map(|e| {
2032 let expr = e.into_expr().0;
2033 match expr {
2034 Expression::Ordered(o) => *o,
2035 other => Ordered {
2036 this: other,
2037 desc: false,
2038 nulls_first: None,
2039 explicit_asc: false,
2040 with_fill: None,
2041 },
2042 }
2043 })
2044 .collect(),
2045 });
2046 self
2047 }
2048
2049 pub fn limit(mut self, count: usize) -> Self {
2051 self.limit = Some(Box::new(Expression::Literal(Literal::Number(
2052 count.to_string(),
2053 ))));
2054 self
2055 }
2056
2057 pub fn offset(mut self, count: usize) -> Self {
2059 self.offset = Some(Box::new(Expression::Literal(Literal::Number(
2060 count.to_string(),
2061 ))));
2062 self
2063 }
2064
2065 pub fn build(self) -> Expression {
2070 match self.kind {
2071 SetOpKind::Union => Expression::Union(Box::new(Union {
2072 left: self.left,
2073 right: self.right,
2074 all: self.all,
2075 distinct: false,
2076 with: None,
2077 order_by: self.order_by,
2078 limit: self.limit,
2079 offset: self.offset,
2080 distribute_by: None,
2081 sort_by: None,
2082 cluster_by: None,
2083 by_name: false,
2084 side: None,
2085 kind: None,
2086 corresponding: false,
2087 strict: false,
2088 on_columns: Vec::new(),
2089 })),
2090 SetOpKind::Intersect => Expression::Intersect(Box::new(Intersect {
2091 left: self.left,
2092 right: self.right,
2093 all: self.all,
2094 distinct: false,
2095 with: None,
2096 order_by: self.order_by,
2097 limit: self.limit,
2098 offset: self.offset,
2099 distribute_by: None,
2100 sort_by: None,
2101 cluster_by: None,
2102 by_name: false,
2103 side: None,
2104 kind: None,
2105 corresponding: false,
2106 strict: false,
2107 on_columns: Vec::new(),
2108 })),
2109 SetOpKind::Except => Expression::Except(Box::new(Except {
2110 left: self.left,
2111 right: self.right,
2112 all: self.all,
2113 distinct: false,
2114 with: None,
2115 order_by: self.order_by,
2116 limit: self.limit,
2117 offset: self.offset,
2118 distribute_by: None,
2119 sort_by: None,
2120 cluster_by: None,
2121 by_name: false,
2122 side: None,
2123 kind: None,
2124 corresponding: false,
2125 strict: false,
2126 on_columns: Vec::new(),
2127 })),
2128 }
2129 }
2130
2131 pub fn to_sql(self) -> String {
2133 Generator::sql(&self.build()).unwrap_or_default()
2134 }
2135}
2136
2137pub fn union(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2141 SetOpBuilder::new(SetOpKind::Union, left, right, false)
2142}
2143
2144pub fn union_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2148 SetOpBuilder::new(SetOpKind::Union, left, right, true)
2149}
2150
2151pub fn intersect(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2155 SetOpBuilder::new(SetOpKind::Intersect, left, right, false)
2156}
2157
2158pub fn intersect_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2162 SetOpBuilder::new(SetOpKind::Intersect, left, right, true)
2163}
2164
2165pub fn except_(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2169 SetOpBuilder::new(SetOpKind::Except, left, right, false)
2170}
2171
2172pub fn except_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2176 SetOpBuilder::new(SetOpKind::Except, left, right, true)
2177}
2178
2179pub struct WindowDefBuilder {
2204 partition_by: Vec<Expression>,
2205 order_by: Vec<Ordered>,
2206}
2207
2208impl WindowDefBuilder {
2209 pub fn new() -> Self {
2211 WindowDefBuilder {
2212 partition_by: Vec::new(),
2213 order_by: Vec::new(),
2214 }
2215 }
2216
2217 pub fn partition_by<I, E>(mut self, expressions: I) -> Self
2219 where
2220 I: IntoIterator<Item = E>,
2221 E: IntoExpr,
2222 {
2223 self.partition_by = expressions.into_iter().map(|e| e.into_expr().0).collect();
2224 self
2225 }
2226
2227 pub fn order_by<I, E>(mut self, expressions: I) -> Self
2232 where
2233 I: IntoIterator<Item = E>,
2234 E: IntoExpr,
2235 {
2236 self.order_by = expressions
2237 .into_iter()
2238 .map(|e| {
2239 let expr = e.into_expr().0;
2240 match expr {
2241 Expression::Ordered(o) => *o,
2242 other => Ordered {
2243 this: other,
2244 desc: false,
2245 nulls_first: None,
2246 explicit_asc: false,
2247 with_fill: None,
2248 },
2249 }
2250 })
2251 .collect();
2252 self
2253 }
2254}
2255
2256pub trait IntoExpr {
2275 fn into_expr(self) -> Expr;
2277}
2278
2279impl IntoExpr for Expr {
2280 fn into_expr(self) -> Expr {
2281 self
2282 }
2283}
2284
2285impl IntoExpr for &str {
2286 fn into_expr(self) -> Expr {
2288 col(self)
2289 }
2290}
2291
2292impl IntoExpr for String {
2293 fn into_expr(self) -> Expr {
2295 col(&self)
2296 }
2297}
2298
2299impl IntoExpr for Expression {
2300 fn into_expr(self) -> Expr {
2302 Expr(self)
2303 }
2304}
2305
2306pub trait IntoLiteral {
2321 fn into_literal(self) -> Expr;
2323}
2324
2325impl IntoLiteral for &str {
2326 fn into_literal(self) -> Expr {
2328 Expr(Expression::Literal(Literal::String(self.to_string())))
2329 }
2330}
2331
2332impl IntoLiteral for String {
2333 fn into_literal(self) -> Expr {
2335 Expr(Expression::Literal(Literal::String(self)))
2336 }
2337}
2338
2339impl IntoLiteral for i64 {
2340 fn into_literal(self) -> Expr {
2342 Expr(Expression::Literal(Literal::Number(self.to_string())))
2343 }
2344}
2345
2346impl IntoLiteral for i32 {
2347 fn into_literal(self) -> Expr {
2349 Expr(Expression::Literal(Literal::Number(self.to_string())))
2350 }
2351}
2352
2353impl IntoLiteral for usize {
2354 fn into_literal(self) -> Expr {
2356 Expr(Expression::Literal(Literal::Number(self.to_string())))
2357 }
2358}
2359
2360impl IntoLiteral for f64 {
2361 fn into_literal(self) -> Expr {
2363 Expr(Expression::Literal(Literal::Number(self.to_string())))
2364 }
2365}
2366
2367impl IntoLiteral for bool {
2368 fn into_literal(self) -> Expr {
2370 Expr(Expression::Boolean(BooleanLiteral { value: self }))
2371 }
2372}
2373
2374fn binary_op(left: Expression, right: Expression) -> BinaryOp {
2379 BinaryOp {
2380 left,
2381 right,
2382 left_comments: Vec::new(),
2383 operator_comments: Vec::new(),
2384 trailing_comments: Vec::new(),
2385 inferred_type: None,
2386 }
2387}
2388
2389pub fn merge_into(target: &str) -> MergeBuilder {
2411 MergeBuilder {
2412 target: Expression::Table(builder_table_ref(target)),
2413 using: None,
2414 on: None,
2415 whens: Vec::new(),
2416 }
2417}
2418
2419pub struct MergeBuilder {
2423 target: Expression,
2424 using: Option<Expression>,
2425 on: Option<Expression>,
2426 whens: Vec<Expression>,
2427}
2428
2429impl MergeBuilder {
2430 pub fn using(mut self, source: &str, on: Expr) -> Self {
2432 self.using = Some(Expression::Table(builder_table_ref(source)));
2433 self.on = Some(on.0);
2434 self
2435 }
2436
2437 pub fn when_matched_update(mut self, assignments: Vec<(&str, Expr)>) -> Self {
2439 let eqs: Vec<Expression> = assignments
2440 .into_iter()
2441 .map(|(col_name, val)| {
2442 Expression::Eq(Box::new(BinaryOp {
2443 left: Expression::Column(Column {
2444 name: builder_identifier(col_name),
2445 table: None,
2446 join_mark: false,
2447 trailing_comments: Vec::new(),
2448 span: None,
2449 inferred_type: None,
2450 }),
2451 right: val.0,
2452 left_comments: Vec::new(),
2453 operator_comments: Vec::new(),
2454 trailing_comments: Vec::new(),
2455 inferred_type: None,
2456 }))
2457 })
2458 .collect();
2459
2460 let action = Expression::Tuple(Box::new(Tuple {
2461 expressions: vec![
2462 Expression::Var(Box::new(Var {
2463 this: "UPDATE".to_string(),
2464 })),
2465 Expression::Tuple(Box::new(Tuple { expressions: eqs })),
2466 ],
2467 }));
2468
2469 let when = Expression::When(Box::new(When {
2470 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2471 value: true,
2472 }))),
2473 source: None,
2474 condition: None,
2475 then: Box::new(action),
2476 }));
2477 self.whens.push(when);
2478 self
2479 }
2480
2481 pub fn when_matched_update_where(
2483 mut self,
2484 condition: Expr,
2485 assignments: Vec<(&str, Expr)>,
2486 ) -> Self {
2487 let eqs: Vec<Expression> = assignments
2488 .into_iter()
2489 .map(|(col_name, val)| {
2490 Expression::Eq(Box::new(BinaryOp {
2491 left: Expression::Column(Column {
2492 name: builder_identifier(col_name),
2493 table: None,
2494 join_mark: false,
2495 trailing_comments: Vec::new(),
2496 span: None,
2497 inferred_type: None,
2498 }),
2499 right: val.0,
2500 left_comments: Vec::new(),
2501 operator_comments: Vec::new(),
2502 trailing_comments: Vec::new(),
2503 inferred_type: None,
2504 }))
2505 })
2506 .collect();
2507
2508 let action = Expression::Tuple(Box::new(Tuple {
2509 expressions: vec![
2510 Expression::Var(Box::new(Var {
2511 this: "UPDATE".to_string(),
2512 })),
2513 Expression::Tuple(Box::new(Tuple { expressions: eqs })),
2514 ],
2515 }));
2516
2517 let when = Expression::When(Box::new(When {
2518 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2519 value: true,
2520 }))),
2521 source: None,
2522 condition: Some(Box::new(condition.0)),
2523 then: Box::new(action),
2524 }));
2525 self.whens.push(when);
2526 self
2527 }
2528
2529 pub fn when_matched_delete(mut self) -> Self {
2531 let action = Expression::Var(Box::new(Var {
2532 this: "DELETE".to_string(),
2533 }));
2534
2535 let when = Expression::When(Box::new(When {
2536 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2537 value: true,
2538 }))),
2539 source: None,
2540 condition: None,
2541 then: Box::new(action),
2542 }));
2543 self.whens.push(when);
2544 self
2545 }
2546
2547 pub fn when_not_matched_insert(mut self, columns: &[&str], values: Vec<Expr>) -> Self {
2549 let col_exprs: Vec<Expression> = columns
2550 .iter()
2551 .map(|c| {
2552 Expression::Column(Column {
2553 name: builder_identifier(c),
2554 table: None,
2555 join_mark: false,
2556 trailing_comments: Vec::new(),
2557 span: None,
2558 inferred_type: None,
2559 })
2560 })
2561 .collect();
2562 let val_exprs: Vec<Expression> = values.into_iter().map(|v| v.0).collect();
2563
2564 let action = Expression::Tuple(Box::new(Tuple {
2565 expressions: vec![
2566 Expression::Var(Box::new(Var {
2567 this: "INSERT".to_string(),
2568 })),
2569 Expression::Tuple(Box::new(Tuple {
2570 expressions: col_exprs,
2571 })),
2572 Expression::Tuple(Box::new(Tuple {
2573 expressions: val_exprs,
2574 })),
2575 ],
2576 }));
2577
2578 let when = Expression::When(Box::new(When {
2579 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2580 value: false,
2581 }))),
2582 source: None,
2583 condition: None,
2584 then: Box::new(action),
2585 }));
2586 self.whens.push(when);
2587 self
2588 }
2589
2590 pub fn build(self) -> Expression {
2592 let whens_expr = Expression::Whens(Box::new(Whens {
2593 expressions: self.whens,
2594 }));
2595
2596 Expression::Merge(Box::new(Merge {
2597 this: Box::new(self.target),
2598 using: Box::new(
2599 self.using
2600 .unwrap_or(Expression::Null(crate::expressions::Null)),
2601 ),
2602 on: self.on.map(Box::new),
2603 using_cond: None,
2604 whens: Some(Box::new(whens_expr)),
2605 with_: None,
2606 returning: None,
2607 }))
2608 }
2609
2610 pub fn to_sql(self) -> String {
2612 Generator::sql(&self.build()).unwrap_or_default()
2613 }
2614}
2615
2616fn parse_simple_data_type(name: &str) -> DataType {
2617 let upper = name.trim().to_uppercase();
2618 match upper.as_str() {
2619 "INT" | "INTEGER" => DataType::Int {
2620 length: None,
2621 integer_spelling: upper == "INTEGER",
2622 },
2623 "BIGINT" => DataType::BigInt { length: None },
2624 "SMALLINT" => DataType::SmallInt { length: None },
2625 "TINYINT" => DataType::TinyInt { length: None },
2626 "FLOAT" => DataType::Float {
2627 precision: None,
2628 scale: None,
2629 real_spelling: false,
2630 },
2631 "DOUBLE" => DataType::Double {
2632 precision: None,
2633 scale: None,
2634 },
2635 "BOOLEAN" | "BOOL" => DataType::Boolean,
2636 "TEXT" => DataType::Text,
2637 "DATE" => DataType::Date,
2638 "TIMESTAMP" => DataType::Timestamp {
2639 precision: None,
2640 timezone: false,
2641 },
2642 "VARCHAR" => DataType::VarChar {
2643 length: None,
2644 parenthesized_length: false,
2645 },
2646 "CHAR" => DataType::Char { length: None },
2647 _ => {
2648 if let Ok(ast) =
2650 crate::parser::Parser::parse_sql(&format!("SELECT CAST(x AS {})", name))
2651 {
2652 if let Expression::Select(s) = &ast[0] {
2653 if let Some(Expression::Cast(c)) = s.expressions.first() {
2654 return c.to.clone();
2655 }
2656 }
2657 }
2658 DataType::Custom {
2660 name: name.to_string(),
2661 }
2662 }
2663 }
2664}
2665
2666#[cfg(test)]
2667mod tests {
2668 use super::*;
2669
2670 #[test]
2671 fn test_simple_select() {
2672 let sql = select(["id", "name"]).from("users").to_sql();
2673 assert_eq!(sql, "SELECT id, name FROM users");
2674 }
2675
2676 #[test]
2677 fn test_builder_quotes_unsafe_identifier_tokens() {
2678 let sql = select(["Name; DROP TABLE titanic"]).to_sql();
2679 assert_eq!(sql, r#"SELECT "Name; DROP TABLE titanic""#);
2680 }
2681
2682 #[test]
2683 fn test_builder_string_literal_requires_lit() {
2684 let sql = select([lit("Name; DROP TABLE titanic")]).to_sql();
2685 assert_eq!(sql, "SELECT 'Name; DROP TABLE titanic'");
2686 }
2687
2688 #[test]
2689 fn test_builder_quotes_unsafe_table_name_tokens() {
2690 let sql = select(["id"]).from("users; DROP TABLE x").to_sql();
2691 assert_eq!(sql, r#"SELECT id FROM "users; DROP TABLE x""#);
2692 }
2693
2694 #[test]
2695 fn test_select_star() {
2696 let sql = select([star()]).from("users").to_sql();
2697 assert_eq!(sql, "SELECT * FROM users");
2698 }
2699
2700 #[test]
2701 fn test_select_with_where() {
2702 let sql = select(["id", "name"])
2703 .from("users")
2704 .where_(col("age").gt(lit(18)))
2705 .to_sql();
2706 assert_eq!(sql, "SELECT id, name FROM users WHERE age > 18");
2707 }
2708
2709 #[test]
2710 fn test_select_with_join() {
2711 let sql = select(["u.id", "o.amount"])
2712 .from("users")
2713 .join("orders", col("u.id").eq(col("o.user_id")))
2714 .to_sql();
2715 assert_eq!(
2716 sql,
2717 "SELECT u.id, o.amount FROM users JOIN orders ON u.id = o.user_id"
2718 );
2719 }
2720
2721 #[test]
2722 fn test_select_with_group_by_having() {
2723 let sql = select([col("dept"), func("COUNT", [star()]).alias("cnt")])
2724 .from("employees")
2725 .group_by(["dept"])
2726 .having(func("COUNT", [star()]).gt(lit(5)))
2727 .to_sql();
2728 assert_eq!(
2729 sql,
2730 "SELECT dept, COUNT(*) AS cnt FROM employees GROUP BY dept HAVING COUNT(*) > 5"
2731 );
2732 }
2733
2734 #[test]
2735 fn test_select_with_order_limit_offset() {
2736 let sql = select(["id", "name"])
2737 .from("users")
2738 .order_by(["name"])
2739 .limit(10)
2740 .offset(20)
2741 .to_sql();
2742 assert_eq!(
2743 sql,
2744 "SELECT id, name FROM users ORDER BY name LIMIT 10 OFFSET 20"
2745 );
2746 }
2747
2748 #[test]
2749 fn test_select_distinct() {
2750 let sql = select(["name"]).from("users").distinct().to_sql();
2751 assert_eq!(sql, "SELECT DISTINCT name FROM users");
2752 }
2753
2754 #[test]
2755 fn test_insert_values() {
2756 let sql = insert_into("users")
2757 .columns(["id", "name"])
2758 .values([lit(1), lit("Alice")])
2759 .values([lit(2), lit("Bob")])
2760 .to_sql();
2761 assert_eq!(
2762 sql,
2763 "INSERT INTO users (id, name) VALUES (1, 'Alice'), (2, 'Bob')"
2764 );
2765 }
2766
2767 #[test]
2768 fn test_insert_select() {
2769 let sql = insert_into("archive")
2770 .columns(["id", "name"])
2771 .query(select(["id", "name"]).from("users"))
2772 .to_sql();
2773 assert_eq!(
2774 sql,
2775 "INSERT INTO archive (id, name) SELECT id, name FROM users"
2776 );
2777 }
2778
2779 #[test]
2780 fn test_update() {
2781 let sql = update("users")
2782 .set("name", lit("Bob"))
2783 .set("age", lit(30))
2784 .where_(col("id").eq(lit(1)))
2785 .to_sql();
2786 assert_eq!(sql, "UPDATE users SET name = 'Bob', age = 30 WHERE id = 1");
2787 }
2788
2789 #[test]
2790 fn test_delete() {
2791 let sql = delete("users").where_(col("id").eq(lit(1))).to_sql();
2792 assert_eq!(sql, "DELETE FROM users WHERE id = 1");
2793 }
2794
2795 #[test]
2796 fn test_complex_where() {
2797 let sql = select(["id"])
2798 .from("users")
2799 .where_(
2800 col("age")
2801 .gte(lit(18))
2802 .and(col("active").eq(boolean(true)))
2803 .and(col("name").like(lit("%test%"))),
2804 )
2805 .to_sql();
2806 assert_eq!(
2807 sql,
2808 "SELECT id FROM users WHERE age >= 18 AND active = TRUE AND name LIKE '%test%'"
2809 );
2810 }
2811
2812 #[test]
2813 fn test_in_list() {
2814 let sql = select(["id"])
2815 .from("users")
2816 .where_(col("status").in_list([lit("active"), lit("pending")]))
2817 .to_sql();
2818 assert_eq!(
2819 sql,
2820 "SELECT id FROM users WHERE status IN ('active', 'pending')"
2821 );
2822 }
2823
2824 #[test]
2825 fn test_between() {
2826 let sql = select(["id"])
2827 .from("orders")
2828 .where_(col("amount").between(lit(100), lit(500)))
2829 .to_sql();
2830 assert_eq!(
2831 sql,
2832 "SELECT id FROM orders WHERE amount BETWEEN 100 AND 500"
2833 );
2834 }
2835
2836 #[test]
2837 fn test_is_null() {
2838 let sql = select(["id"])
2839 .from("users")
2840 .where_(col("email").is_null())
2841 .to_sql();
2842 assert_eq!(sql, "SELECT id FROM users WHERE email IS NULL");
2843 }
2844
2845 #[test]
2846 fn test_arithmetic() {
2847 let sql = select([col("price").mul(col("quantity")).alias("total")])
2848 .from("items")
2849 .to_sql();
2850 assert_eq!(sql, "SELECT price * quantity AS total FROM items");
2851 }
2852
2853 #[test]
2854 fn test_cast() {
2855 let sql = select([col("id").cast("VARCHAR")]).from("users").to_sql();
2856 assert_eq!(sql, "SELECT CAST(id AS VARCHAR) FROM users");
2857 }
2858
2859 #[test]
2860 fn test_from_starter() {
2861 let sql = from("users").select_cols(["id", "name"]).to_sql();
2862 assert_eq!(sql, "SELECT id, name FROM users");
2863 }
2864
2865 #[test]
2866 fn test_qualified_column() {
2867 let sql = select([col("u.id"), col("u.name")]).from("users").to_sql();
2868 assert_eq!(sql, "SELECT u.id, u.name FROM users");
2869 }
2870
2871 #[test]
2872 fn test_not_condition() {
2873 let sql = select(["id"])
2874 .from("users")
2875 .where_(not(col("active").eq(boolean(true))))
2876 .to_sql();
2877 assert_eq!(sql, "SELECT id FROM users WHERE NOT active = TRUE");
2878 }
2879
2880 #[test]
2881 fn test_order_by_desc() {
2882 let sql = select(["id", "name"])
2883 .from("users")
2884 .order_by([col("name").desc()])
2885 .to_sql();
2886 assert_eq!(sql, "SELECT id, name FROM users ORDER BY name DESC");
2887 }
2888
2889 #[test]
2890 fn test_left_join() {
2891 let sql = select(["u.id", "o.amount"])
2892 .from("users")
2893 .left_join("orders", col("u.id").eq(col("o.user_id")))
2894 .to_sql();
2895 assert_eq!(
2896 sql,
2897 "SELECT u.id, o.amount FROM users LEFT JOIN orders ON u.id = o.user_id"
2898 );
2899 }
2900
2901 #[test]
2902 fn test_build_returns_expression() {
2903 let expr = select(["id"]).from("users").build();
2904 assert!(matches!(expr, Expression::Select(_)));
2905 }
2906
2907 #[test]
2908 fn test_expr_interop() {
2909 let age_check = col("age").gt(lit(18));
2911 let sql = select([col("id"), age_check.alias("is_adult")])
2912 .from("users")
2913 .to_sql();
2914 assert_eq!(sql, "SELECT id, age > 18 AS is_adult FROM users");
2915 }
2916
2917 #[test]
2920 fn test_sql_expr_simple() {
2921 let expr = sql_expr("age > 18");
2922 let sql = select(["id"]).from("users").where_(expr).to_sql();
2923 assert_eq!(sql, "SELECT id FROM users WHERE age > 18");
2924 }
2925
2926 #[test]
2927 fn test_sql_expr_compound() {
2928 let expr = sql_expr("a > 1 AND b < 10");
2929 let sql = select(["*"]).from("t").where_(expr).to_sql();
2930 assert_eq!(sql, "SELECT * FROM t WHERE a > 1 AND b < 10");
2931 }
2932
2933 #[test]
2934 fn test_sql_expr_function() {
2935 let expr = sql_expr("COALESCE(a, b, 0)");
2936 let sql = select([expr.alias("val")]).from("t").to_sql();
2937 assert_eq!(sql, "SELECT COALESCE(a, b, 0) AS val FROM t");
2938 }
2939
2940 #[test]
2941 fn test_condition_alias() {
2942 let cond = condition("x > 0");
2943 let sql = select(["*"]).from("t").where_(cond).to_sql();
2944 assert_eq!(sql, "SELECT * FROM t WHERE x > 0");
2945 }
2946
2947 #[test]
2950 fn test_ilike() {
2951 let sql = select(["id"])
2952 .from("users")
2953 .where_(col("name").ilike(lit("%test%")))
2954 .to_sql();
2955 assert_eq!(sql, "SELECT id FROM users WHERE name ILIKE '%test%'");
2956 }
2957
2958 #[test]
2959 fn test_rlike() {
2960 let sql = select(["id"])
2961 .from("users")
2962 .where_(col("name").rlike(lit("^[A-Z]")))
2963 .to_sql();
2964 assert_eq!(
2965 sql,
2966 "SELECT id FROM users WHERE REGEXP_LIKE(name, '^[A-Z]')"
2967 );
2968 }
2969
2970 #[test]
2971 fn test_not_in() {
2972 let sql = select(["id"])
2973 .from("users")
2974 .where_(col("status").not_in([lit("deleted"), lit("banned")]))
2975 .to_sql();
2976 assert_eq!(
2977 sql,
2978 "SELECT id FROM users WHERE NOT status IN ('deleted', 'banned')"
2979 );
2980 }
2981
2982 #[test]
2985 fn test_case_searched() {
2986 let expr = case()
2987 .when(col("x").gt(lit(0)), lit("positive"))
2988 .when(col("x").eq(lit(0)), lit("zero"))
2989 .else_(lit("negative"))
2990 .build();
2991 let sql = select([expr.alias("label")]).from("t").to_sql();
2992 assert_eq!(
2993 sql,
2994 "SELECT CASE WHEN x > 0 THEN 'positive' WHEN x = 0 THEN 'zero' ELSE 'negative' END AS label FROM t"
2995 );
2996 }
2997
2998 #[test]
2999 fn test_case_simple() {
3000 let expr = case_of(col("status"))
3001 .when(lit(1), lit("active"))
3002 .when(lit(0), lit("inactive"))
3003 .build();
3004 let sql = select([expr.alias("status_label")]).from("t").to_sql();
3005 assert_eq!(
3006 sql,
3007 "SELECT CASE status WHEN 1 THEN 'active' WHEN 0 THEN 'inactive' END AS status_label FROM t"
3008 );
3009 }
3010
3011 #[test]
3012 fn test_case_no_else() {
3013 let expr = case().when(col("x").gt(lit(0)), lit("yes")).build();
3014 let sql = select([expr]).from("t").to_sql();
3015 assert_eq!(sql, "SELECT CASE WHEN x > 0 THEN 'yes' END FROM t");
3016 }
3017
3018 #[test]
3021 fn test_subquery_in_from() {
3022 let inner = select(["id", "name"])
3023 .from("users")
3024 .where_(col("active").eq(boolean(true)));
3025 let outer = select(["sub.id"])
3026 .from_expr(subquery(inner, "sub"))
3027 .to_sql();
3028 assert_eq!(
3029 outer,
3030 "SELECT sub.id FROM (SELECT id, name FROM users WHERE active = TRUE) AS sub"
3031 );
3032 }
3033
3034 #[test]
3035 fn test_subquery_in_join() {
3036 let inner = select([col("user_id"), func("SUM", [col("amount")]).alias("total")])
3037 .from("orders")
3038 .group_by(["user_id"]);
3039 let sql = select(["u.name", "o.total"])
3040 .from("users")
3041 .join("orders", col("u.id").eq(col("o.user_id")))
3042 .to_sql();
3043 assert!(sql.contains("JOIN"));
3044 let _sub = subquery(inner, "o");
3046 }
3047
3048 #[test]
3051 fn test_union() {
3052 let sql = union(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3053 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
3054 }
3055
3056 #[test]
3057 fn test_union_all() {
3058 let sql = union_all(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3059 assert_eq!(sql, "SELECT id FROM a UNION ALL SELECT id FROM b");
3060 }
3061
3062 #[test]
3063 fn test_intersect_builder() {
3064 let sql = intersect(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3065 assert_eq!(sql, "SELECT id FROM a INTERSECT SELECT id FROM b");
3066 }
3067
3068 #[test]
3069 fn test_except_builder() {
3070 let sql = except_(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3071 assert_eq!(sql, "SELECT id FROM a EXCEPT SELECT id FROM b");
3072 }
3073
3074 #[test]
3075 fn test_union_with_order_limit() {
3076 let sql = union(select(["id"]).from("a"), select(["id"]).from("b"))
3077 .order_by(["id"])
3078 .limit(10)
3079 .to_sql();
3080 assert!(sql.contains("UNION"));
3081 assert!(sql.contains("ORDER BY"));
3082 assert!(sql.contains("LIMIT"));
3083 }
3084
3085 #[test]
3086 fn test_select_builder_union() {
3087 let sql = select(["id"])
3088 .from("a")
3089 .union(select(["id"]).from("b"))
3090 .to_sql();
3091 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
3092 }
3093
3094 #[test]
3097 fn test_qualify() {
3098 let sql = select(["id", "name"])
3099 .from("users")
3100 .qualify(col("rn").eq(lit(1)))
3101 .to_sql();
3102 assert_eq!(sql, "SELECT id, name FROM users QUALIFY rn = 1");
3103 }
3104
3105 #[test]
3106 fn test_right_join() {
3107 let sql = select(["u.id", "o.amount"])
3108 .from("users")
3109 .right_join("orders", col("u.id").eq(col("o.user_id")))
3110 .to_sql();
3111 assert_eq!(
3112 sql,
3113 "SELECT u.id, o.amount FROM users RIGHT JOIN orders ON u.id = o.user_id"
3114 );
3115 }
3116
3117 #[test]
3118 fn test_cross_join() {
3119 let sql = select(["a.x", "b.y"]).from("a").cross_join("b").to_sql();
3120 assert_eq!(sql, "SELECT a.x, b.y FROM a CROSS JOIN b");
3121 }
3122
3123 #[test]
3124 fn test_lateral_view() {
3125 let sql = select(["id", "col_val"])
3126 .from("t")
3127 .lateral_view(func("EXPLODE", [col("arr")]), "lv", ["col_val"])
3128 .to_sql();
3129 assert!(sql.contains("LATERAL VIEW"));
3130 assert!(sql.contains("EXPLODE"));
3131 }
3132
3133 #[test]
3134 fn test_window_clause() {
3135 let sql = select(["id"])
3136 .from("t")
3137 .window(
3138 "w",
3139 WindowDefBuilder::new()
3140 .partition_by(["dept"])
3141 .order_by(["salary"]),
3142 )
3143 .to_sql();
3144 assert!(sql.contains("WINDOW"));
3145 assert!(sql.contains("PARTITION BY"));
3146 }
3147
3148 #[test]
3151 fn test_xor() {
3152 let sql = select(["*"])
3153 .from("t")
3154 .where_(col("a").xor(col("b")))
3155 .to_sql();
3156 assert_eq!(sql, "SELECT * FROM t WHERE a XOR b");
3157 }
3158
3159 #[test]
3162 fn test_for_update() {
3163 let sql = select(["id"]).from("t").for_update().to_sql();
3164 assert_eq!(sql, "SELECT id FROM t FOR UPDATE");
3165 }
3166
3167 #[test]
3168 fn test_for_share() {
3169 let sql = select(["id"]).from("t").for_share().to_sql();
3170 assert_eq!(sql, "SELECT id FROM t FOR SHARE");
3171 }
3172
3173 #[test]
3176 fn test_hint() {
3177 let sql = select(["*"]).from("t").hint("FULL(t)").to_sql();
3178 assert!(sql.contains("FULL(t)"), "Expected hint in: {}", sql);
3179 }
3180
3181 #[test]
3184 fn test_ctas() {
3185 let expr = select(["*"]).from("t").ctas("new_table");
3186 let sql = Generator::sql(&expr).unwrap();
3187 assert_eq!(sql, "CREATE TABLE new_table AS SELECT * FROM t");
3188 }
3189
3190 #[test]
3193 fn test_merge_update_insert() {
3194 let sql = merge_into("target")
3195 .using("source", col("target.id").eq(col("source.id")))
3196 .when_matched_update(vec![("name", col("source.name"))])
3197 .when_not_matched_insert(&["id", "name"], vec![col("source.id"), col("source.name")])
3198 .to_sql();
3199 assert!(
3200 sql.contains("MERGE INTO"),
3201 "Expected MERGE INTO in: {}",
3202 sql
3203 );
3204 assert!(sql.contains("USING"), "Expected USING in: {}", sql);
3205 assert!(
3206 sql.contains("WHEN MATCHED"),
3207 "Expected WHEN MATCHED in: {}",
3208 sql
3209 );
3210 assert!(
3211 sql.contains("UPDATE SET"),
3212 "Expected UPDATE SET in: {}",
3213 sql
3214 );
3215 assert!(
3216 sql.contains("WHEN NOT MATCHED"),
3217 "Expected WHEN NOT MATCHED in: {}",
3218 sql
3219 );
3220 assert!(sql.contains("INSERT"), "Expected INSERT in: {}", sql);
3221 }
3222
3223 #[test]
3224 fn test_merge_delete() {
3225 let sql = merge_into("target")
3226 .using("source", col("target.id").eq(col("source.id")))
3227 .when_matched_delete()
3228 .to_sql();
3229 assert!(
3230 sql.contains("MERGE INTO"),
3231 "Expected MERGE INTO in: {}",
3232 sql
3233 );
3234 assert!(
3235 sql.contains("WHEN MATCHED THEN DELETE"),
3236 "Expected WHEN MATCHED THEN DELETE in: {}",
3237 sql
3238 );
3239 }
3240
3241 #[test]
3242 fn test_merge_with_condition() {
3243 let sql = merge_into("target")
3244 .using("source", col("target.id").eq(col("source.id")))
3245 .when_matched_update_where(
3246 col("source.active").eq(boolean(true)),
3247 vec![("name", col("source.name"))],
3248 )
3249 .to_sql();
3250 assert!(
3251 sql.contains("MERGE INTO"),
3252 "Expected MERGE INTO in: {}",
3253 sql
3254 );
3255 assert!(
3256 sql.contains("AND source.active = TRUE"),
3257 "Expected condition in: {}",
3258 sql
3259 );
3260 }
3261}