1use crate::expressions::*;
59use crate::generator::Generator;
60use crate::parser::Parser;
61
62pub fn col(name: &str) -> Expr {
86 if let Some((table, column)) = name.rsplit_once('.') {
87 Expr(Expression::Column(Column {
88 name: Identifier::new(column),
89 table: Some(Identifier::new(table)),
90 join_mark: false,
91 trailing_comments: Vec::new(),
92 }))
93 } else {
94 Expr(Expression::Column(Column {
95 name: Identifier::new(name),
96 table: None,
97 join_mark: false,
98 trailing_comments: Vec::new(),
99 }))
100 }
101}
102
103pub fn lit<V: IntoLiteral>(value: V) -> Expr {
119 value.into_literal()
120}
121
122pub fn star() -> Expr {
124 Expr(Expression::star())
125}
126
127pub fn null() -> Expr {
129 Expr(Expression::Null(Null))
130}
131
132pub fn boolean(value: bool) -> Expr {
134 Expr(Expression::Boolean(BooleanLiteral { value }))
135}
136
137pub fn table(name: &str) -> Expr {
154 let parts: Vec<&str> = name.split('.').collect();
155 let table_ref = match parts.len() {
156 3 => TableRef::new_with_catalog(parts[2], parts[1], parts[0]),
157 2 => TableRef::new_with_schema(parts[1], parts[0]),
158 _ => TableRef::new(parts[0]),
159 };
160 Expr(Expression::Table(table_ref))
161}
162
163pub fn func(name: &str, args: impl IntoIterator<Item = Expr>) -> Expr {
180 Expr(Expression::Function(Box::new(Function {
181 name: name.to_string(),
182 args: args.into_iter().map(|a| a.0).collect(),
183 ..Function::default()
184 })))
185}
186
187pub fn cast(expr: Expr, to: &str) -> Expr {
203 let data_type = parse_simple_data_type(to);
204 Expr(Expression::Cast(Box::new(Cast {
205 this: expr.0,
206 to: data_type,
207 trailing_comments: Vec::new(),
208 double_colon_syntax: false,
209 format: None,
210 default: None,
211 })))
212}
213
214pub fn not(expr: Expr) -> Expr {
219 Expr(Expression::Not(Box::new(UnaryOp::new(expr.0))))
220}
221
222pub fn and(left: Expr, right: Expr) -> Expr {
227 left.and(right)
228}
229
230pub fn or(left: Expr, right: Expr) -> Expr {
235 left.or(right)
236}
237
238pub fn alias(expr: Expr, name: &str) -> Expr {
243 Expr(Expression::Alias(Box::new(Alias {
244 this: expr.0,
245 alias: Identifier::new(name),
246 column_aliases: Vec::new(),
247 pre_alias_comments: Vec::new(),
248 trailing_comments: Vec::new(),
249 })))
250}
251
252pub fn sql_expr(sql: &str) -> Expr {
276 let wrapped = format!("SELECT {}", sql);
277 let ast = Parser::parse_sql(&wrapped).expect("sql_expr: failed to parse SQL expression");
278 if let Expression::Select(s) = &ast[0] {
279 if let Some(first) = s.expressions.first() {
280 return Expr(first.clone());
281 }
282 }
283 panic!("sql_expr: failed to extract expression from parsed SQL");
284}
285
286pub fn condition(sql: &str) -> Expr {
295 sql_expr(sql)
296}
297
298pub fn select<I, E>(expressions: I) -> SelectBuilder
325where
326 I: IntoIterator<Item = E>,
327 E: IntoExpr,
328{
329 let mut builder = SelectBuilder::new();
330 for expr in expressions {
331 builder.select = builder.select.column(expr.into_expr().0);
332 }
333 builder
334}
335
336pub fn from(table_name: &str) -> SelectBuilder {
351 let mut builder = SelectBuilder::new();
352 builder.select.from = Some(From {
353 expressions: vec![Expression::Table(TableRef::new(table_name))],
354 });
355 builder
356}
357
358pub fn delete(table_name: &str) -> DeleteBuilder {
371 DeleteBuilder {
372 delete: Delete {
373 table: TableRef::new(table_name),
374 on_cluster: None,
375 alias: None,
376 alias_explicit_as: false,
377 using: Vec::new(),
378 where_clause: None,
379 output: None,
380 leading_comments: Vec::new(),
381 with: None,
382 limit: None,
383 order_by: None,
384 returning: Vec::new(),
385 tables: Vec::new(),
386 tables_from_using: false,
387 joins: Vec::new(),
388 force_index: None,
389 no_from: false,
390 },
391 }
392}
393
394pub fn insert_into(table_name: &str) -> InsertBuilder {
411 InsertBuilder {
412 insert: Insert {
413 table: TableRef::new(table_name),
414 columns: Vec::new(),
415 values: Vec::new(),
416 query: None,
417 overwrite: false,
418 partition: Vec::new(),
419 directory: None,
420 returning: Vec::new(),
421 output: None,
422 on_conflict: None,
423 leading_comments: Vec::new(),
424 if_exists: false,
425 with: None,
426 ignore: false,
427 source_alias: None,
428 alias: None,
429 alias_explicit_as: false,
430 default_values: false,
431 by_name: false,
432 conflict_action: None,
433 is_replace: false,
434 hint: None,
435 replace_where: None,
436 source: None,
437 function_target: None,
438 partition_by: None,
439 settings: Vec::new(),
440 },
441 }
442}
443
444pub fn update(table_name: &str) -> UpdateBuilder {
462 UpdateBuilder {
463 update: Update {
464 table: TableRef::new(table_name),
465 extra_tables: Vec::new(),
466 table_joins: Vec::new(),
467 set: Vec::new(),
468 from_clause: None,
469 from_joins: Vec::new(),
470 where_clause: None,
471 returning: Vec::new(),
472 output: None,
473 with: None,
474 leading_comments: Vec::new(),
475 limit: None,
476 order_by: None,
477 from_before_set: false,
478 },
479 }
480}
481
482#[derive(Debug, Clone)]
507pub struct Expr(pub Expression);
508
509impl Expr {
510 pub fn into_inner(self) -> Expression {
512 self.0
513 }
514
515 pub fn to_sql(&self) -> String {
519 Generator::sql(&self.0).unwrap_or_default()
520 }
521
522 pub fn eq(self, other: Expr) -> Expr {
526 Expr(Expression::Eq(Box::new(binary_op(self.0, other.0))))
527 }
528
529 pub fn neq(self, other: Expr) -> Expr {
531 Expr(Expression::Neq(Box::new(binary_op(self.0, other.0))))
532 }
533
534 pub fn lt(self, other: Expr) -> Expr {
536 Expr(Expression::Lt(Box::new(binary_op(self.0, other.0))))
537 }
538
539 pub fn lte(self, other: Expr) -> Expr {
541 Expr(Expression::Lte(Box::new(binary_op(self.0, other.0))))
542 }
543
544 pub fn gt(self, other: Expr) -> Expr {
546 Expr(Expression::Gt(Box::new(binary_op(self.0, other.0))))
547 }
548
549 pub fn gte(self, other: Expr) -> Expr {
551 Expr(Expression::Gte(Box::new(binary_op(self.0, other.0))))
552 }
553
554 pub fn and(self, other: Expr) -> Expr {
558 Expr(Expression::And(Box::new(binary_op(self.0, other.0))))
559 }
560
561 pub fn or(self, other: Expr) -> Expr {
563 Expr(Expression::Or(Box::new(binary_op(self.0, other.0))))
564 }
565
566 pub fn not(self) -> Expr {
568 Expr(Expression::Not(Box::new(UnaryOp::new(self.0))))
569 }
570
571 pub fn xor(self, other: Expr) -> Expr {
573 Expr(Expression::Xor(Box::new(Xor {
574 this: Some(Box::new(self.0)),
575 expression: Some(Box::new(other.0)),
576 expressions: vec![],
577 })))
578 }
579
580 pub fn add(self, other: Expr) -> Expr {
584 Expr(Expression::Add(Box::new(binary_op(self.0, other.0))))
585 }
586
587 pub fn sub(self, other: Expr) -> Expr {
589 Expr(Expression::Sub(Box::new(binary_op(self.0, other.0))))
590 }
591
592 pub fn mul(self, other: Expr) -> Expr {
594 Expr(Expression::Mul(Box::new(binary_op(self.0, other.0))))
595 }
596
597 pub fn div(self, other: Expr) -> Expr {
599 Expr(Expression::Div(Box::new(binary_op(self.0, other.0))))
600 }
601
602 pub fn is_null(self) -> Expr {
606 Expr(Expression::Is(Box::new(BinaryOp {
607 left: self.0,
608 right: Expression::Null(Null),
609 left_comments: Vec::new(),
610 operator_comments: Vec::new(),
611 trailing_comments: Vec::new(),
612 })))
613 }
614
615 pub fn is_not_null(self) -> Expr {
617 Expr(Expression::Not(Box::new(UnaryOp::new(
618 Expression::Is(Box::new(BinaryOp {
619 left: self.0,
620 right: Expression::Null(Null),
621 left_comments: Vec::new(),
622 operator_comments: Vec::new(),
623 trailing_comments: Vec::new(),
624 })),
625 ))))
626 }
627
628 pub fn in_list(self, values: impl IntoIterator<Item = Expr>) -> Expr {
632 Expr(Expression::In(Box::new(In {
633 this: self.0,
634 expressions: values.into_iter().map(|v| v.0).collect(),
635 query: None,
636 not: false,
637 global: false,
638 unnest: None,
639 })))
640 }
641
642 pub fn between(self, low: Expr, high: Expr) -> Expr {
644 Expr(Expression::Between(Box::new(Between {
645 this: self.0,
646 low: low.0,
647 high: high.0,
648 not: false,
649 })))
650 }
651
652 pub fn like(self, pattern: Expr) -> Expr {
654 Expr(Expression::Like(Box::new(LikeOp {
655 left: self.0,
656 right: pattern.0,
657 escape: None,
658 quantifier: None,
659 })))
660 }
661
662 pub fn alias(self, name: &str) -> Expr {
664 alias(self, name)
665 }
666
667 pub fn cast(self, to: &str) -> Expr {
671 cast(self, to)
672 }
673
674 pub fn asc(self) -> Expr {
679 Expr(Expression::Ordered(Box::new(Ordered {
680 this: self.0,
681 desc: false,
682 nulls_first: None,
683 explicit_asc: true,
684 with_fill: None,
685 })))
686 }
687
688 pub fn desc(self) -> Expr {
692 Expr(Expression::Ordered(Box::new(Ordered {
693 this: self.0,
694 desc: true,
695 nulls_first: None,
696 explicit_asc: false,
697 with_fill: None,
698 })))
699 }
700
701 pub fn ilike(self, pattern: Expr) -> Expr {
706 Expr(Expression::ILike(Box::new(LikeOp {
707 left: self.0,
708 right: pattern.0,
709 escape: None,
710 quantifier: None,
711 })))
712 }
713
714 pub fn rlike(self, pattern: Expr) -> Expr {
719 Expr(Expression::RegexpLike(Box::new(RegexpFunc {
720 this: self.0,
721 pattern: pattern.0,
722 flags: None,
723 })))
724 }
725
726 pub fn not_in(self, values: impl IntoIterator<Item = Expr>) -> Expr {
730 Expr(Expression::In(Box::new(In {
731 this: self.0,
732 expressions: values.into_iter().map(|v| v.0).collect(),
733 query: None,
734 not: true,
735 global: false,
736 unnest: None,
737 })))
738 }
739}
740
741pub struct SelectBuilder {
767 select: Select,
768}
769
770impl SelectBuilder {
771 fn new() -> Self {
772 SelectBuilder {
773 select: Select::new(),
774 }
775 }
776
777 pub fn select_cols<I, E>(mut self, expressions: I) -> Self
782 where
783 I: IntoIterator<Item = E>,
784 E: IntoExpr,
785 {
786 for expr in expressions {
787 self.select.expressions.push(expr.into_expr().0);
788 }
789 self
790 }
791
792 pub fn from(mut self, table_name: &str) -> Self {
794 self.select.from = Some(From {
795 expressions: vec![Expression::Table(TableRef::new(table_name))],
796 });
797 self
798 }
799
800 pub fn from_expr(mut self, expr: Expr) -> Self {
805 self.select.from = Some(From {
806 expressions: vec![expr.0],
807 });
808 self
809 }
810
811 pub fn join(mut self, table_name: &str, on: Expr) -> Self {
813 self.select.joins.push(Join {
814 kind: JoinKind::Inner,
815 this: Expression::Table(TableRef::new(table_name)),
816 on: Some(on.0),
817 using: Vec::new(),
818 use_inner_keyword: false,
819 use_outer_keyword: false,
820 deferred_condition: false,
821 join_hint: None,
822 match_condition: None,
823 pivots: Vec::new(),
824 });
825 self
826 }
827
828 pub fn left_join(mut self, table_name: &str, on: Expr) -> Self {
830 self.select.joins.push(Join {
831 kind: JoinKind::Left,
832 this: Expression::Table(TableRef::new(table_name)),
833 on: Some(on.0),
834 using: Vec::new(),
835 use_inner_keyword: false,
836 use_outer_keyword: false,
837 deferred_condition: false,
838 join_hint: None,
839 match_condition: None,
840 pivots: Vec::new(),
841 });
842 self
843 }
844
845 pub fn where_(mut self, condition: Expr) -> Self {
851 self.select.where_clause = Some(Where { this: condition.0 });
852 self
853 }
854
855 pub fn group_by<I, E>(mut self, expressions: I) -> Self
857 where
858 I: IntoIterator<Item = E>,
859 E: IntoExpr,
860 {
861 self.select.group_by = Some(GroupBy {
862 expressions: expressions.into_iter().map(|e| e.into_expr().0).collect(),
863 all: None,
864 totals: false,
865 });
866 self
867 }
868
869 pub fn having(mut self, condition: Expr) -> Self {
871 self.select.having = Some(Having { this: condition.0 });
872 self
873 }
874
875 pub fn order_by<I, E>(mut self, expressions: I) -> Self
881 where
882 I: IntoIterator<Item = E>,
883 E: IntoExpr,
884 {
885 self.select.order_by = Some(OrderBy {
886 siblings: false,
887 expressions: expressions
888 .into_iter()
889 .map(|e| {
890 let expr = e.into_expr().0;
891 match expr {
892 Expression::Ordered(_) => expr,
893 other => Expression::Ordered(Box::new(Ordered {
894 this: other,
895 desc: false,
896 nulls_first: None,
897 explicit_asc: false,
898 with_fill: None,
899 })),
900 }
901 })
902 .collect::<Vec<_>>()
903 .into_iter()
904 .map(|e| {
905 if let Expression::Ordered(o) = e {
906 *o
907 } else {
908 Ordered {
909 this: e,
910 desc: false,
911 nulls_first: None,
912 explicit_asc: false,
913 with_fill: None,
914 }
915 }
916 })
917 .collect(),
918 });
919 self
920 }
921
922 pub fn limit(mut self, count: usize) -> Self {
924 self.select.limit = Some(Limit {
925 this: Expression::Literal(Literal::Number(count.to_string())),
926 percent: false,
927 });
928 self
929 }
930
931 pub fn offset(mut self, count: usize) -> Self {
933 self.select.offset = Some(Offset {
934 this: Expression::Literal(Literal::Number(count.to_string())),
935 rows: None,
936 });
937 self
938 }
939
940 pub fn distinct(mut self) -> Self {
942 self.select.distinct = true;
943 self
944 }
945
946 pub fn qualify(mut self, condition: Expr) -> Self {
951 self.select.qualify = Some(Qualify { this: condition.0 });
952 self
953 }
954
955 pub fn right_join(mut self, table_name: &str, on: Expr) -> Self {
957 self.select.joins.push(Join {
958 kind: JoinKind::Right,
959 this: Expression::Table(TableRef::new(table_name)),
960 on: Some(on.0),
961 using: Vec::new(),
962 use_inner_keyword: false,
963 use_outer_keyword: false,
964 deferred_condition: false,
965 join_hint: None,
966 match_condition: None,
967 pivots: Vec::new(),
968 });
969 self
970 }
971
972 pub fn cross_join(mut self, table_name: &str) -> Self {
974 self.select.joins.push(Join {
975 kind: JoinKind::Cross,
976 this: Expression::Table(TableRef::new(table_name)),
977 on: None,
978 using: Vec::new(),
979 use_inner_keyword: false,
980 use_outer_keyword: false,
981 deferred_condition: false,
982 join_hint: None,
983 match_condition: None,
984 pivots: Vec::new(),
985 });
986 self
987 }
988
989 pub fn lateral_view<S: AsRef<str>>(
996 mut self,
997 table_function: Expr,
998 table_alias: &str,
999 column_aliases: impl IntoIterator<Item = S>,
1000 ) -> Self {
1001 self.select.lateral_views.push(LateralView {
1002 this: table_function.0,
1003 table_alias: Some(Identifier::new(table_alias)),
1004 column_aliases: column_aliases
1005 .into_iter()
1006 .map(|c| Identifier::new(c.as_ref()))
1007 .collect(),
1008 outer: false,
1009 });
1010 self
1011 }
1012
1013 pub fn window(mut self, name: &str, def: WindowDefBuilder) -> Self {
1019 let named_window = NamedWindow {
1020 name: Identifier::new(name),
1021 spec: Over {
1022 window_name: None,
1023 partition_by: def.partition_by,
1024 order_by: def.order_by,
1025 frame: None,
1026 alias: None,
1027 },
1028 };
1029 match self.select.windows {
1030 Some(ref mut windows) => windows.push(named_window),
1031 None => self.select.windows = Some(vec![named_window]),
1032 }
1033 self
1034 }
1035
1036 pub fn for_update(mut self) -> Self {
1041 self.select.locks.push(Lock {
1042 update: Some(Box::new(Expression::Boolean(BooleanLiteral { value: true }))),
1043 expressions: vec![],
1044 wait: None,
1045 key: None,
1046 });
1047 self
1048 }
1049
1050 pub fn for_share(mut self) -> Self {
1055 self.select.locks.push(Lock {
1056 update: None,
1057 expressions: vec![],
1058 wait: None,
1059 key: None,
1060 });
1061 self
1062 }
1063
1064 pub fn hint(mut self, hint_text: &str) -> Self {
1069 let hint_expr = HintExpression::Raw(hint_text.to_string());
1070 match &mut self.select.hint {
1071 Some(h) => h.expressions.push(hint_expr),
1072 None => {
1073 self.select.hint = Some(Hint {
1074 expressions: vec![hint_expr],
1075 })
1076 }
1077 }
1078 self
1079 }
1080
1081 pub fn ctas(self, table_name: &str) -> Expression {
1097 Expression::CreateTable(Box::new(CreateTable {
1098 name: TableRef::new(table_name),
1099 on_cluster: None,
1100 columns: vec![],
1101 constraints: vec![],
1102 if_not_exists: false,
1103 temporary: false,
1104 or_replace: false,
1105 table_modifier: None,
1106 as_select: Some(self.build()),
1107 as_select_parenthesized: false,
1108 on_commit: None,
1109 clone_source: None,
1110 clone_at_clause: None,
1111 is_copy: false,
1112 shallow_clone: false,
1113 leading_comments: vec![],
1114 with_properties: vec![],
1115 teradata_post_name_options: vec![],
1116 with_data: None,
1117 with_statistics: None,
1118 teradata_indexes: vec![],
1119 with_cte: None,
1120 properties: vec![],
1121 partition_of: None,
1122 post_table_properties: vec![],
1123 mysql_table_options: vec![],
1124 inherits: vec![],
1125 on_property: None,
1126 copy_grants: false,
1127 using_template: None,
1128 rollup: None,
1129 }))
1130 }
1131
1132 pub fn union(self, other: SelectBuilder) -> SetOpBuilder {
1136 SetOpBuilder::new(SetOpKind::Union, self, other, false)
1137 }
1138
1139 pub fn union_all(self, other: SelectBuilder) -> SetOpBuilder {
1143 SetOpBuilder::new(SetOpKind::Union, self, other, true)
1144 }
1145
1146 pub fn intersect(self, other: SelectBuilder) -> SetOpBuilder {
1150 SetOpBuilder::new(SetOpKind::Intersect, self, other, false)
1151 }
1152
1153 pub fn except_(self, other: SelectBuilder) -> SetOpBuilder {
1157 SetOpBuilder::new(SetOpKind::Except, self, other, false)
1158 }
1159
1160 pub fn build(self) -> Expression {
1162 Expression::Select(Box::new(self.select))
1163 }
1164
1165 pub fn to_sql(self) -> String {
1170 Generator::sql(&self.build()).unwrap_or_default()
1171 }
1172}
1173
1174pub struct DeleteBuilder {
1183 delete: Delete,
1184}
1185
1186impl DeleteBuilder {
1187 pub fn where_(mut self, condition: Expr) -> Self {
1189 self.delete.where_clause = Some(Where { this: condition.0 });
1190 self
1191 }
1192
1193 pub fn build(self) -> Expression {
1195 Expression::Delete(Box::new(self.delete))
1196 }
1197
1198 pub fn to_sql(self) -> String {
1200 Generator::sql(&self.build()).unwrap_or_default()
1201 }
1202}
1203
1204pub struct InsertBuilder {
1215 insert: Insert,
1216}
1217
1218impl InsertBuilder {
1219 pub fn columns<I, S>(mut self, columns: I) -> Self
1221 where
1222 I: IntoIterator<Item = S>,
1223 S: AsRef<str>,
1224 {
1225 self.insert.columns = columns
1226 .into_iter()
1227 .map(|c| Identifier::new(c.as_ref()))
1228 .collect();
1229 self
1230 }
1231
1232 pub fn values<I>(mut self, values: I) -> Self
1236 where
1237 I: IntoIterator<Item = Expr>,
1238 {
1239 self.insert
1240 .values
1241 .push(values.into_iter().map(|v| v.0).collect());
1242 self
1243 }
1244
1245 pub fn query(mut self, query: SelectBuilder) -> Self {
1249 self.insert.query = Some(query.build());
1250 self
1251 }
1252
1253 pub fn build(self) -> Expression {
1255 Expression::Insert(Box::new(self.insert))
1256 }
1257
1258 pub fn to_sql(self) -> String {
1260 Generator::sql(&self.build()).unwrap_or_default()
1261 }
1262}
1263
1264pub struct UpdateBuilder {
1274 update: Update,
1275}
1276
1277impl UpdateBuilder {
1278 pub fn set(mut self, column: &str, value: Expr) -> Self {
1282 self.update
1283 .set
1284 .push((Identifier::new(column), value.0));
1285 self
1286 }
1287
1288 pub fn where_(mut self, condition: Expr) -> Self {
1290 self.update.where_clause = Some(Where { this: condition.0 });
1291 self
1292 }
1293
1294 pub fn from(mut self, table_name: &str) -> Self {
1298 self.update.from_clause = Some(From {
1299 expressions: vec![Expression::Table(TableRef::new(table_name))],
1300 });
1301 self
1302 }
1303
1304 pub fn build(self) -> Expression {
1306 Expression::Update(Box::new(self.update))
1307 }
1308
1309 pub fn to_sql(self) -> String {
1311 Generator::sql(&self.build()).unwrap_or_default()
1312 }
1313}
1314
1315pub fn case() -> CaseBuilder {
1340 CaseBuilder {
1341 operand: None,
1342 whens: Vec::new(),
1343 else_: None,
1344 }
1345}
1346
1347pub fn case_of(operand: Expr) -> CaseBuilder {
1368 CaseBuilder {
1369 operand: Some(operand.0),
1370 whens: Vec::new(),
1371 else_: None,
1372 }
1373}
1374
1375pub struct CaseBuilder {
1383 operand: Option<Expression>,
1384 whens: Vec<(Expression, Expression)>,
1385 else_: Option<Expression>,
1386}
1387
1388impl CaseBuilder {
1389 pub fn when(mut self, condition: Expr, result: Expr) -> Self {
1394 self.whens.push((condition.0, result.0));
1395 self
1396 }
1397
1398 pub fn else_(mut self, result: Expr) -> Self {
1403 self.else_ = Some(result.0);
1404 self
1405 }
1406
1407 pub fn build(self) -> Expr {
1409 Expr(self.build_expr())
1410 }
1411
1412 pub fn build_expr(self) -> Expression {
1417 Expression::Case(Box::new(Case {
1418 operand: self.operand,
1419 whens: self.whens,
1420 else_: self.else_,
1421 }))
1422 }
1423}
1424
1425pub fn subquery(query: SelectBuilder, alias_name: &str) -> Expr {
1449 subquery_expr(query.build(), alias_name)
1450}
1451
1452pub fn subquery_expr(expr: Expression, alias_name: &str) -> Expr {
1457 Expr(Expression::Subquery(Box::new(Subquery {
1458 this: expr,
1459 alias: Some(Identifier::new(alias_name)),
1460 column_aliases: Vec::new(),
1461 order_by: None,
1462 limit: None,
1463 offset: None,
1464 distribute_by: None,
1465 sort_by: None,
1466 cluster_by: None,
1467 lateral: false,
1468 modifiers_inside: true,
1469 trailing_comments: Vec::new(),
1470 })))
1471}
1472
1473#[derive(Debug, Clone, Copy)]
1479enum SetOpKind {
1480 Union,
1481 Intersect,
1482 Except,
1483}
1484
1485pub struct SetOpBuilder {
1506 kind: SetOpKind,
1507 left: Expression,
1508 right: Expression,
1509 all: bool,
1510 order_by: Option<OrderBy>,
1511 limit: Option<Box<Expression>>,
1512 offset: Option<Box<Expression>>,
1513}
1514
1515impl SetOpBuilder {
1516 fn new(kind: SetOpKind, left: SelectBuilder, right: SelectBuilder, all: bool) -> Self {
1517 SetOpBuilder {
1518 kind,
1519 left: left.build(),
1520 right: right.build(),
1521 all,
1522 order_by: None,
1523 limit: None,
1524 offset: None,
1525 }
1526 }
1527
1528 pub fn order_by<I, E>(mut self, expressions: I) -> Self
1533 where
1534 I: IntoIterator<Item = E>,
1535 E: IntoExpr,
1536 {
1537 self.order_by = Some(OrderBy {
1538 siblings: false,
1539 expressions: expressions
1540 .into_iter()
1541 .map(|e| {
1542 let expr = e.into_expr().0;
1543 match expr {
1544 Expression::Ordered(o) => *o,
1545 other => Ordered {
1546 this: other,
1547 desc: false,
1548 nulls_first: None,
1549 explicit_asc: false,
1550 with_fill: None,
1551 },
1552 }
1553 })
1554 .collect(),
1555 });
1556 self
1557 }
1558
1559 pub fn limit(mut self, count: usize) -> Self {
1561 self.limit = Some(Box::new(Expression::Literal(Literal::Number(
1562 count.to_string(),
1563 ))));
1564 self
1565 }
1566
1567 pub fn offset(mut self, count: usize) -> Self {
1569 self.offset = Some(Box::new(Expression::Literal(Literal::Number(
1570 count.to_string(),
1571 ))));
1572 self
1573 }
1574
1575 pub fn build(self) -> Expression {
1580 match self.kind {
1581 SetOpKind::Union => Expression::Union(Box::new(Union {
1582 left: self.left,
1583 right: self.right,
1584 all: self.all,
1585 distinct: false,
1586 with: None,
1587 order_by: self.order_by,
1588 limit: self.limit,
1589 offset: self.offset,
1590 distribute_by: None,
1591 sort_by: None,
1592 cluster_by: None,
1593 by_name: false,
1594 side: None,
1595 kind: None,
1596 corresponding: false,
1597 strict: false,
1598 on_columns: Vec::new(),
1599 })),
1600 SetOpKind::Intersect => Expression::Intersect(Box::new(Intersect {
1601 left: self.left,
1602 right: self.right,
1603 all: self.all,
1604 distinct: false,
1605 with: None,
1606 order_by: self.order_by,
1607 limit: self.limit,
1608 offset: self.offset,
1609 distribute_by: None,
1610 sort_by: None,
1611 cluster_by: None,
1612 by_name: false,
1613 side: None,
1614 kind: None,
1615 corresponding: false,
1616 strict: false,
1617 on_columns: Vec::new(),
1618 })),
1619 SetOpKind::Except => Expression::Except(Box::new(Except {
1620 left: self.left,
1621 right: self.right,
1622 all: self.all,
1623 distinct: false,
1624 with: None,
1625 order_by: self.order_by,
1626 limit: self.limit,
1627 offset: self.offset,
1628 distribute_by: None,
1629 sort_by: None,
1630 cluster_by: None,
1631 by_name: false,
1632 side: None,
1633 kind: None,
1634 corresponding: false,
1635 strict: false,
1636 on_columns: Vec::new(),
1637 })),
1638 }
1639 }
1640
1641 pub fn to_sql(self) -> String {
1643 Generator::sql(&self.build()).unwrap_or_default()
1644 }
1645}
1646
1647pub fn union(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
1651 SetOpBuilder::new(SetOpKind::Union, left, right, false)
1652}
1653
1654pub fn union_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
1658 SetOpBuilder::new(SetOpKind::Union, left, right, true)
1659}
1660
1661pub fn intersect(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
1665 SetOpBuilder::new(SetOpKind::Intersect, left, right, false)
1666}
1667
1668pub fn intersect_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
1672 SetOpBuilder::new(SetOpKind::Intersect, left, right, true)
1673}
1674
1675pub fn except_(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
1679 SetOpBuilder::new(SetOpKind::Except, left, right, false)
1680}
1681
1682pub fn except_all(left: SelectBuilder, right: SelectBuilder) -> SetOpBuilder {
1686 SetOpBuilder::new(SetOpKind::Except, left, right, true)
1687}
1688
1689pub struct WindowDefBuilder {
1714 partition_by: Vec<Expression>,
1715 order_by: Vec<Ordered>,
1716}
1717
1718impl WindowDefBuilder {
1719 pub fn new() -> Self {
1721 WindowDefBuilder {
1722 partition_by: Vec::new(),
1723 order_by: Vec::new(),
1724 }
1725 }
1726
1727 pub fn partition_by<I, E>(mut self, expressions: I) -> Self
1729 where
1730 I: IntoIterator<Item = E>,
1731 E: IntoExpr,
1732 {
1733 self.partition_by = expressions.into_iter().map(|e| e.into_expr().0).collect();
1734 self
1735 }
1736
1737 pub fn order_by<I, E>(mut self, expressions: I) -> Self
1742 where
1743 I: IntoIterator<Item = E>,
1744 E: IntoExpr,
1745 {
1746 self.order_by = expressions
1747 .into_iter()
1748 .map(|e| {
1749 let expr = e.into_expr().0;
1750 match expr {
1751 Expression::Ordered(o) => *o,
1752 other => Ordered {
1753 this: other,
1754 desc: false,
1755 nulls_first: None,
1756 explicit_asc: false,
1757 with_fill: None,
1758 },
1759 }
1760 })
1761 .collect();
1762 self
1763 }
1764}
1765
1766pub trait IntoExpr {
1782 fn into_expr(self) -> Expr;
1784}
1785
1786impl IntoExpr for Expr {
1787 fn into_expr(self) -> Expr {
1788 self
1789 }
1790}
1791
1792impl IntoExpr for &str {
1793 fn into_expr(self) -> Expr {
1795 col(self)
1796 }
1797}
1798
1799impl IntoExpr for String {
1800 fn into_expr(self) -> Expr {
1802 col(&self)
1803 }
1804}
1805
1806impl IntoExpr for Expression {
1807 fn into_expr(self) -> Expr {
1809 Expr(self)
1810 }
1811}
1812
1813pub trait IntoLiteral {
1828 fn into_literal(self) -> Expr;
1830}
1831
1832impl IntoLiteral for &str {
1833 fn into_literal(self) -> Expr {
1835 Expr(Expression::Literal(Literal::String(self.to_string())))
1836 }
1837}
1838
1839impl IntoLiteral for String {
1840 fn into_literal(self) -> Expr {
1842 Expr(Expression::Literal(Literal::String(self)))
1843 }
1844}
1845
1846impl IntoLiteral for i64 {
1847 fn into_literal(self) -> Expr {
1849 Expr(Expression::Literal(Literal::Number(self.to_string())))
1850 }
1851}
1852
1853impl IntoLiteral for i32 {
1854 fn into_literal(self) -> Expr {
1856 Expr(Expression::Literal(Literal::Number(self.to_string())))
1857 }
1858}
1859
1860impl IntoLiteral for usize {
1861 fn into_literal(self) -> Expr {
1863 Expr(Expression::Literal(Literal::Number(self.to_string())))
1864 }
1865}
1866
1867impl IntoLiteral for f64 {
1868 fn into_literal(self) -> Expr {
1870 Expr(Expression::Literal(Literal::Number(self.to_string())))
1871 }
1872}
1873
1874impl IntoLiteral for bool {
1875 fn into_literal(self) -> Expr {
1877 Expr(Expression::Boolean(BooleanLiteral { value: self }))
1878 }
1879}
1880
1881fn binary_op(left: Expression, right: Expression) -> BinaryOp {
1886 BinaryOp {
1887 left,
1888 right,
1889 left_comments: Vec::new(),
1890 operator_comments: Vec::new(),
1891 trailing_comments: Vec::new(),
1892 }
1893}
1894
1895pub fn merge_into(target: &str) -> MergeBuilder {
1917 MergeBuilder {
1918 target: Expression::Table(TableRef::new(target)),
1919 using: None,
1920 on: None,
1921 whens: Vec::new(),
1922 }
1923}
1924
1925pub struct MergeBuilder {
1929 target: Expression,
1930 using: Option<Expression>,
1931 on: Option<Expression>,
1932 whens: Vec<Expression>,
1933}
1934
1935impl MergeBuilder {
1936 pub fn using(mut self, source: &str, on: Expr) -> Self {
1938 self.using = Some(Expression::Table(TableRef::new(source)));
1939 self.on = Some(on.0);
1940 self
1941 }
1942
1943 pub fn when_matched_update(mut self, assignments: Vec<(&str, Expr)>) -> Self {
1945 let eqs: Vec<Expression> = assignments
1946 .into_iter()
1947 .map(|(col_name, val)| {
1948 Expression::Eq(Box::new(BinaryOp {
1949 left: Expression::Column(Column {
1950 name: Identifier::new(col_name),
1951 table: None,
1952 join_mark: false,
1953 trailing_comments: Vec::new(),
1954 }),
1955 right: val.0,
1956 left_comments: Vec::new(),
1957 operator_comments: Vec::new(),
1958 trailing_comments: Vec::new(),
1959 }))
1960 })
1961 .collect();
1962
1963 let action = Expression::Tuple(Box::new(Tuple {
1964 expressions: vec![
1965 Expression::Var(Box::new(Var {
1966 this: "UPDATE".to_string(),
1967 })),
1968 Expression::Tuple(Box::new(Tuple { expressions: eqs })),
1969 ],
1970 }));
1971
1972 let when = Expression::When(Box::new(When {
1973 matched: Some(Box::new(Expression::Boolean(BooleanLiteral { value: true }))),
1974 source: None,
1975 condition: None,
1976 then: Box::new(action),
1977 }));
1978 self.whens.push(when);
1979 self
1980 }
1981
1982 pub fn when_matched_update_where(
1984 mut self,
1985 condition: Expr,
1986 assignments: Vec<(&str, Expr)>,
1987 ) -> Self {
1988 let eqs: Vec<Expression> = assignments
1989 .into_iter()
1990 .map(|(col_name, val)| {
1991 Expression::Eq(Box::new(BinaryOp {
1992 left: Expression::Column(Column {
1993 name: Identifier::new(col_name),
1994 table: None,
1995 join_mark: false,
1996 trailing_comments: Vec::new(),
1997 }),
1998 right: val.0,
1999 left_comments: Vec::new(),
2000 operator_comments: Vec::new(),
2001 trailing_comments: Vec::new(),
2002 }))
2003 })
2004 .collect();
2005
2006 let action = Expression::Tuple(Box::new(Tuple {
2007 expressions: vec![
2008 Expression::Var(Box::new(Var {
2009 this: "UPDATE".to_string(),
2010 })),
2011 Expression::Tuple(Box::new(Tuple { expressions: eqs })),
2012 ],
2013 }));
2014
2015 let when = Expression::When(Box::new(When {
2016 matched: Some(Box::new(Expression::Boolean(BooleanLiteral { value: true }))),
2017 source: None,
2018 condition: Some(Box::new(condition.0)),
2019 then: Box::new(action),
2020 }));
2021 self.whens.push(when);
2022 self
2023 }
2024
2025 pub fn when_matched_delete(mut self) -> Self {
2027 let action = Expression::Var(Box::new(Var {
2028 this: "DELETE".to_string(),
2029 }));
2030
2031 let when = Expression::When(Box::new(When {
2032 matched: Some(Box::new(Expression::Boolean(BooleanLiteral { value: true }))),
2033 source: None,
2034 condition: None,
2035 then: Box::new(action),
2036 }));
2037 self.whens.push(when);
2038 self
2039 }
2040
2041 pub fn when_not_matched_insert(mut self, columns: &[&str], values: Vec<Expr>) -> Self {
2043 let col_exprs: Vec<Expression> = columns
2044 .iter()
2045 .map(|c| {
2046 Expression::Column(Column {
2047 name: Identifier::new(*c),
2048 table: None,
2049 join_mark: false,
2050 trailing_comments: Vec::new(),
2051 })
2052 })
2053 .collect();
2054 let val_exprs: Vec<Expression> = values.into_iter().map(|v| v.0).collect();
2055
2056 let action = Expression::Tuple(Box::new(Tuple {
2057 expressions: vec![
2058 Expression::Var(Box::new(Var {
2059 this: "INSERT".to_string(),
2060 })),
2061 Expression::Tuple(Box::new(Tuple {
2062 expressions: col_exprs,
2063 })),
2064 Expression::Tuple(Box::new(Tuple {
2065 expressions: val_exprs,
2066 })),
2067 ],
2068 }));
2069
2070 let when = Expression::When(Box::new(When {
2071 matched: Some(Box::new(Expression::Boolean(BooleanLiteral {
2072 value: false,
2073 }))),
2074 source: None,
2075 condition: None,
2076 then: Box::new(action),
2077 }));
2078 self.whens.push(when);
2079 self
2080 }
2081
2082 pub fn build(self) -> Expression {
2084 let whens_expr = Expression::Whens(Box::new(Whens {
2085 expressions: self.whens,
2086 }));
2087
2088 Expression::Merge(Box::new(Merge {
2089 this: Box::new(self.target),
2090 using: Box::new(
2091 self.using
2092 .unwrap_or(Expression::Null(crate::expressions::Null)),
2093 ),
2094 on: self.on.map(Box::new),
2095 using_cond: None,
2096 whens: Some(Box::new(whens_expr)),
2097 with_: None,
2098 returning: None,
2099 }))
2100 }
2101
2102 pub fn to_sql(self) -> String {
2104 Generator::sql(&self.build()).unwrap_or_default()
2105 }
2106}
2107
2108fn parse_simple_data_type(name: &str) -> DataType {
2109 let upper = name.trim().to_uppercase();
2110 match upper.as_str() {
2111 "INT" | "INTEGER" => DataType::Int {
2112 length: None,
2113 integer_spelling: upper == "INTEGER",
2114 },
2115 "BIGINT" => DataType::BigInt { length: None },
2116 "SMALLINT" => DataType::SmallInt { length: None },
2117 "TINYINT" => DataType::TinyInt { length: None },
2118 "FLOAT" => DataType::Float { precision: None, scale: None, real_spelling: false },
2119 "DOUBLE" => DataType::Double {
2120 precision: None,
2121 scale: None,
2122 },
2123 "BOOLEAN" | "BOOL" => DataType::Boolean,
2124 "TEXT" => DataType::Text,
2125 "DATE" => DataType::Date,
2126 "TIMESTAMP" => DataType::Timestamp {
2127 precision: None,
2128 timezone: false,
2129 },
2130 "VARCHAR" => DataType::VarChar {
2131 length: None,
2132 parenthesized_length: false,
2133 },
2134 "CHAR" => DataType::Char { length: None },
2135 _ => {
2136 if let Ok(ast) = crate::parser::Parser::parse_sql(&format!("SELECT CAST(x AS {})", name)) {
2138 if let Expression::Select(s) = &ast[0] {
2139 if let Some(Expression::Cast(c)) = s.expressions.first() {
2140 return c.to.clone();
2141 }
2142 }
2143 }
2144 DataType::Custom { name: name.to_string() }
2146 }
2147 }
2148}
2149
2150#[cfg(test)]
2151mod tests {
2152 use super::*;
2153
2154 #[test]
2155 fn test_simple_select() {
2156 let sql = select(["id", "name"]).from("users").to_sql();
2157 assert_eq!(sql, "SELECT id, name FROM users");
2158 }
2159
2160 #[test]
2161 fn test_select_star() {
2162 let sql = select([star()]).from("users").to_sql();
2163 assert_eq!(sql, "SELECT * FROM users");
2164 }
2165
2166 #[test]
2167 fn test_select_with_where() {
2168 let sql = select(["id", "name"])
2169 .from("users")
2170 .where_(col("age").gt(lit(18)))
2171 .to_sql();
2172 assert_eq!(sql, "SELECT id, name FROM users WHERE age > 18");
2173 }
2174
2175 #[test]
2176 fn test_select_with_join() {
2177 let sql = select(["u.id", "o.amount"])
2178 .from("users")
2179 .join("orders", col("u.id").eq(col("o.user_id")))
2180 .to_sql();
2181 assert_eq!(
2182 sql,
2183 "SELECT u.id, o.amount FROM users JOIN orders ON u.id = o.user_id"
2184 );
2185 }
2186
2187 #[test]
2188 fn test_select_with_group_by_having() {
2189 let sql = select([col("dept"), func("COUNT", [star()]).alias("cnt")])
2190 .from("employees")
2191 .group_by(["dept"])
2192 .having(func("COUNT", [star()]).gt(lit(5)))
2193 .to_sql();
2194 assert_eq!(
2195 sql,
2196 "SELECT dept, COUNT(*) AS cnt FROM employees GROUP BY dept HAVING COUNT(*) > 5"
2197 );
2198 }
2199
2200 #[test]
2201 fn test_select_with_order_limit_offset() {
2202 let sql = select(["id", "name"])
2203 .from("users")
2204 .order_by(["name"])
2205 .limit(10)
2206 .offset(20)
2207 .to_sql();
2208 assert_eq!(
2209 sql,
2210 "SELECT id, name FROM users ORDER BY name LIMIT 10 OFFSET 20"
2211 );
2212 }
2213
2214 #[test]
2215 fn test_select_distinct() {
2216 let sql = select(["name"]).from("users").distinct().to_sql();
2217 assert_eq!(sql, "SELECT DISTINCT name FROM users");
2218 }
2219
2220 #[test]
2221 fn test_insert_values() {
2222 let sql = insert_into("users")
2223 .columns(["id", "name"])
2224 .values([lit(1), lit("Alice")])
2225 .values([lit(2), lit("Bob")])
2226 .to_sql();
2227 assert_eq!(
2228 sql,
2229 "INSERT INTO users (id, name) VALUES (1, 'Alice'), (2, 'Bob')"
2230 );
2231 }
2232
2233 #[test]
2234 fn test_insert_select() {
2235 let sql = insert_into("archive")
2236 .columns(["id", "name"])
2237 .query(select(["id", "name"]).from("users"))
2238 .to_sql();
2239 assert_eq!(
2240 sql,
2241 "INSERT INTO archive (id, name) SELECT id, name FROM users"
2242 );
2243 }
2244
2245 #[test]
2246 fn test_update() {
2247 let sql = update("users")
2248 .set("name", lit("Bob"))
2249 .set("age", lit(30))
2250 .where_(col("id").eq(lit(1)))
2251 .to_sql();
2252 assert_eq!(
2253 sql,
2254 "UPDATE users SET name = 'Bob', age = 30 WHERE id = 1"
2255 );
2256 }
2257
2258 #[test]
2259 fn test_delete() {
2260 let sql = delete("users")
2261 .where_(col("id").eq(lit(1)))
2262 .to_sql();
2263 assert_eq!(sql, "DELETE FROM users WHERE id = 1");
2264 }
2265
2266 #[test]
2267 fn test_complex_where() {
2268 let sql = select(["id"])
2269 .from("users")
2270 .where_(
2271 col("age").gte(lit(18))
2272 .and(col("active").eq(boolean(true)))
2273 .and(col("name").like(lit("%test%"))),
2274 )
2275 .to_sql();
2276 assert_eq!(
2277 sql,
2278 "SELECT id FROM users WHERE age >= 18 AND active = TRUE AND name LIKE '%test%'"
2279 );
2280 }
2281
2282 #[test]
2283 fn test_in_list() {
2284 let sql = select(["id"])
2285 .from("users")
2286 .where_(col("status").in_list([lit("active"), lit("pending")]))
2287 .to_sql();
2288 assert_eq!(
2289 sql,
2290 "SELECT id FROM users WHERE status IN ('active', 'pending')"
2291 );
2292 }
2293
2294 #[test]
2295 fn test_between() {
2296 let sql = select(["id"])
2297 .from("orders")
2298 .where_(col("amount").between(lit(100), lit(500)))
2299 .to_sql();
2300 assert_eq!(
2301 sql,
2302 "SELECT id FROM orders WHERE amount BETWEEN 100 AND 500"
2303 );
2304 }
2305
2306 #[test]
2307 fn test_is_null() {
2308 let sql = select(["id"])
2309 .from("users")
2310 .where_(col("email").is_null())
2311 .to_sql();
2312 assert_eq!(sql, "SELECT id FROM users WHERE email IS NULL");
2313 }
2314
2315 #[test]
2316 fn test_arithmetic() {
2317 let sql = select([col("price").mul(col("quantity")).alias("total")])
2318 .from("items")
2319 .to_sql();
2320 assert_eq!(sql, "SELECT price * quantity AS total FROM items");
2321 }
2322
2323 #[test]
2324 fn test_cast() {
2325 let sql = select([col("id").cast("VARCHAR")])
2326 .from("users")
2327 .to_sql();
2328 assert_eq!(sql, "SELECT CAST(id AS VARCHAR) FROM users");
2329 }
2330
2331 #[test]
2332 fn test_from_starter() {
2333 let sql = from("users").select_cols(["id", "name"]).to_sql();
2334 assert_eq!(sql, "SELECT id, name FROM users");
2335 }
2336
2337 #[test]
2338 fn test_qualified_column() {
2339 let sql = select([col("u.id"), col("u.name")])
2340 .from("users")
2341 .to_sql();
2342 assert_eq!(sql, "SELECT u.id, u.name FROM users");
2343 }
2344
2345 #[test]
2346 fn test_not_condition() {
2347 let sql = select(["id"])
2348 .from("users")
2349 .where_(not(col("active").eq(boolean(true))))
2350 .to_sql();
2351 assert_eq!(sql, "SELECT id FROM users WHERE NOT active = TRUE");
2352 }
2353
2354 #[test]
2355 fn test_order_by_desc() {
2356 let sql = select(["id", "name"])
2357 .from("users")
2358 .order_by([col("name").desc()])
2359 .to_sql();
2360 assert_eq!(sql, "SELECT id, name FROM users ORDER BY name DESC");
2361 }
2362
2363 #[test]
2364 fn test_left_join() {
2365 let sql = select(["u.id", "o.amount"])
2366 .from("users")
2367 .left_join("orders", col("u.id").eq(col("o.user_id")))
2368 .to_sql();
2369 assert_eq!(
2370 sql,
2371 "SELECT u.id, o.amount FROM users LEFT JOIN orders ON u.id = o.user_id"
2372 );
2373 }
2374
2375 #[test]
2376 fn test_build_returns_expression() {
2377 let expr = select(["id"]).from("users").build();
2378 assert!(matches!(expr, Expression::Select(_)));
2379 }
2380
2381 #[test]
2382 fn test_expr_interop() {
2383 let age_check = col("age").gt(lit(18));
2385 let sql = select([col("id"), age_check.alias("is_adult")])
2386 .from("users")
2387 .to_sql();
2388 assert_eq!(sql, "SELECT id, age > 18 AS is_adult FROM users");
2389 }
2390
2391 #[test]
2394 fn test_sql_expr_simple() {
2395 let expr = sql_expr("age > 18");
2396 let sql = select(["id"])
2397 .from("users")
2398 .where_(expr)
2399 .to_sql();
2400 assert_eq!(sql, "SELECT id FROM users WHERE age > 18");
2401 }
2402
2403 #[test]
2404 fn test_sql_expr_compound() {
2405 let expr = sql_expr("a > 1 AND b < 10");
2406 let sql = select(["*"])
2407 .from("t")
2408 .where_(expr)
2409 .to_sql();
2410 assert_eq!(sql, "SELECT * FROM t WHERE a > 1 AND b < 10");
2411 }
2412
2413 #[test]
2414 fn test_sql_expr_function() {
2415 let expr = sql_expr("COALESCE(a, b, 0)");
2416 let sql = select([expr.alias("val")]).from("t").to_sql();
2417 assert_eq!(sql, "SELECT COALESCE(a, b, 0) AS val FROM t");
2418 }
2419
2420 #[test]
2421 fn test_condition_alias() {
2422 let cond = condition("x > 0");
2423 let sql = select(["*"]).from("t").where_(cond).to_sql();
2424 assert_eq!(sql, "SELECT * FROM t WHERE x > 0");
2425 }
2426
2427 #[test]
2430 fn test_ilike() {
2431 let sql = select(["id"])
2432 .from("users")
2433 .where_(col("name").ilike(lit("%test%")))
2434 .to_sql();
2435 assert_eq!(sql, "SELECT id FROM users WHERE name ILIKE '%test%'");
2436 }
2437
2438 #[test]
2439 fn test_rlike() {
2440 let sql = select(["id"])
2441 .from("users")
2442 .where_(col("name").rlike(lit("^[A-Z]")))
2443 .to_sql();
2444 assert_eq!(sql, "SELECT id FROM users WHERE REGEXP_LIKE(name, '^[A-Z]')");
2445 }
2446
2447 #[test]
2448 fn test_not_in() {
2449 let sql = select(["id"])
2450 .from("users")
2451 .where_(col("status").not_in([lit("deleted"), lit("banned")]))
2452 .to_sql();
2453 assert_eq!(
2454 sql,
2455 "SELECT id FROM users WHERE status NOT IN ('deleted', 'banned')"
2456 );
2457 }
2458
2459 #[test]
2462 fn test_case_searched() {
2463 let expr = case()
2464 .when(col("x").gt(lit(0)), lit("positive"))
2465 .when(col("x").eq(lit(0)), lit("zero"))
2466 .else_(lit("negative"))
2467 .build();
2468 let sql = select([expr.alias("label")]).from("t").to_sql();
2469 assert_eq!(
2470 sql,
2471 "SELECT CASE WHEN x > 0 THEN 'positive' WHEN x = 0 THEN 'zero' ELSE 'negative' END AS label FROM t"
2472 );
2473 }
2474
2475 #[test]
2476 fn test_case_simple() {
2477 let expr = case_of(col("status"))
2478 .when(lit(1), lit("active"))
2479 .when(lit(0), lit("inactive"))
2480 .build();
2481 let sql = select([expr.alias("status_label")]).from("t").to_sql();
2482 assert_eq!(
2483 sql,
2484 "SELECT CASE status WHEN 1 THEN 'active' WHEN 0 THEN 'inactive' END AS status_label FROM t"
2485 );
2486 }
2487
2488 #[test]
2489 fn test_case_no_else() {
2490 let expr = case()
2491 .when(col("x").gt(lit(0)), lit("yes"))
2492 .build();
2493 let sql = select([expr]).from("t").to_sql();
2494 assert_eq!(sql, "SELECT CASE WHEN x > 0 THEN 'yes' END FROM t");
2495 }
2496
2497 #[test]
2500 fn test_subquery_in_from() {
2501 let inner = select(["id", "name"]).from("users").where_(col("active").eq(boolean(true)));
2502 let outer = select(["sub.id"])
2503 .from_expr(subquery(inner, "sub"))
2504 .to_sql();
2505 assert_eq!(
2506 outer,
2507 "SELECT sub.id FROM (SELECT id, name FROM users WHERE active = TRUE) AS sub"
2508 );
2509 }
2510
2511 #[test]
2512 fn test_subquery_in_join() {
2513 let inner = select([col("user_id"), func("SUM", [col("amount")]).alias("total")])
2514 .from("orders")
2515 .group_by(["user_id"]);
2516 let sql = select(["u.name", "o.total"])
2517 .from("users")
2518 .join("orders", col("u.id").eq(col("o.user_id")))
2519 .to_sql();
2520 assert!(sql.contains("JOIN"));
2521 let _sub = subquery(inner, "o");
2523 }
2524
2525 #[test]
2528 fn test_union() {
2529 let sql = union(
2530 select(["id"]).from("a"),
2531 select(["id"]).from("b"),
2532 )
2533 .to_sql();
2534 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
2535 }
2536
2537 #[test]
2538 fn test_union_all() {
2539 let sql = union_all(
2540 select(["id"]).from("a"),
2541 select(["id"]).from("b"),
2542 )
2543 .to_sql();
2544 assert_eq!(sql, "SELECT id FROM a UNION ALL SELECT id FROM b");
2545 }
2546
2547 #[test]
2548 fn test_intersect_builder() {
2549 let sql = intersect(
2550 select(["id"]).from("a"),
2551 select(["id"]).from("b"),
2552 )
2553 .to_sql();
2554 assert_eq!(sql, "SELECT id FROM a INTERSECT SELECT id FROM b");
2555 }
2556
2557 #[test]
2558 fn test_except_builder() {
2559 let sql = except_(
2560 select(["id"]).from("a"),
2561 select(["id"]).from("b"),
2562 )
2563 .to_sql();
2564 assert_eq!(sql, "SELECT id FROM a EXCEPT SELECT id FROM b");
2565 }
2566
2567 #[test]
2568 fn test_union_with_order_limit() {
2569 let sql = union(
2570 select(["id"]).from("a"),
2571 select(["id"]).from("b"),
2572 )
2573 .order_by(["id"])
2574 .limit(10)
2575 .to_sql();
2576 assert!(sql.contains("UNION"));
2577 assert!(sql.contains("ORDER BY"));
2578 assert!(sql.contains("LIMIT"));
2579 }
2580
2581 #[test]
2582 fn test_select_builder_union() {
2583 let sql = select(["id"])
2584 .from("a")
2585 .union(select(["id"]).from("b"))
2586 .to_sql();
2587 assert_eq!(sql, "SELECT id FROM a UNION SELECT id FROM b");
2588 }
2589
2590 #[test]
2593 fn test_qualify() {
2594 let sql = select(["id", "name"])
2595 .from("users")
2596 .qualify(col("rn").eq(lit(1)))
2597 .to_sql();
2598 assert_eq!(
2599 sql,
2600 "SELECT id, name FROM users QUALIFY rn = 1"
2601 );
2602 }
2603
2604 #[test]
2605 fn test_right_join() {
2606 let sql = select(["u.id", "o.amount"])
2607 .from("users")
2608 .right_join("orders", col("u.id").eq(col("o.user_id")))
2609 .to_sql();
2610 assert_eq!(
2611 sql,
2612 "SELECT u.id, o.amount FROM users RIGHT JOIN orders ON u.id = o.user_id"
2613 );
2614 }
2615
2616 #[test]
2617 fn test_cross_join() {
2618 let sql = select(["a.x", "b.y"])
2619 .from("a")
2620 .cross_join("b")
2621 .to_sql();
2622 assert_eq!(sql, "SELECT a.x, b.y FROM a CROSS JOIN b");
2623 }
2624
2625 #[test]
2626 fn test_lateral_view() {
2627 let sql = select(["id", "col_val"])
2628 .from("t")
2629 .lateral_view(func("EXPLODE", [col("arr")]), "lv", ["col_val"])
2630 .to_sql();
2631 assert!(sql.contains("LATERAL VIEW"));
2632 assert!(sql.contains("EXPLODE"));
2633 }
2634
2635 #[test]
2636 fn test_window_clause() {
2637 let sql = select(["id"])
2638 .from("t")
2639 .window(
2640 "w",
2641 WindowDefBuilder::new()
2642 .partition_by(["dept"])
2643 .order_by(["salary"]),
2644 )
2645 .to_sql();
2646 assert!(sql.contains("WINDOW"));
2647 assert!(sql.contains("PARTITION BY"));
2648 }
2649
2650 #[test]
2653 fn test_xor() {
2654 let sql = select(["*"])
2655 .from("t")
2656 .where_(col("a").xor(col("b")))
2657 .to_sql();
2658 assert_eq!(sql, "SELECT * FROM t WHERE a XOR b");
2659 }
2660
2661 #[test]
2664 fn test_for_update() {
2665 let sql = select(["id"]).from("t").for_update().to_sql();
2666 assert_eq!(sql, "SELECT id FROM t FOR UPDATE");
2667 }
2668
2669 #[test]
2670 fn test_for_share() {
2671 let sql = select(["id"]).from("t").for_share().to_sql();
2672 assert_eq!(sql, "SELECT id FROM t FOR SHARE");
2673 }
2674
2675 #[test]
2678 fn test_hint() {
2679 let sql = select(["*"]).from("t").hint("FULL(t)").to_sql();
2680 assert!(sql.contains("FULL(t)"), "Expected hint in: {}", sql);
2681 }
2682
2683 #[test]
2686 fn test_ctas() {
2687 let expr = select(["*"]).from("t").ctas("new_table");
2688 let sql = Generator::sql(&expr).unwrap();
2689 assert_eq!(sql, "CREATE TABLE new_table AS SELECT * FROM t");
2690 }
2691
2692 #[test]
2695 fn test_merge_update_insert() {
2696 let sql = merge_into("target")
2697 .using("source", col("target.id").eq(col("source.id")))
2698 .when_matched_update(vec![("name", col("source.name"))])
2699 .when_not_matched_insert(
2700 &["id", "name"],
2701 vec![col("source.id"), col("source.name")],
2702 )
2703 .to_sql();
2704 assert!(sql.contains("MERGE INTO"), "Expected MERGE INTO in: {}", sql);
2705 assert!(sql.contains("USING"), "Expected USING in: {}", sql);
2706 assert!(sql.contains("WHEN MATCHED"), "Expected WHEN MATCHED in: {}", sql);
2707 assert!(sql.contains("UPDATE SET"), "Expected UPDATE SET in: {}", sql);
2708 assert!(
2709 sql.contains("WHEN NOT MATCHED"),
2710 "Expected WHEN NOT MATCHED in: {}",
2711 sql
2712 );
2713 assert!(sql.contains("INSERT"), "Expected INSERT in: {}", sql);
2714 }
2715
2716 #[test]
2717 fn test_merge_delete() {
2718 let sql = merge_into("target")
2719 .using("source", col("target.id").eq(col("source.id")))
2720 .when_matched_delete()
2721 .to_sql();
2722 assert!(sql.contains("MERGE INTO"), "Expected MERGE INTO in: {}", sql);
2723 assert!(sql.contains("WHEN MATCHED THEN DELETE"), "Expected WHEN MATCHED THEN DELETE in: {}", sql);
2724 }
2725
2726 #[test]
2727 fn test_merge_with_condition() {
2728 let sql = merge_into("target")
2729 .using("source", col("target.id").eq(col("source.id")))
2730 .when_matched_update_where(
2731 col("source.active").eq(boolean(true)),
2732 vec![("name", col("source.name"))],
2733 )
2734 .to_sql();
2735 assert!(sql.contains("MERGE INTO"), "Expected MERGE INTO in: {}", sql);
2736 assert!(sql.contains("AND source.active = TRUE"), "Expected condition in: {}", sql);
2737 }
2738}