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 let parts: Vec<&str> = name.split('.').collect();
138 if parts.len() >= 3 && parts.iter().all(|part| !part.is_empty()) {
139 let mut expr = Expression::boxed_column(Column {
140 name: builder_identifier(parts[1]),
141 table: Some(builder_identifier(parts[0])),
142 join_mark: false,
143 trailing_comments: Vec::new(),
144 span: None,
145 inferred_type: None,
146 });
147
148 for field in &parts[2..] {
149 expr = Expression::Dot(Box::new(DotAccess {
150 this: expr,
151 field: builder_identifier(field),
152 }));
153 }
154
155 return Expr(expr);
156 }
157
158 if let Some((table, column)) = name.rsplit_once('.') {
159 Expr(Expression::boxed_column(Column {
160 name: builder_identifier(column),
161 table: Some(builder_identifier(table)),
162 join_mark: false,
163 trailing_comments: Vec::new(),
164 span: None,
165 inferred_type: None,
166 }))
167 } else {
168 Expr(Expression::boxed_column(Column {
169 name: builder_identifier(name),
170 table: None,
171 join_mark: false,
172 trailing_comments: Vec::new(),
173 span: None,
174 inferred_type: None,
175 }))
176 }
177}
178
179pub fn lit<V: IntoLiteral>(value: V) -> Expr {
195 value.into_literal()
196}
197
198pub fn star() -> Expr {
200 Expr(Expression::star())
201}
202
203pub fn null() -> Expr {
205 Expr(Expression::Null(Null))
206}
207
208pub fn boolean(value: bool) -> Expr {
210 Expr(Expression::Boolean(BooleanLiteral { value }))
211}
212
213pub fn table(name: &str) -> Expr {
230 Expr(Expression::Table(Box::new(builder_table_ref(name))))
231}
232
233pub fn func(name: &str, args: impl IntoIterator<Item = Expr>) -> Expr {
250 Expr(Expression::Function(Box::new(Function {
251 name: name.to_string(),
252 args: args.into_iter().map(|a| a.0).collect(),
253 ..Function::default()
254 })))
255}
256
257pub fn cast(expr: Expr, to: &str) -> Expr {
273 let data_type = parse_simple_data_type(to);
274 Expr(Expression::Cast(Box::new(Cast {
275 this: expr.0,
276 to: data_type,
277 trailing_comments: Vec::new(),
278 double_colon_syntax: false,
279 format: None,
280 default: None,
281 inferred_type: None,
282 })))
283}
284
285pub fn not(expr: Expr) -> Expr {
290 Expr(Expression::Not(Box::new(UnaryOp::new(expr.0))))
291}
292
293pub fn and(left: Expr, right: Expr) -> Expr {
298 left.and(right)
299}
300
301pub fn or(left: Expr, right: Expr) -> Expr {
306 left.or(right)
307}
308
309pub fn alias(expr: Expr, name: &str) -> Expr {
314 Expr(Expression::Alias(Box::new(Alias {
315 this: expr.0,
316 alias: builder_identifier(name),
317 column_aliases: Vec::new(),
318 alias_explicit_as: false,
319 alias_keyword: None,
320 pre_alias_comments: Vec::new(),
321 trailing_comments: Vec::new(),
322 inferred_type: None,
323 })))
324}
325
326pub fn sql_expr(sql: &str) -> Expr {
350 let wrapped = format!("SELECT {}", sql);
351 let ast = Parser::parse_sql(&wrapped).expect("sql_expr: failed to parse SQL expression");
352 if let Expression::Select(s) = &ast[0] {
353 if let Some(first) = s.expressions.first() {
354 return Expr(first.clone());
355 }
356 }
357 panic!("sql_expr: failed to extract expression from parsed SQL");
358}
359
360pub fn condition(sql: &str) -> Expr {
369 sql_expr(sql)
370}
371
372pub fn count(expr: Expr) -> Expr {
380 Expr(Expression::Count(Box::new(CountFunc {
381 this: Some(expr.0),
382 star: false,
383 distinct: false,
384 filter: None,
385 ignore_nulls: None,
386 original_name: None,
387 inferred_type: None,
388 })))
389}
390
391pub fn count_star() -> Expr {
393 Expr(Expression::Count(Box::new(CountFunc {
394 this: None,
395 star: true,
396 distinct: false,
397 filter: None,
398 ignore_nulls: None,
399 original_name: None,
400 inferred_type: None,
401 })))
402}
403
404pub fn count_distinct(expr: Expr) -> Expr {
406 Expr(Expression::Count(Box::new(CountFunc {
407 this: Some(expr.0),
408 star: false,
409 distinct: true,
410 filter: None,
411 ignore_nulls: None,
412 original_name: None,
413 inferred_type: None,
414 })))
415}
416
417pub fn sum(expr: Expr) -> Expr {
419 Expr(Expression::Sum(Box::new(AggFunc {
420 this: expr.0,
421 distinct: false,
422 filter: None,
423 order_by: vec![],
424 name: None,
425 ignore_nulls: None,
426 having_max: None,
427 limit: None,
428 inferred_type: None,
429 })))
430}
431
432pub fn avg(expr: Expr) -> Expr {
434 Expr(Expression::Avg(Box::new(AggFunc {
435 this: expr.0,
436 distinct: false,
437 filter: None,
438 order_by: vec![],
439 name: None,
440 ignore_nulls: None,
441 having_max: None,
442 limit: None,
443 inferred_type: None,
444 })))
445}
446
447pub fn min_(expr: Expr) -> Expr {
449 Expr(Expression::Min(Box::new(AggFunc {
450 this: expr.0,
451 distinct: false,
452 filter: None,
453 order_by: vec![],
454 name: None,
455 ignore_nulls: None,
456 having_max: None,
457 limit: None,
458 inferred_type: None,
459 })))
460}
461
462pub fn max_(expr: Expr) -> Expr {
464 Expr(Expression::Max(Box::new(AggFunc {
465 this: expr.0,
466 distinct: false,
467 filter: None,
468 order_by: vec![],
469 name: None,
470 ignore_nulls: None,
471 having_max: None,
472 limit: None,
473 inferred_type: None,
474 })))
475}
476
477pub fn approx_distinct(expr: Expr) -> Expr {
479 Expr(Expression::ApproxDistinct(Box::new(AggFunc {
480 this: expr.0,
481 distinct: false,
482 filter: None,
483 order_by: vec![],
484 name: None,
485 ignore_nulls: None,
486 having_max: None,
487 limit: None,
488 inferred_type: None,
489 })))
490}
491
492pub fn upper(expr: Expr) -> Expr {
496 Expr(Expression::Upper(Box::new(UnaryFunc::new(expr.0))))
497}
498
499pub fn lower(expr: Expr) -> Expr {
501 Expr(Expression::Lower(Box::new(UnaryFunc::new(expr.0))))
502}
503
504pub fn length(expr: Expr) -> Expr {
506 Expr(Expression::Length(Box::new(UnaryFunc::new(expr.0))))
507}
508
509pub fn trim(expr: Expr) -> Expr {
511 Expr(Expression::Trim(Box::new(TrimFunc {
512 this: expr.0,
513 characters: None,
514 position: TrimPosition::Both,
515 sql_standard_syntax: false,
516 position_explicit: false,
517 })))
518}
519
520pub fn ltrim(expr: Expr) -> Expr {
522 Expr(Expression::LTrim(Box::new(UnaryFunc::new(expr.0))))
523}
524
525pub fn rtrim(expr: Expr) -> Expr {
527 Expr(Expression::RTrim(Box::new(UnaryFunc::new(expr.0))))
528}
529
530pub fn reverse(expr: Expr) -> Expr {
532 Expr(Expression::Reverse(Box::new(UnaryFunc::new(expr.0))))
533}
534
535pub fn initcap(expr: Expr) -> Expr {
537 Expr(Expression::Initcap(Box::new(UnaryFunc::new(expr.0))))
538}
539
540pub fn substring(expr: Expr, start: Expr, len: Option<Expr>) -> Expr {
542 Expr(Expression::Substring(Box::new(SubstringFunc {
543 this: expr.0,
544 start: start.0,
545 length: len.map(|l| l.0),
546 from_for_syntax: false,
547 })))
548}
549
550pub fn replace_(expr: Expr, old: Expr, new: Expr) -> Expr {
553 Expr(Expression::Replace(Box::new(ReplaceFunc {
554 this: expr.0,
555 old: old.0,
556 new: new.0,
557 })))
558}
559
560pub fn concat_ws(separator: Expr, exprs: impl IntoIterator<Item = Expr>) -> Expr {
562 Expr(Expression::ConcatWs(Box::new(ConcatWs {
563 separator: separator.0,
564 expressions: exprs.into_iter().map(|e| e.0).collect(),
565 })))
566}
567
568pub fn coalesce(exprs: impl IntoIterator<Item = Expr>) -> Expr {
572 Expr(Expression::Coalesce(Box::new(VarArgFunc {
573 expressions: exprs.into_iter().map(|e| e.0).collect(),
574 original_name: None,
575 inferred_type: None,
576 })))
577}
578
579pub fn null_if(expr1: Expr, expr2: Expr) -> Expr {
581 Expr(Expression::NullIf(Box::new(BinaryFunc {
582 this: expr1.0,
583 expression: expr2.0,
584 original_name: None,
585 inferred_type: None,
586 })))
587}
588
589pub fn if_null(expr: Expr, fallback: Expr) -> Expr {
591 Expr(Expression::IfNull(Box::new(BinaryFunc {
592 this: expr.0,
593 expression: fallback.0,
594 original_name: None,
595 inferred_type: None,
596 })))
597}
598
599pub fn abs(expr: Expr) -> Expr {
603 Expr(Expression::Abs(Box::new(UnaryFunc::new(expr.0))))
604}
605
606pub fn round(expr: Expr, decimals: Option<Expr>) -> Expr {
608 Expr(Expression::Round(Box::new(RoundFunc {
609 this: expr.0,
610 decimals: decimals.map(|d| d.0),
611 })))
612}
613
614pub fn floor(expr: Expr) -> Expr {
616 Expr(Expression::Floor(Box::new(FloorFunc {
617 this: expr.0,
618 scale: None,
619 to: None,
620 })))
621}
622
623pub fn ceil(expr: Expr) -> Expr {
625 Expr(Expression::Ceil(Box::new(CeilFunc {
626 this: expr.0,
627 decimals: None,
628 to: None,
629 })))
630}
631
632pub fn power(base: Expr, exponent: Expr) -> Expr {
634 Expr(Expression::Power(Box::new(BinaryFunc {
635 this: base.0,
636 expression: exponent.0,
637 original_name: None,
638 inferred_type: None,
639 })))
640}
641
642pub fn sqrt(expr: Expr) -> Expr {
644 Expr(Expression::Sqrt(Box::new(UnaryFunc::new(expr.0))))
645}
646
647pub fn ln(expr: Expr) -> Expr {
649 Expr(Expression::Ln(Box::new(UnaryFunc::new(expr.0))))
650}
651
652pub fn exp_(expr: Expr) -> Expr {
654 Expr(Expression::Exp(Box::new(UnaryFunc::new(expr.0))))
655}
656
657pub fn sign(expr: Expr) -> Expr {
659 Expr(Expression::Sign(Box::new(UnaryFunc::new(expr.0))))
660}
661
662pub fn greatest(exprs: impl IntoIterator<Item = Expr>) -> Expr {
664 Expr(Expression::Greatest(Box::new(VarArgFunc {
665 expressions: exprs.into_iter().map(|e| e.0).collect(),
666 original_name: None,
667 inferred_type: None,
668 })))
669}
670
671pub fn least(exprs: impl IntoIterator<Item = Expr>) -> Expr {
673 Expr(Expression::Least(Box::new(VarArgFunc {
674 expressions: exprs.into_iter().map(|e| e.0).collect(),
675 original_name: None,
676 inferred_type: None,
677 })))
678}
679
680pub fn current_date_() -> Expr {
684 Expr(Expression::CurrentDate(CurrentDate))
685}
686
687pub fn current_time_() -> Expr {
689 Expr(Expression::CurrentTime(CurrentTime { precision: None }))
690}
691
692pub fn current_timestamp_() -> Expr {
694 Expr(Expression::CurrentTimestamp(CurrentTimestamp {
695 precision: None,
696 sysdate: false,
697 }))
698}
699
700pub fn extract_(field: &str, expr: Expr) -> Expr {
702 Expr(Expression::Extract(Box::new(ExtractFunc {
703 this: expr.0,
704 field: parse_datetime_field(field),
705 })))
706}
707
708fn parse_datetime_field(field: &str) -> DateTimeField {
710 match field.to_uppercase().as_str() {
711 "YEAR" => DateTimeField::Year,
712 "MONTH" => DateTimeField::Month,
713 "DAY" => DateTimeField::Day,
714 "HOUR" => DateTimeField::Hour,
715 "MINUTE" => DateTimeField::Minute,
716 "SECOND" => DateTimeField::Second,
717 "MILLISECOND" => DateTimeField::Millisecond,
718 "MICROSECOND" => DateTimeField::Microsecond,
719 "DOW" | "DAYOFWEEK" => DateTimeField::DayOfWeek,
720 "DOY" | "DAYOFYEAR" => DateTimeField::DayOfYear,
721 "WEEK" => DateTimeField::Week,
722 "QUARTER" => DateTimeField::Quarter,
723 "EPOCH" => DateTimeField::Epoch,
724 "TIMEZONE" => DateTimeField::Timezone,
725 "TIMEZONE_HOUR" => DateTimeField::TimezoneHour,
726 "TIMEZONE_MINUTE" => DateTimeField::TimezoneMinute,
727 "DATE" => DateTimeField::Date,
728 "TIME" => DateTimeField::Time,
729 other => DateTimeField::Custom(other.to_string()),
730 }
731}
732
733pub fn row_number() -> Expr {
737 Expr(Expression::RowNumber(RowNumber))
738}
739
740pub fn rank_() -> Expr {
742 Expr(Expression::Rank(Rank {
743 order_by: None,
744 args: vec![],
745 }))
746}
747
748pub fn dense_rank() -> Expr {
750 Expr(Expression::DenseRank(DenseRank { args: vec![] }))
751}
752
753pub fn select<I, E>(expressions: I) -> SelectBuilder
780where
781 I: IntoIterator<Item = E>,
782 E: IntoExpr,
783{
784 let mut builder = SelectBuilder::new();
785 for expr in expressions {
786 builder.select = builder.select.column(expr.into_expr().0);
787 }
788 builder
789}
790
791pub fn from(table_name: &str) -> SelectBuilder {
806 let mut builder = SelectBuilder::new();
807 builder.select.from = Some(From {
808 expressions: vec![Expression::Table(Box::new(builder_table_ref(table_name)))],
809 });
810 builder
811}
812
813pub fn delete(table_name: &str) -> DeleteBuilder {
826 DeleteBuilder {
827 delete: Delete {
828 table: builder_table_ref(table_name),
829 hint: None,
830 on_cluster: None,
831 alias: None,
832 alias_explicit_as: false,
833 using: Vec::new(),
834 where_clause: None,
835 output: None,
836 leading_comments: Vec::new(),
837 with: None,
838 limit: None,
839 order_by: None,
840 returning: Vec::new(),
841 tables: Vec::new(),
842 tables_from_using: false,
843 joins: Vec::new(),
844 force_index: None,
845 no_from: false,
846 },
847 }
848}
849
850pub fn insert_into(table_name: &str) -> InsertBuilder {
867 InsertBuilder {
868 insert: Insert {
869 table: builder_table_ref(table_name),
870 columns: Vec::new(),
871 values: Vec::new(),
872 query: None,
873 overwrite: false,
874 partition: Vec::new(),
875 directory: None,
876 returning: Vec::new(),
877 output: None,
878 on_conflict: None,
879 leading_comments: Vec::new(),
880 if_exists: false,
881 with: None,
882 ignore: false,
883 source_alias: None,
884 alias: None,
885 alias_explicit_as: false,
886 default_values: false,
887 by_name: false,
888 conflict_action: None,
889 is_replace: false,
890 hint: None,
891 replace_where: None,
892 source: None,
893 function_target: None,
894 partition_by: None,
895 settings: Vec::new(),
896 },
897 }
898}
899
900pub fn update(table_name: &str) -> UpdateBuilder {
918 UpdateBuilder {
919 update: Update {
920 table: builder_table_ref(table_name),
921 hint: None,
922 extra_tables: Vec::new(),
923 table_joins: Vec::new(),
924 set: Vec::new(),
925 from_clause: None,
926 from_joins: Vec::new(),
927 where_clause: None,
928 returning: Vec::new(),
929 output: None,
930 with: None,
931 leading_comments: Vec::new(),
932 limit: None,
933 order_by: None,
934 from_before_set: false,
935 },
936 }
937}
938
939#[derive(Debug, Clone)]
964pub struct Expr(pub Expression);
965
966impl Expr {
967 pub fn into_inner(self) -> Expression {
969 self.0
970 }
971
972 pub fn to_sql(&self) -> String {
976 Generator::sql(&self.0).unwrap_or_default()
977 }
978
979 pub fn eq(self, other: Expr) -> Expr {
983 Expr(Expression::Eq(Box::new(binary_op(self.0, other.0))))
984 }
985
986 pub fn neq(self, other: Expr) -> Expr {
988 Expr(Expression::Neq(Box::new(binary_op(self.0, other.0))))
989 }
990
991 pub fn lt(self, other: Expr) -> Expr {
993 Expr(Expression::Lt(Box::new(binary_op(self.0, other.0))))
994 }
995
996 pub fn lte(self, other: Expr) -> Expr {
998 Expr(Expression::Lte(Box::new(binary_op(self.0, other.0))))
999 }
1000
1001 pub fn gt(self, other: Expr) -> Expr {
1003 Expr(Expression::Gt(Box::new(binary_op(self.0, other.0))))
1004 }
1005
1006 pub fn gte(self, other: Expr) -> Expr {
1008 Expr(Expression::Gte(Box::new(binary_op(self.0, other.0))))
1009 }
1010
1011 pub fn and(self, other: Expr) -> Expr {
1015 Expr(Expression::And(Box::new(binary_op(self.0, other.0))))
1016 }
1017
1018 pub fn or(self, other: Expr) -> Expr {
1020 Expr(Expression::Or(Box::new(binary_op(self.0, other.0))))
1021 }
1022
1023 pub fn not(self) -> Expr {
1025 Expr(Expression::Not(Box::new(UnaryOp::new(self.0))))
1026 }
1027
1028 pub fn xor(self, other: Expr) -> Expr {
1030 Expr(Expression::Xor(Box::new(Xor {
1031 this: Some(Box::new(self.0)),
1032 expression: Some(Box::new(other.0)),
1033 expressions: vec![],
1034 })))
1035 }
1036
1037 pub fn add(self, other: Expr) -> Expr {
1041 Expr(Expression::Add(Box::new(binary_op(self.0, other.0))))
1042 }
1043
1044 pub fn sub(self, other: Expr) -> Expr {
1046 Expr(Expression::Sub(Box::new(binary_op(self.0, other.0))))
1047 }
1048
1049 pub fn mul(self, other: Expr) -> Expr {
1051 Expr(Expression::Mul(Box::new(binary_op(self.0, other.0))))
1052 }
1053
1054 pub fn div(self, other: Expr) -> Expr {
1056 Expr(Expression::Div(Box::new(binary_op(self.0, other.0))))
1057 }
1058
1059 pub fn is_null(self) -> Expr {
1063 Expr(Expression::Is(Box::new(BinaryOp {
1064 left: self.0,
1065 right: Expression::Null(Null),
1066 left_comments: Vec::new(),
1067 operator_comments: Vec::new(),
1068 trailing_comments: Vec::new(),
1069 inferred_type: None,
1070 })))
1071 }
1072
1073 pub fn is_not_null(self) -> Expr {
1075 Expr(Expression::Not(Box::new(UnaryOp::new(Expression::Is(
1076 Box::new(BinaryOp {
1077 left: self.0,
1078 right: Expression::Null(Null),
1079 left_comments: Vec::new(),
1080 operator_comments: Vec::new(),
1081 trailing_comments: Vec::new(),
1082 inferred_type: None,
1083 }),
1084 )))))
1085 }
1086
1087 pub fn in_list(self, values: impl IntoIterator<Item = Expr>) -> Expr {
1091 Expr(Expression::In(Box::new(In {
1092 this: self.0,
1093 expressions: values.into_iter().map(|v| v.0).collect(),
1094 query: None,
1095 not: false,
1096 global: false,
1097 unnest: None,
1098 is_field: false,
1099 })))
1100 }
1101
1102 pub fn between(self, low: Expr, high: Expr) -> Expr {
1104 Expr(Expression::Between(Box::new(Between {
1105 this: self.0,
1106 low: low.0,
1107 high: high.0,
1108 not: false,
1109 symmetric: None,
1110 })))
1111 }
1112
1113 pub fn like(self, pattern: Expr) -> Expr {
1115 Expr(Expression::Like(Box::new(LikeOp {
1116 left: self.0,
1117 right: pattern.0,
1118 escape: None,
1119 quantifier: None,
1120 inferred_type: None,
1121 })))
1122 }
1123
1124 pub fn alias(self, name: &str) -> Expr {
1126 alias(self, name)
1127 }
1128
1129 pub fn cast(self, to: &str) -> Expr {
1133 cast(self, to)
1134 }
1135
1136 pub fn asc(self) -> Expr {
1141 Expr(Expression::Ordered(Box::new(Ordered {
1142 this: self.0,
1143 desc: false,
1144 nulls_first: None,
1145 explicit_asc: true,
1146 with_fill: None,
1147 })))
1148 }
1149
1150 pub fn desc(self) -> Expr {
1154 Expr(Expression::Ordered(Box::new(Ordered {
1155 this: self.0,
1156 desc: true,
1157 nulls_first: None,
1158 explicit_asc: false,
1159 with_fill: None,
1160 })))
1161 }
1162
1163 pub fn ilike(self, pattern: Expr) -> Expr {
1168 Expr(Expression::ILike(Box::new(LikeOp {
1169 left: self.0,
1170 right: pattern.0,
1171 escape: None,
1172 quantifier: None,
1173 inferred_type: None,
1174 })))
1175 }
1176
1177 pub fn rlike(self, pattern: Expr) -> Expr {
1182 Expr(Expression::RegexpLike(Box::new(RegexpFunc {
1183 this: self.0,
1184 pattern: pattern.0,
1185 flags: None,
1186 })))
1187 }
1188
1189 pub fn not_in(self, values: impl IntoIterator<Item = Expr>) -> Expr {
1193 Expr(Expression::In(Box::new(In {
1194 this: self.0,
1195 expressions: values.into_iter().map(|v| v.0).collect(),
1196 query: None,
1197 not: true,
1198 global: false,
1199 unnest: None,
1200 is_field: false,
1201 })))
1202 }
1203}
1204
1205pub struct SelectBuilder {
1231 select: Select,
1232}
1233
1234impl SelectBuilder {
1235 fn new() -> Self {
1236 SelectBuilder {
1237 select: Select::new(),
1238 }
1239 }
1240
1241 pub fn select_cols<I, E>(mut self, expressions: I) -> Self
1246 where
1247 I: IntoIterator<Item = E>,
1248 E: IntoExpr,
1249 {
1250 for expr in expressions {
1251 self.select.expressions.push(expr.into_expr().0);
1252 }
1253 self
1254 }
1255
1256 pub fn from(mut self, table_name: &str) -> Self {
1258 self.select.from = Some(From {
1259 expressions: vec![Expression::Table(Box::new(builder_table_ref(table_name)))],
1260 });
1261 self
1262 }
1263
1264 pub fn from_expr(mut self, expr: Expr) -> Self {
1269 self.select.from = Some(From {
1270 expressions: vec![expr.0],
1271 });
1272 self
1273 }
1274
1275 pub fn join(mut self, table_name: &str, on: Expr) -> Self {
1277 self.select.joins.push(Join {
1278 kind: JoinKind::Inner,
1279 this: Expression::Table(Box::new(builder_table_ref(table_name))),
1280 on: Some(on.0),
1281 using: Vec::new(),
1282 use_inner_keyword: false,
1283 use_outer_keyword: false,
1284 deferred_condition: false,
1285 join_hint: None,
1286 match_condition: None,
1287 pivots: Vec::new(),
1288 comments: Vec::new(),
1289 nesting_group: 0,
1290 directed: false,
1291 });
1292 self
1293 }
1294
1295 pub fn left_join(mut self, table_name: &str, on: Expr) -> Self {
1297 self.select.joins.push(Join {
1298 kind: JoinKind::Left,
1299 this: Expression::Table(Box::new(builder_table_ref(table_name))),
1300 on: Some(on.0),
1301 using: Vec::new(),
1302 use_inner_keyword: false,
1303 use_outer_keyword: false,
1304 deferred_condition: false,
1305 join_hint: None,
1306 match_condition: None,
1307 pivots: Vec::new(),
1308 comments: Vec::new(),
1309 nesting_group: 0,
1310 directed: false,
1311 });
1312 self
1313 }
1314
1315 pub fn where_(mut self, condition: Expr) -> Self {
1321 self.select.where_clause = Some(Where { this: condition.0 });
1322 self
1323 }
1324
1325 pub fn group_by<I, E>(mut self, expressions: I) -> Self
1327 where
1328 I: IntoIterator<Item = E>,
1329 E: IntoExpr,
1330 {
1331 self.select.group_by = Some(GroupBy {
1332 expressions: expressions.into_iter().map(|e| e.into_expr().0).collect(),
1333 all: None,
1334 totals: false,
1335 comments: Vec::new(),
1336 });
1337 self
1338 }
1339
1340 pub fn having(mut self, condition: Expr) -> Self {
1342 self.select.having = Some(Having {
1343 this: condition.0,
1344 comments: Vec::new(),
1345 });
1346 self
1347 }
1348
1349 pub fn order_by<I, E>(mut self, expressions: I) -> Self
1355 where
1356 I: IntoIterator<Item = E>,
1357 E: IntoExpr,
1358 {
1359 self.select.order_by = Some(OrderBy {
1360 siblings: false,
1361 comments: Vec::new(),
1362 expressions: expressions
1363 .into_iter()
1364 .map(|e| {
1365 let expr = e.into_expr().0;
1366 match expr {
1367 Expression::Ordered(_) => expr,
1368 other => Expression::Ordered(Box::new(Ordered {
1369 this: other,
1370 desc: false,
1371 nulls_first: None,
1372 explicit_asc: false,
1373 with_fill: None,
1374 })),
1375 }
1376 })
1377 .collect::<Vec<_>>()
1378 .into_iter()
1379 .map(|e| {
1380 if let Expression::Ordered(o) = e {
1381 *o
1382 } else {
1383 Ordered {
1384 this: e,
1385 desc: false,
1386 nulls_first: None,
1387 explicit_asc: false,
1388 with_fill: None,
1389 }
1390 }
1391 })
1392 .collect(),
1393 });
1394 self
1395 }
1396
1397 pub fn sort_by<I, E>(mut self, expressions: I) -> Self
1404 where
1405 I: IntoIterator<Item = E>,
1406 E: IntoExpr,
1407 {
1408 self.select.sort_by = Some(SortBy {
1409 expressions: expressions
1410 .into_iter()
1411 .map(|e| {
1412 let expr = e.into_expr().0;
1413 match expr {
1414 Expression::Ordered(o) => *o,
1415 other => Ordered {
1416 this: other,
1417 desc: false,
1418 nulls_first: None,
1419 explicit_asc: false,
1420 with_fill: None,
1421 },
1422 }
1423 })
1424 .collect(),
1425 });
1426 self
1427 }
1428
1429 pub fn limit(mut self, count: usize) -> Self {
1431 self.select.limit = Some(Limit {
1432 this: Expression::Literal(Box::new(Literal::Number(count.to_string()))),
1433 percent: false,
1434 comments: Vec::new(),
1435 });
1436 self
1437 }
1438
1439 pub fn offset(mut self, count: usize) -> Self {
1441 self.select.offset = Some(Offset {
1442 this: Expression::Literal(Box::new(Literal::Number(count.to_string()))),
1443 rows: None,
1444 });
1445 self
1446 }
1447
1448 pub fn distinct(mut self) -> Self {
1450 self.select.distinct = true;
1451 self
1452 }
1453
1454 pub fn qualify(mut self, condition: Expr) -> Self {
1459 self.select.qualify = Some(Qualify { this: condition.0 });
1460 self
1461 }
1462
1463 pub fn right_join(mut self, table_name: &str, on: Expr) -> Self {
1465 self.select.joins.push(Join {
1466 kind: JoinKind::Right,
1467 this: Expression::Table(Box::new(builder_table_ref(table_name))),
1468 on: Some(on.0),
1469 using: Vec::new(),
1470 use_inner_keyword: false,
1471 use_outer_keyword: false,
1472 deferred_condition: false,
1473 join_hint: None,
1474 match_condition: None,
1475 pivots: Vec::new(),
1476 comments: Vec::new(),
1477 nesting_group: 0,
1478 directed: false,
1479 });
1480 self
1481 }
1482
1483 pub fn cross_join(mut self, table_name: &str) -> Self {
1485 self.select.joins.push(Join {
1486 kind: JoinKind::Cross,
1487 this: Expression::Table(Box::new(builder_table_ref(table_name))),
1488 on: None,
1489 using: Vec::new(),
1490 use_inner_keyword: false,
1491 use_outer_keyword: false,
1492 deferred_condition: false,
1493 join_hint: None,
1494 match_condition: None,
1495 pivots: Vec::new(),
1496 comments: Vec::new(),
1497 nesting_group: 0,
1498 directed: false,
1499 });
1500 self
1501 }
1502
1503 pub fn lateral_view<S: AsRef<str>>(
1510 mut self,
1511 table_function: Expr,
1512 table_alias: &str,
1513 column_aliases: impl IntoIterator<Item = S>,
1514 ) -> Self {
1515 self.select.lateral_views.push(LateralView {
1516 this: table_function.0,
1517 table_alias: Some(builder_identifier(table_alias)),
1518 column_aliases: column_aliases
1519 .into_iter()
1520 .map(|c| builder_identifier(c.as_ref()))
1521 .collect(),
1522 outer: false,
1523 });
1524 self
1525 }
1526
1527 pub fn window(mut self, name: &str, def: WindowDefBuilder) -> Self {
1533 let named_window = NamedWindow {
1534 name: builder_identifier(name),
1535 spec: Over {
1536 window_name: None,
1537 partition_by: def.partition_by,
1538 order_by: def.order_by,
1539 frame: None,
1540 alias: None,
1541 },
1542 };
1543 match self.select.windows {
1544 Some(ref mut windows) => windows.push(named_window),
1545 None => self.select.windows = Some(vec![named_window]),
1546 }
1547 self
1548 }
1549
1550 pub fn for_update(mut self) -> Self {
1555 self.select.locks.push(Lock {
1556 update: Some(Box::new(Expression::Boolean(BooleanLiteral {
1557 value: true,
1558 }))),
1559 expressions: vec![],
1560 wait: None,
1561 key: None,
1562 });
1563 self
1564 }
1565
1566 pub fn for_share(mut self) -> Self {
1571 self.select.locks.push(Lock {
1572 update: None,
1573 expressions: vec![],
1574 wait: None,
1575 key: None,
1576 });
1577 self
1578 }
1579
1580 pub fn hint(mut self, hint_text: &str) -> Self {
1585 let hint_expr = HintExpression::Raw(hint_text.to_string());
1586 match &mut self.select.hint {
1587 Some(h) => h.expressions.push(hint_expr),
1588 None => {
1589 self.select.hint = Some(Hint {
1590 expressions: vec![hint_expr],
1591 })
1592 }
1593 }
1594 self
1595 }
1596
1597 pub fn ctas(self, table_name: &str) -> Expression {
1613 Expression::CreateTable(Box::new(CreateTable {
1614 name: builder_table_ref(table_name),
1615 on_cluster: None,
1616 columns: vec![],
1617 constraints: vec![],
1618 if_not_exists: false,
1619 temporary: false,
1620 or_replace: false,
1621 table_modifier: None,
1622 as_select: Some(self.build()),
1623 as_select_parenthesized: false,
1624 on_commit: None,
1625 clone_source: None,
1626 clone_at_clause: None,
1627 is_copy: false,
1628 shallow_clone: false,
1629 deep_clone: false,
1630 leading_comments: vec![],
1631 with_properties: vec![],
1632 teradata_post_name_options: vec![],
1633 with_data: None,
1634 with_statistics: None,
1635 teradata_indexes: vec![],
1636 with_cte: None,
1637 properties: vec![],
1638 partition_of: None,
1639 post_table_properties: vec![],
1640 mysql_table_options: vec![],
1641 inherits: vec![],
1642 on_property: None,
1643 copy_grants: false,
1644 using_template: None,
1645 rollup: None,
1646 uuid: None,
1647 with_partition_columns: vec![],
1648 with_connection: None,
1649 }))
1650 }
1651
1652 pub fn union(self, other: SelectBuilder) -> SetOpBuilder {
1656 SetOpBuilder::new(SetOpKind::Union, self, other, false)
1657 }
1658
1659 pub fn union_all(self, other: SelectBuilder) -> SetOpBuilder {
1663 SetOpBuilder::new(SetOpKind::Union, self, other, true)
1664 }
1665
1666 pub fn intersect(self, other: SelectBuilder) -> SetOpBuilder {
1670 SetOpBuilder::new(SetOpKind::Intersect, self, other, false)
1671 }
1672
1673 pub fn except_(self, other: SelectBuilder) -> SetOpBuilder {
1677 SetOpBuilder::new(SetOpKind::Except, self, other, false)
1678 }
1679
1680 pub fn build(self) -> Expression {
1682 Expression::Select(Box::new(self.select))
1683 }
1684
1685 pub fn to_sql(self) -> String {
1690 Generator::sql(&self.build()).unwrap_or_default()
1691 }
1692}
1693
1694pub struct DeleteBuilder {
1703 delete: Delete,
1704}
1705
1706impl DeleteBuilder {
1707 pub fn where_(mut self, condition: Expr) -> Self {
1709 self.delete.where_clause = Some(Where { this: condition.0 });
1710 self
1711 }
1712
1713 pub fn build(self) -> Expression {
1715 Expression::Delete(Box::new(self.delete))
1716 }
1717
1718 pub fn to_sql(self) -> String {
1720 Generator::sql(&self.build()).unwrap_or_default()
1721 }
1722}
1723
1724pub struct InsertBuilder {
1735 insert: Insert,
1736}
1737
1738impl InsertBuilder {
1739 pub fn columns<I, S>(mut self, columns: I) -> Self
1741 where
1742 I: IntoIterator<Item = S>,
1743 S: AsRef<str>,
1744 {
1745 self.insert.columns = columns
1746 .into_iter()
1747 .map(|c| builder_identifier(c.as_ref()))
1748 .collect();
1749 self
1750 }
1751
1752 pub fn values<I>(mut self, values: I) -> Self
1756 where
1757 I: IntoIterator<Item = Expr>,
1758 {
1759 self.insert
1760 .values
1761 .push(values.into_iter().map(|v| v.0).collect());
1762 self
1763 }
1764
1765 pub fn query(mut self, query: SelectBuilder) -> Self {
1769 self.insert.query = Some(query.build());
1770 self
1771 }
1772
1773 pub fn build(self) -> Expression {
1775 Expression::Insert(Box::new(self.insert))
1776 }
1777
1778 pub fn to_sql(self) -> String {
1780 Generator::sql(&self.build()).unwrap_or_default()
1781 }
1782}
1783
1784pub struct UpdateBuilder {
1794 update: Update,
1795}
1796
1797impl UpdateBuilder {
1798 pub fn set(mut self, column: &str, value: Expr) -> Self {
1802 self.update.set.push((builder_identifier(column), value.0));
1803 self
1804 }
1805
1806 pub fn where_(mut self, condition: Expr) -> Self {
1808 self.update.where_clause = Some(Where { this: condition.0 });
1809 self
1810 }
1811
1812 pub fn from(mut self, table_name: &str) -> Self {
1816 self.update.from_clause = Some(From {
1817 expressions: vec![Expression::Table(Box::new(builder_table_ref(table_name)))],
1818 });
1819 self
1820 }
1821
1822 pub fn build(self) -> Expression {
1824 Expression::Update(Box::new(self.update))
1825 }
1826
1827 pub fn to_sql(self) -> String {
1829 Generator::sql(&self.build()).unwrap_or_default()
1830 }
1831}
1832
1833pub fn case() -> CaseBuilder {
1858 CaseBuilder {
1859 operand: None,
1860 whens: Vec::new(),
1861 else_: None,
1862 }
1863}
1864
1865pub fn case_of(operand: Expr) -> CaseBuilder {
1886 CaseBuilder {
1887 operand: Some(operand.0),
1888 whens: Vec::new(),
1889 else_: None,
1890 }
1891}
1892
1893pub struct CaseBuilder {
1901 operand: Option<Expression>,
1902 whens: Vec<(Expression, Expression)>,
1903 else_: Option<Expression>,
1904}
1905
1906impl CaseBuilder {
1907 pub fn when(mut self, condition: Expr, result: Expr) -> Self {
1912 self.whens.push((condition.0, result.0));
1913 self
1914 }
1915
1916 pub fn else_(mut self, result: Expr) -> Self {
1921 self.else_ = Some(result.0);
1922 self
1923 }
1924
1925 pub fn build(self) -> Expr {
1927 Expr(self.build_expr())
1928 }
1929
1930 pub fn build_expr(self) -> Expression {
1935 Expression::Case(Box::new(Case {
1936 operand: self.operand,
1937 whens: self.whens,
1938 else_: self.else_,
1939 comments: Vec::new(),
1940 inferred_type: None,
1941 }))
1942 }
1943}
1944
1945pub fn subquery(query: SelectBuilder, alias_name: &str) -> Expr {
1969 subquery_expr(query.build(), alias_name)
1970}
1971
1972pub fn subquery_expr(expr: Expression, alias_name: &str) -> Expr {
1977 Expr(Expression::Subquery(Box::new(Subquery {
1978 this: expr,
1979 alias: Some(builder_identifier(alias_name)),
1980 column_aliases: Vec::new(),
1981 alias_explicit_as: false,
1982 alias_keyword: None,
1983 order_by: None,
1984 limit: None,
1985 offset: None,
1986 distribute_by: None,
1987 sort_by: None,
1988 cluster_by: None,
1989 lateral: false,
1990 modifiers_inside: true,
1991 trailing_comments: Vec::new(),
1992 inferred_type: None,
1993 })))
1994}
1995
1996#[derive(Debug, Clone, Copy)]
2002enum SetOpKind {
2003 Union,
2004 Intersect,
2005 Except,
2006}
2007
2008pub struct SetOpBuilder {
2029 kind: SetOpKind,
2030 left: Expression,
2031 right: Expression,
2032 all: bool,
2033 order_by: Option<OrderBy>,
2034 limit: Option<Box<Expression>>,
2035 offset: Option<Box<Expression>>,
2036}
2037
2038impl SetOpBuilder {
2039 fn new(kind: SetOpKind, left: SelectBuilder, right: SelectBuilder, all: bool) -> Self {
2040 SetOpBuilder {
2041 kind,
2042 left: left.build(),
2043 right: right.build(),
2044 all,
2045 order_by: None,
2046 limit: None,
2047 offset: None,
2048 }
2049 }
2050
2051 pub fn order_by<I, E>(mut self, expressions: I) -> Self
2056 where
2057 I: IntoIterator<Item = E>,
2058 E: IntoExpr,
2059 {
2060 self.order_by = Some(OrderBy {
2061 siblings: false,
2062 comments: Vec::new(),
2063 expressions: expressions
2064 .into_iter()
2065 .map(|e| {
2066 let expr = e.into_expr().0;
2067 match expr {
2068 Expression::Ordered(o) => *o,
2069 other => Ordered {
2070 this: other,
2071 desc: false,
2072 nulls_first: None,
2073 explicit_asc: false,
2074 with_fill: None,
2075 },
2076 }
2077 })
2078 .collect(),
2079 });
2080 self
2081 }
2082
2083 pub fn limit(mut self, count: usize) -> Self {
2085 self.limit = Some(Box::new(Expression::Literal(Box::new(Literal::Number(
2086 count.to_string(),
2087 )))));
2088 self
2089 }
2090
2091 pub fn offset(mut self, count: usize) -> Self {
2093 self.offset = Some(Box::new(Expression::Literal(Box::new(Literal::Number(
2094 count.to_string(),
2095 )))));
2096 self
2097 }
2098
2099 pub fn build(self) -> Expression {
2104 match self.kind {
2105 SetOpKind::Union => Expression::Union(Box::new(Union {
2106 left: self.left,
2107 right: self.right,
2108 all: self.all,
2109 distinct: false,
2110 with: None,
2111 order_by: self.order_by,
2112 limit: self.limit,
2113 offset: self.offset,
2114 distribute_by: None,
2115 sort_by: None,
2116 cluster_by: None,
2117 by_name: false,
2118 side: None,
2119 kind: None,
2120 corresponding: false,
2121 strict: false,
2122 on_columns: Vec::new(),
2123 })),
2124 SetOpKind::Intersect => Expression::Intersect(Box::new(Intersect {
2125 left: self.left,
2126 right: self.right,
2127 all: self.all,
2128 distinct: false,
2129 with: None,
2130 order_by: self.order_by,
2131 limit: self.limit,
2132 offset: self.offset,
2133 distribute_by: None,
2134 sort_by: None,
2135 cluster_by: None,
2136 by_name: false,
2137 side: None,
2138 kind: None,
2139 corresponding: false,
2140 strict: false,
2141 on_columns: Vec::new(),
2142 })),
2143 SetOpKind::Except => Expression::Except(Box::new(Except {
2144 left: self.left,
2145 right: self.right,
2146 all: self.all,
2147 distinct: false,
2148 with: None,
2149 order_by: self.order_by,
2150 limit: self.limit,
2151 offset: self.offset,
2152 distribute_by: None,
2153 sort_by: None,
2154 cluster_by: None,
2155 by_name: false,
2156 side: None,
2157 kind: None,
2158 corresponding: false,
2159 strict: false,
2160 on_columns: Vec::new(),
2161 })),
2162 }
2163 }
2164
2165 pub fn to_sql(self) -> String {
2167 Generator::sql(&self.build()).unwrap_or_default()
2168 }
2169}
2170
2171pub fn union(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2175 SetOpBuilder::new(SetOpKind::Union, left, right, false)
2176}
2177
2178pub fn union_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2182 SetOpBuilder::new(SetOpKind::Union, left, right, true)
2183}
2184
2185pub fn intersect(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2189 SetOpBuilder::new(SetOpKind::Intersect, left, right, false)
2190}
2191
2192pub fn intersect_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2196 SetOpBuilder::new(SetOpKind::Intersect, left, right, true)
2197}
2198
2199pub fn except_(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2203 SetOpBuilder::new(SetOpKind::Except, left, right, false)
2204}
2205
2206pub fn except_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
2210 SetOpBuilder::new(SetOpKind::Except, left, right, true)
2211}
2212
2213pub struct WindowDefBuilder {
2238 partition_by: Vec<Expression>,
2239 order_by: Vec<Ordered>,
2240}
2241
2242impl WindowDefBuilder {
2243 pub fn new() -> Self {
2245 WindowDefBuilder {
2246 partition_by: Vec::new(),
2247 order_by: Vec::new(),
2248 }
2249 }
2250
2251 pub fn partition_by<I, E>(mut self, expressions: I) -> Self
2253 where
2254 I: IntoIterator<Item = E>,
2255 E: IntoExpr,
2256 {
2257 self.partition_by = expressions.into_iter().map(|e| e.into_expr().0).collect();
2258 self
2259 }
2260
2261 pub fn order_by<I, E>(mut self, expressions: I) -> Self
2266 where
2267 I: IntoIterator<Item = E>,
2268 E: IntoExpr,
2269 {
2270 self.order_by = expressions
2271 .into_iter()
2272 .map(|e| {
2273 let expr = e.into_expr().0;
2274 match expr {
2275 Expression::Ordered(o) => *o,
2276 other => Ordered {
2277 this: other,
2278 desc: false,
2279 nulls_first: None,
2280 explicit_asc: false,
2281 with_fill: None,
2282 },
2283 }
2284 })
2285 .collect();
2286 self
2287 }
2288}
2289
2290pub trait IntoExpr {
2309 fn into_expr(self) -> Expr;
2311}
2312
2313impl IntoExpr for Expr {
2314 fn into_expr(self) -> Expr {
2315 self
2316 }
2317}
2318
2319impl IntoExpr for &str {
2320 fn into_expr(self) -> Expr {
2322 col(self)
2323 }
2324}
2325
2326impl IntoExpr for String {
2327 fn into_expr(self) -> Expr {
2329 col(&self)
2330 }
2331}
2332
2333impl IntoExpr for Expression {
2334 fn into_expr(self) -> Expr {
2336 Expr(self)
2337 }
2338}
2339
2340pub trait IntoLiteral {
2355 fn into_literal(self) -> Expr;
2357}
2358
2359impl IntoLiteral for &str {
2360 fn into_literal(self) -> Expr {
2362 Expr(Expression::Literal(Box::new(Literal::String(
2363 self.to_string(),
2364 ))))
2365 }
2366}
2367
2368impl IntoLiteral for String {
2369 fn into_literal(self) -> Expr {
2371 Expr(Expression::Literal(Box::new(Literal::String(self))))
2372 }
2373}
2374
2375impl IntoLiteral for i64 {
2376 fn into_literal(self) -> Expr {
2378 Expr(Expression::Literal(Box::new(Literal::Number(
2379 self.to_string(),
2380 ))))
2381 }
2382}
2383
2384impl IntoLiteral for i32 {
2385 fn into_literal(self) -> Expr {
2387 Expr(Expression::Literal(Box::new(Literal::Number(
2388 self.to_string(),
2389 ))))
2390 }
2391}
2392
2393impl IntoLiteral for usize {
2394 fn into_literal(self) -> Expr {
2396 Expr(Expression::Literal(Box::new(Literal::Number(
2397 self.to_string(),
2398 ))))
2399 }
2400}
2401
2402impl IntoLiteral for f64 {
2403 fn into_literal(self) -> Expr {
2405 Expr(Expression::Literal(Box::new(Literal::Number(
2406 self.to_string(),
2407 ))))
2408 }
2409}
2410
2411impl IntoLiteral for bool {
2412 fn into_literal(self) -> Expr {
2414 Expr(Expression::Boolean(BooleanLiteral { value: self }))
2415 }
2416}
2417
2418fn binary_op(left: Expression, right: Expression) -> BinaryOp {
2423 BinaryOp {
2424 left,
2425 right,
2426 left_comments: Vec::new(),
2427 operator_comments: Vec::new(),
2428 trailing_comments: Vec::new(),
2429 inferred_type: None,
2430 }
2431}
2432
2433pub fn merge_into(target: &str) -> MergeBuilder {
2455 MergeBuilder {
2456 target: Expression::Table(Box::new(builder_table_ref(target))),
2457 using: None,
2458 on: None,
2459 whens: Vec::new(),
2460 }
2461}
2462
2463pub struct MergeBuilder {
2467 target: Expression,
2468 using: Option<Expression>,
2469 on: Option<Expression>,
2470 whens: Vec<Expression>,
2471}
2472
2473impl MergeBuilder {
2474 pub fn using(mut self, source: &str, on: Expr) -> Self {
2476 self.using = Some(Expression::Table(Box::new(builder_table_ref(source))));
2477 self.on = Some(on.0);
2478 self
2479 }
2480
2481 pub fn when_matched_update(mut self, assignments: Vec<(&str, Expr)>) -> Self {
2483 let eqs: Vec<Expression> = assignments
2484 .into_iter()
2485 .map(|(col_name, val)| {
2486 Expression::Eq(Box::new(BinaryOp {
2487 left: Expression::boxed_column(Column {
2488 name: builder_identifier(col_name),
2489 table: None,
2490 join_mark: false,
2491 trailing_comments: Vec::new(),
2492 span: None,
2493 inferred_type: None,
2494 }),
2495 right: val.0,
2496 left_comments: Vec::new(),
2497 operator_comments: Vec::new(),
2498 trailing_comments: Vec::new(),
2499 inferred_type: None,
2500 }))
2501 })
2502 .collect();
2503
2504 let action = Expression::Tuple(Box::new(Tuple {
2505 expressions: vec![
2506 Expression::Var(Box::new(Var {
2507 this: "UPDATE".to_string(),
2508 })),
2509 Expression::Tuple(Box::new(Tuple { expressions: eqs })),
2510 ],
2511 }));
2512
2513 let when = Expression::When(Box::new(When {
2514 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2515 value: true,
2516 }))),
2517 source: None,
2518 condition: None,
2519 then: Box::new(action),
2520 }));
2521 self.whens.push(when);
2522 self
2523 }
2524
2525 pub fn when_matched_update_where(
2527 mut self,
2528 condition: Expr,
2529 assignments: Vec<(&str, Expr)>,
2530 ) -> Self {
2531 let eqs: Vec<Expression> = assignments
2532 .into_iter()
2533 .map(|(col_name, val)| {
2534 Expression::Eq(Box::new(BinaryOp {
2535 left: Expression::boxed_column(Column {
2536 name: builder_identifier(col_name),
2537 table: None,
2538 join_mark: false,
2539 trailing_comments: Vec::new(),
2540 span: None,
2541 inferred_type: None,
2542 }),
2543 right: val.0,
2544 left_comments: Vec::new(),
2545 operator_comments: Vec::new(),
2546 trailing_comments: Vec::new(),
2547 inferred_type: None,
2548 }))
2549 })
2550 .collect();
2551
2552 let action = Expression::Tuple(Box::new(Tuple {
2553 expressions: vec![
2554 Expression::Var(Box::new(Var {
2555 this: "UPDATE".to_string(),
2556 })),
2557 Expression::Tuple(Box::new(Tuple { expressions: eqs })),
2558 ],
2559 }));
2560
2561 let when = Expression::When(Box::new(When {
2562 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2563 value: true,
2564 }))),
2565 source: None,
2566 condition: Some(Box::new(condition.0)),
2567 then: Box::new(action),
2568 }));
2569 self.whens.push(when);
2570 self
2571 }
2572
2573 pub fn when_matched_delete(mut self) -> Self {
2575 let action = Expression::Var(Box::new(Var {
2576 this: "DELETE".to_string(),
2577 }));
2578
2579 let when = Expression::When(Box::new(When {
2580 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2581 value: true,
2582 }))),
2583 source: None,
2584 condition: None,
2585 then: Box::new(action),
2586 }));
2587 self.whens.push(when);
2588 self
2589 }
2590
2591 pub fn when_not_matched_insert(mut self, columns: &[&str], values: Vec<Expr>) -> Self {
2593 let col_exprs: Vec<Expression> = columns
2594 .iter()
2595 .map(|c| {
2596 Expression::boxed_column(Column {
2597 name: builder_identifier(c),
2598 table: None,
2599 join_mark: false,
2600 trailing_comments: Vec::new(),
2601 span: None,
2602 inferred_type: None,
2603 })
2604 })
2605 .collect();
2606 let val_exprs: Vec<Expression> = values.into_iter().map(|v| v.0).collect();
2607
2608 let action = Expression::Tuple(Box::new(Tuple {
2609 expressions: vec![
2610 Expression::Var(Box::new(Var {
2611 this: "INSERT".to_string(),
2612 })),
2613 Expression::Tuple(Box::new(Tuple {
2614 expressions: col_exprs,
2615 })),
2616 Expression::Tuple(Box::new(Tuple {
2617 expressions: val_exprs,
2618 })),
2619 ],
2620 }));
2621
2622 let when = Expression::When(Box::new(When {
2623 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2624 value: false,
2625 }))),
2626 source: None,
2627 condition: None,
2628 then: Box::new(action),
2629 }));
2630 self.whens.push(when);
2631 self
2632 }
2633
2634 pub fn build(self) -> Expression {
2636 let whens_expr = Expression::Whens(Box::new(Whens {
2637 expressions: self.whens,
2638 }));
2639
2640 Expression::Merge(Box::new(Merge {
2641 this: Box::new(self.target),
2642 using: Box::new(
2643 self.using
2644 .unwrap_or(Expression::Null(crate::expressions::Null)),
2645 ),
2646 on: self.on.map(Box::new),
2647 using_cond: None,
2648 whens: Some(Box::new(whens_expr)),
2649 with_: None,
2650 returning: None,
2651 }))
2652 }
2653
2654 pub fn to_sql(self) -> String {
2656 Generator::sql(&self.build()).unwrap_or_default()
2657 }
2658}
2659
2660fn parse_simple_data_type(name: &str) -> DataType {
2661 let upper = name.trim().to_uppercase();
2662 match upper.as_str() {
2663 "INT" | "INTEGER" => DataType::Int {
2664 length: None,
2665 integer_spelling: upper == "INTEGER",
2666 },
2667 "BIGINT" => DataType::BigInt { length: None },
2668 "SMALLINT" => DataType::SmallInt { length: None },
2669 "TINYINT" => DataType::TinyInt { length: None },
2670 "FLOAT" => DataType::Float {
2671 precision: None,
2672 scale: None,
2673 real_spelling: false,
2674 },
2675 "DOUBLE" => DataType::Double {
2676 precision: None,
2677 scale: None,
2678 },
2679 "BOOLEAN" | "BOOL" => DataType::Boolean,
2680 "TEXT" => DataType::Text,
2681 "DATE" => DataType::Date,
2682 "TIMESTAMP" => DataType::Timestamp {
2683 precision: None,
2684 timezone: false,
2685 },
2686 "VARCHAR" => DataType::VarChar {
2687 length: None,
2688 parenthesized_length: false,
2689 },
2690 "CHAR" => DataType::Char { length: None },
2691 _ => {
2692 if let Ok(ast) =
2694 crate::parser::Parser::parse_sql(&format!("SELECT CAST(x AS {})", name))
2695 {
2696 if let Expression::Select(s) = &ast[0] {
2697 if let Some(Expression::Cast(c)) = s.expressions.first() {
2698 return c.to.clone();
2699 }
2700 }
2701 }
2702 DataType::Custom {
2704 name: name.to_string(),
2705 }
2706 }
2707 }
2708}
2709
2710#[cfg(test)]
2711mod tests {
2712 use super::*;
2713
2714 #[test]
2715 fn test_simple_select() {
2716 let sql = select(["id", "name"]).from("users").to_sql();
2717 assert_eq!(sql, "SELECT id, name FROM users");
2718 }
2719
2720 #[test]
2721 fn test_builder_quotes_unsafe_identifier_tokens() {
2722 let sql = select(["Name; DROP TABLE titanic"]).to_sql();
2723 assert_eq!(sql, r#"SELECT "Name; DROP TABLE titanic""#);
2724 }
2725
2726 #[test]
2727 fn test_builder_string_literal_requires_lit() {
2728 let sql = select([lit("Name; DROP TABLE titanic")]).to_sql();
2729 assert_eq!(sql, "SELECT 'Name; DROP TABLE titanic'");
2730 }
2731
2732 #[test]
2733 fn test_builder_quotes_unsafe_table_name_tokens() {
2734 let sql = select(["id"]).from("users; DROP TABLE x").to_sql();
2735 assert_eq!(sql, r#"SELECT id FROM "users; DROP TABLE x""#);
2736 }
2737
2738 #[test]
2739 fn test_select_star() {
2740 let sql = select([star()]).from("users").to_sql();
2741 assert_eq!(sql, "SELECT * FROM users");
2742 }
2743
2744 #[test]
2745 fn test_select_with_where() {
2746 let sql = select(["id", "name"])
2747 .from("users")
2748 .where_(col("age").gt(lit(18)))
2749 .to_sql();
2750 assert_eq!(sql, "SELECT id, name FROM users WHERE age > 18");
2751 }
2752
2753 #[test]
2754 fn test_select_with_join() {
2755 let sql = select(["u.id", "o.amount"])
2756 .from("users")
2757 .join("orders", col("u.id").eq(col("o.user_id")))
2758 .to_sql();
2759 assert_eq!(
2760 sql,
2761 "SELECT u.id, o.amount FROM users JOIN orders ON u.id = o.user_id"
2762 );
2763 }
2764
2765 #[test]
2766 fn test_select_with_group_by_having() {
2767 let sql = select([col("dept"), func("COUNT", [star()]).alias("cnt")])
2768 .from("employees")
2769 .group_by(["dept"])
2770 .having(func("COUNT", [star()]).gt(lit(5)))
2771 .to_sql();
2772 assert_eq!(
2773 sql,
2774 "SELECT dept, COUNT(*) AS cnt FROM employees GROUP BY dept HAVING COUNT(*) > 5"
2775 );
2776 }
2777
2778 #[test]
2779 fn test_select_with_order_limit_offset() {
2780 let sql = select(["id", "name"])
2781 .from("users")
2782 .order_by(["name"])
2783 .limit(10)
2784 .offset(20)
2785 .to_sql();
2786 assert_eq!(
2787 sql,
2788 "SELECT id, name FROM users ORDER BY name LIMIT 10 OFFSET 20"
2789 );
2790 }
2791
2792 #[test]
2793 fn test_select_distinct() {
2794 let sql = select(["name"]).from("users").distinct().to_sql();
2795 assert_eq!(sql, "SELECT DISTINCT name FROM users");
2796 }
2797
2798 #[test]
2799 fn test_insert_values() {
2800 let sql = insert_into("users")
2801 .columns(["id", "name"])
2802 .values([lit(1), lit("Alice")])
2803 .values([lit(2), lit("Bob")])
2804 .to_sql();
2805 assert_eq!(
2806 sql,
2807 "INSERT INTO users (id, name) VALUES (1, 'Alice'), (2, 'Bob')"
2808 );
2809 }
2810
2811 #[test]
2812 fn test_insert_select() {
2813 let sql = insert_into("archive")
2814 .columns(["id", "name"])
2815 .query(select(["id", "name"]).from("users"))
2816 .to_sql();
2817 assert_eq!(
2818 sql,
2819 "INSERT INTO archive (id, name) SELECT id, name FROM users"
2820 );
2821 }
2822
2823 #[test]
2824 fn test_update() {
2825 let sql = update("users")
2826 .set("name", lit("Bob"))
2827 .set("age", lit(30))
2828 .where_(col("id").eq(lit(1)))
2829 .to_sql();
2830 assert_eq!(sql, "UPDATE users SET name = 'Bob', age = 30 WHERE id = 1");
2831 }
2832
2833 #[test]
2834 fn test_delete() {
2835 let sql = delete("users").where_(col("id").eq(lit(1))).to_sql();
2836 assert_eq!(sql, "DELETE FROM users WHERE id = 1");
2837 }
2838
2839 #[test]
2840 fn test_complex_where() {
2841 let sql = select(["id"])
2842 .from("users")
2843 .where_(
2844 col("age")
2845 .gte(lit(18))
2846 .and(col("active").eq(boolean(true)))
2847 .and(col("name").like(lit("%test%"))),
2848 )
2849 .to_sql();
2850 assert_eq!(
2851 sql,
2852 "SELECT id FROM users WHERE age >= 18 AND active = TRUE AND name LIKE '%test%'"
2853 );
2854 }
2855
2856 #[test]
2857 fn test_in_list() {
2858 let sql = select(["id"])
2859 .from("users")
2860 .where_(col("status").in_list([lit("active"), lit("pending")]))
2861 .to_sql();
2862 assert_eq!(
2863 sql,
2864 "SELECT id FROM users WHERE status IN ('active', 'pending')"
2865 );
2866 }
2867
2868 #[test]
2869 fn test_between() {
2870 let sql = select(["id"])
2871 .from("orders")
2872 .where_(col("amount").between(lit(100), lit(500)))
2873 .to_sql();
2874 assert_eq!(
2875 sql,
2876 "SELECT id FROM orders WHERE amount BETWEEN 100 AND 500"
2877 );
2878 }
2879
2880 #[test]
2881 fn test_is_null() {
2882 let sql = select(["id"])
2883 .from("users")
2884 .where_(col("email").is_null())
2885 .to_sql();
2886 assert_eq!(sql, "SELECT id FROM users WHERE email IS NULL");
2887 }
2888
2889 #[test]
2890 fn test_arithmetic() {
2891 let sql = select([col("price").mul(col("quantity")).alias("total")])
2892 .from("items")
2893 .to_sql();
2894 assert_eq!(sql, "SELECT price * quantity AS total FROM items");
2895 }
2896
2897 #[test]
2898 fn test_cast() {
2899 let sql = select([col("id").cast("VARCHAR")]).from("users").to_sql();
2900 assert_eq!(sql, "SELECT CAST(id AS VARCHAR) FROM users");
2901 }
2902
2903 #[test]
2904 fn test_from_starter() {
2905 let sql = from("users").select_cols(["id", "name"]).to_sql();
2906 assert_eq!(sql, "SELECT id, name FROM users");
2907 }
2908
2909 #[test]
2910 fn test_qualified_column() {
2911 let sql = select([col("u.id"), col("u.name")]).from("users").to_sql();
2912 assert_eq!(sql, "SELECT u.id, u.name FROM users");
2913 }
2914
2915 #[test]
2916 fn test_nested_dot_column() {
2917 let sql = select([col("t.s.f")]).from("users").to_sql();
2918 assert_eq!(sql, "SELECT t.s.f FROM users");
2919 }
2920
2921 #[test]
2922 fn test_not_condition() {
2923 let sql = select(["id"])
2924 .from("users")
2925 .where_(not(col("active").eq(boolean(true))))
2926 .to_sql();
2927 assert_eq!(sql, "SELECT id FROM users WHERE NOT active = TRUE");
2928 }
2929
2930 #[test]
2931 fn test_order_by_desc() {
2932 let sql = select(["id", "name"])
2933 .from("users")
2934 .order_by([col("name").desc()])
2935 .to_sql();
2936 assert_eq!(sql, "SELECT id, name FROM users ORDER BY name DESC");
2937 }
2938
2939 #[test]
2940 fn test_left_join() {
2941 let sql = select(["u.id", "o.amount"])
2942 .from("users")
2943 .left_join("orders", col("u.id").eq(col("o.user_id")))
2944 .to_sql();
2945 assert_eq!(
2946 sql,
2947 "SELECT u.id, o.amount FROM users LEFT JOIN orders ON u.id = o.user_id"
2948 );
2949 }
2950
2951 #[test]
2952 fn test_build_returns_expression() {
2953 let expr = select(["id"]).from("users").build();
2954 assert!(matches!(expr, Expression::Select(_)));
2955 }
2956
2957 #[test]
2958 fn test_expr_interop() {
2959 let age_check = col("age").gt(lit(18));
2961 let sql = select([col("id"), age_check.alias("is_adult")])
2962 .from("users")
2963 .to_sql();
2964 assert_eq!(sql, "SELECT id, age > 18 AS is_adult FROM users");
2965 }
2966
2967 #[test]
2970 fn test_sql_expr_simple() {
2971 let expr = sql_expr("age > 18");
2972 let sql = select(["id"]).from("users").where_(expr).to_sql();
2973 assert_eq!(sql, "SELECT id FROM users WHERE age > 18");
2974 }
2975
2976 #[test]
2977 fn test_sql_expr_compound() {
2978 let expr = sql_expr("a > 1 AND b < 10");
2979 let sql = select(["*"]).from("t").where_(expr).to_sql();
2980 assert_eq!(sql, "SELECT * FROM t WHERE a > 1 AND b < 10");
2981 }
2982
2983 #[test]
2984 fn test_sql_expr_function() {
2985 let expr = sql_expr("COALESCE(a, b, 0)");
2986 let sql = select([expr.alias("val")]).from("t").to_sql();
2987 assert_eq!(sql, "SELECT COALESCE(a, b, 0) AS val FROM t");
2988 }
2989
2990 #[test]
2991 fn test_condition_alias() {
2992 let cond = condition("x > 0");
2993 let sql = select(["*"]).from("t").where_(cond).to_sql();
2994 assert_eq!(sql, "SELECT * FROM t WHERE x > 0");
2995 }
2996
2997 #[test]
3000 fn test_ilike() {
3001 let sql = select(["id"])
3002 .from("users")
3003 .where_(col("name").ilike(lit("%test%")))
3004 .to_sql();
3005 assert_eq!(sql, "SELECT id FROM users WHERE name ILIKE '%test%'");
3006 }
3007
3008 #[test]
3009 fn test_rlike() {
3010 let sql = select(["id"])
3011 .from("users")
3012 .where_(col("name").rlike(lit("^[A-Z]")))
3013 .to_sql();
3014 assert_eq!(
3015 sql,
3016 "SELECT id FROM users WHERE REGEXP_LIKE(name, '^[A-Z]')"
3017 );
3018 }
3019
3020 #[test]
3021 fn test_not_in() {
3022 let sql = select(["id"])
3023 .from("users")
3024 .where_(col("status").not_in([lit("deleted"), lit("banned")]))
3025 .to_sql();
3026 assert_eq!(
3027 sql,
3028 "SELECT id FROM users WHERE NOT status IN ('deleted', 'banned')"
3029 );
3030 }
3031
3032 #[test]
3035 fn test_case_searched() {
3036 let expr = case()
3037 .when(col("x").gt(lit(0)), lit("positive"))
3038 .when(col("x").eq(lit(0)), lit("zero"))
3039 .else_(lit("negative"))
3040 .build();
3041 let sql = select([expr.alias("label")]).from("t").to_sql();
3042 assert_eq!(
3043 sql,
3044 "SELECT CASE WHEN x > 0 THEN 'positive' WHEN x = 0 THEN 'zero' ELSE 'negative' END AS label FROM t"
3045 );
3046 }
3047
3048 #[test]
3049 fn test_case_simple() {
3050 let expr = case_of(col("status"))
3051 .when(lit(1), lit("active"))
3052 .when(lit(0), lit("inactive"))
3053 .build();
3054 let sql = select([expr.alias("status_label")]).from("t").to_sql();
3055 assert_eq!(
3056 sql,
3057 "SELECT CASE status WHEN 1 THEN 'active' WHEN 0 THEN 'inactive' END AS status_label FROM t"
3058 );
3059 }
3060
3061 #[test]
3062 fn test_case_no_else() {
3063 let expr = case().when(col("x").gt(lit(0)), lit("yes")).build();
3064 let sql = select([expr]).from("t").to_sql();
3065 assert_eq!(sql, "SELECT CASE WHEN x > 0 THEN 'yes' END FROM t");
3066 }
3067
3068 #[test]
3071 fn test_subquery_in_from() {
3072 let inner = select(["id", "name"])
3073 .from("users")
3074 .where_(col("active").eq(boolean(true)));
3075 let outer = select(["sub.id"])
3076 .from_expr(subquery(inner, "sub"))
3077 .to_sql();
3078 assert_eq!(
3079 outer,
3080 "SELECT sub.id FROM (SELECT id, name FROM users WHERE active = TRUE) AS sub"
3081 );
3082 }
3083
3084 #[test]
3085 fn test_subquery_in_join() {
3086 let inner = select([col("user_id"), func("SUM", [col("amount")]).alias("total")])
3087 .from("orders")
3088 .group_by(["user_id"]);
3089 let sql = select(["u.name", "o.total"])
3090 .from("users")
3091 .join("orders", col("u.id").eq(col("o.user_id")))
3092 .to_sql();
3093 assert!(sql.contains("JOIN"));
3094 let _sub = subquery(inner, "o");
3096 }
3097
3098 #[test]
3101 fn test_union() {
3102 let sql = union(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3103 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
3104 }
3105
3106 #[test]
3107 fn test_union_all() {
3108 let sql = union_all(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3109 assert_eq!(sql, "SELECT id FROM a UNION ALL SELECT id FROM b");
3110 }
3111
3112 #[test]
3113 fn test_intersect_builder() {
3114 let sql = intersect(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3115 assert_eq!(sql, "SELECT id FROM a INTERSECT SELECT id FROM b");
3116 }
3117
3118 #[test]
3119 fn test_except_builder() {
3120 let sql = except_(select(["id"]).from("a"), select(["id"]).from("b")).to_sql();
3121 assert_eq!(sql, "SELECT id FROM a EXCEPT SELECT id FROM b");
3122 }
3123
3124 #[test]
3125 fn test_union_with_order_limit() {
3126 let sql = union(select(["id"]).from("a"), select(["id"]).from("b"))
3127 .order_by(["id"])
3128 .limit(10)
3129 .to_sql();
3130 assert!(sql.contains("UNION"));
3131 assert!(sql.contains("ORDER BY"));
3132 assert!(sql.contains("LIMIT"));
3133 }
3134
3135 #[test]
3136 fn test_select_builder_union() {
3137 let sql = select(["id"])
3138 .from("a")
3139 .union(select(["id"]).from("b"))
3140 .to_sql();
3141 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
3142 }
3143
3144 #[test]
3147 fn test_qualify() {
3148 let sql = select(["id", "name"])
3149 .from("users")
3150 .qualify(col("rn").eq(lit(1)))
3151 .to_sql();
3152 assert_eq!(sql, "SELECT id, name FROM users QUALIFY rn = 1");
3153 }
3154
3155 #[test]
3156 fn test_right_join() {
3157 let sql = select(["u.id", "o.amount"])
3158 .from("users")
3159 .right_join("orders", col("u.id").eq(col("o.user_id")))
3160 .to_sql();
3161 assert_eq!(
3162 sql,
3163 "SELECT u.id, o.amount FROM users RIGHT JOIN orders ON u.id = o.user_id"
3164 );
3165 }
3166
3167 #[test]
3168 fn test_cross_join() {
3169 let sql = select(["a.x", "b.y"]).from("a").cross_join("b").to_sql();
3170 assert_eq!(sql, "SELECT a.x, b.y FROM a CROSS JOIN b");
3171 }
3172
3173 #[test]
3174 fn test_lateral_view() {
3175 let sql = select(["id", "col_val"])
3176 .from("t")
3177 .lateral_view(func("EXPLODE", [col("arr")]), "lv", ["col_val"])
3178 .to_sql();
3179 assert!(sql.contains("LATERAL VIEW"));
3180 assert!(sql.contains("EXPLODE"));
3181 }
3182
3183 #[test]
3184 fn test_window_clause() {
3185 let sql = select(["id"])
3186 .from("t")
3187 .window(
3188 "w",
3189 WindowDefBuilder::new()
3190 .partition_by(["dept"])
3191 .order_by(["salary"]),
3192 )
3193 .to_sql();
3194 assert!(sql.contains("WINDOW"));
3195 assert!(sql.contains("PARTITION BY"));
3196 }
3197
3198 #[test]
3201 fn test_xor() {
3202 let sql = select(["*"])
3203 .from("t")
3204 .where_(col("a").xor(col("b")))
3205 .to_sql();
3206 assert_eq!(sql, "SELECT * FROM t WHERE a XOR b");
3207 }
3208
3209 #[test]
3212 fn test_for_update() {
3213 let sql = select(["id"]).from("t").for_update().to_sql();
3214 assert_eq!(sql, "SELECT id FROM t FOR UPDATE");
3215 }
3216
3217 #[test]
3218 fn test_for_share() {
3219 let sql = select(["id"]).from("t").for_share().to_sql();
3220 assert_eq!(sql, "SELECT id FROM t FOR SHARE");
3221 }
3222
3223 #[test]
3226 fn test_hint() {
3227 let sql = select(["*"]).from("t").hint("FULL(t)").to_sql();
3228 assert!(sql.contains("FULL(t)"), "Expected hint in: {}", sql);
3229 }
3230
3231 #[test]
3234 fn test_ctas() {
3235 let expr = select(["*"]).from("t").ctas("new_table");
3236 let sql = Generator::sql(&expr).unwrap();
3237 assert_eq!(sql, "CREATE TABLE new_table AS SELECT * FROM t");
3238 }
3239
3240 #[test]
3243 fn test_merge_update_insert() {
3244 let sql = merge_into("target")
3245 .using("source", col("target.id").eq(col("source.id")))
3246 .when_matched_update(vec![("name", col("source.name"))])
3247 .when_not_matched_insert(&["id", "name"], vec![col("source.id"), col("source.name")])
3248 .to_sql();
3249 assert!(
3250 sql.contains("MERGE INTO"),
3251 "Expected MERGE INTO in: {}",
3252 sql
3253 );
3254 assert!(sql.contains("USING"), "Expected USING in: {}", sql);
3255 assert!(
3256 sql.contains("WHEN MATCHED"),
3257 "Expected WHEN MATCHED in: {}",
3258 sql
3259 );
3260 assert!(
3261 sql.contains("UPDATE SET"),
3262 "Expected UPDATE SET in: {}",
3263 sql
3264 );
3265 assert!(
3266 sql.contains("WHEN NOT MATCHED"),
3267 "Expected WHEN NOT MATCHED in: {}",
3268 sql
3269 );
3270 assert!(sql.contains("INSERT"), "Expected INSERT in: {}", sql);
3271 }
3272
3273 #[test]
3274 fn test_merge_delete() {
3275 let sql = merge_into("target")
3276 .using("source", col("target.id").eq(col("source.id")))
3277 .when_matched_delete()
3278 .to_sql();
3279 assert!(
3280 sql.contains("MERGE INTO"),
3281 "Expected MERGE INTO in: {}",
3282 sql
3283 );
3284 assert!(
3285 sql.contains("WHEN MATCHED THEN DELETE"),
3286 "Expected WHEN MATCHED THEN DELETE in: {}",
3287 sql
3288 );
3289 }
3290
3291 #[test]
3292 fn test_merge_with_condition() {
3293 let sql = merge_into("target")
3294 .using("source", col("target.id").eq(col("source.id")))
3295 .when_matched_update_where(
3296 col("source.active").eq(boolean(true)),
3297 vec![("name", col("source.name"))],
3298 )
3299 .to_sql();
3300 assert!(
3301 sql.contains("MERGE INTO"),
3302 "Expected MERGE INTO in: {}",
3303 sql
3304 );
3305 assert!(
3306 sql.contains("AND source.active = TRUE"),
3307 "Expected condition in: {}",
3308 sql
3309 );
3310 }
3311}