1use crate::ast::{
52 BinaryOperator, DataType, Expr, FromClause, JoinClause, JoinType, OrderByItem, QuoteStyle,
53 SelectItem, SelectStatement, Statement, TableRef, TableSource,
54};
55use crate::dialects::Dialect;
56use crate::parser::parse;
57
58#[must_use]
77pub fn column(name: &str, table: Option<&str>) -> Expr {
78 Expr::Column {
79 table: table.map(String::from),
80 name: name.to_string(),
81 quote_style: QuoteStyle::None,
82 table_quote_style: QuoteStyle::None,
83 }
84}
85
86#[must_use]
101pub fn table(name: &str, schema: Option<&str>) -> TableRef {
102 TableRef {
103 catalog: None,
104 schema: schema.map(String::from),
105 name: name.to_string(),
106 alias: None,
107 name_quote_style: QuoteStyle::None,
108 }
109}
110
111#[must_use]
126pub fn table_full(name: &str, schema: Option<&str>, catalog: Option<&str>) -> TableRef {
127 TableRef {
128 catalog: catalog.map(String::from),
129 schema: schema.map(String::from),
130 name: name.to_string(),
131 alias: None,
132 name_quote_style: QuoteStyle::None,
133 }
134}
135
136#[must_use]
146pub fn literal<T: ToString>(value: T) -> Expr {
147 Expr::Number(value.to_string())
148}
149
150#[must_use]
160pub fn string_literal(value: &str) -> Expr {
161 Expr::StringLiteral(value.to_string())
162}
163
164#[must_use]
175pub fn boolean(value: bool) -> Expr {
176 Expr::Boolean(value)
177}
178
179#[must_use]
189pub fn null() -> Expr {
190 Expr::Null
191}
192
193#[must_use]
208pub fn cast(expr: Expr, data_type: DataType) -> Expr {
209 Expr::Cast {
210 expr: Box::new(expr),
211 data_type,
212 }
213}
214
215#[must_use]
240pub fn and_all<I>(conditions: I) -> Option<Expr>
241where
242 I: IntoIterator<Item = Expr>,
243{
244 let mut iter = conditions.into_iter();
245 let first = iter.next()?;
246 Some(iter.fold(first, |acc, cond| Expr::BinaryOp {
247 left: Box::new(acc),
248 op: BinaryOperator::And,
249 right: Box::new(cond),
250 }))
251}
252
253#[must_use]
278pub fn or_all<I>(conditions: I) -> Option<Expr>
279where
280 I: IntoIterator<Item = Expr>,
281{
282 let mut iter = conditions.into_iter();
283 let first = iter.next()?;
284 Some(iter.fold(first, |acc, cond| Expr::BinaryOp {
285 left: Box::new(acc),
286 op: BinaryOperator::Or,
287 right: Box::new(cond),
288 }))
289}
290
291#[must_use]
301pub fn not(expr: Expr) -> Expr {
302 Expr::UnaryOp {
303 op: crate::ast::UnaryOperator::Not,
304 expr: Box::new(expr),
305 }
306}
307
308#[must_use]
323pub fn func(name: &str, args: Vec<Expr>) -> Expr {
324 Expr::Function {
325 name: name.to_string(),
326 args,
327 distinct: false,
328 filter: None,
329 over: None,
330 }
331}
332
333#[must_use]
343pub fn func_distinct(name: &str, args: Vec<Expr>) -> Expr {
344 Expr::Function {
345 name: name.to_string(),
346 args,
347 distinct: true,
348 filter: None,
349 over: None,
350 }
351}
352
353#[must_use]
363pub fn star() -> Expr {
364 Expr::Star
365}
366
367#[must_use]
377pub fn qualified_star(table: &str) -> Expr {
378 Expr::QualifiedWildcard {
379 table: table.to_string(),
380 }
381}
382
383#[must_use]
394pub fn subquery(statement: Statement) -> Expr {
395 Expr::Subquery(Box::new(statement))
396}
397
398#[must_use]
409pub fn exists(statement: Statement, negated: bool) -> Expr {
410 Expr::Exists {
411 subquery: Box::new(statement),
412 negated,
413 }
414}
415
416#[must_use]
426pub fn alias(expr: Expr, name: &str) -> Expr {
427 Expr::Alias {
428 expr: Box::new(expr),
429 name: name.to_string(),
430 }
431}
432
433#[must_use]
439pub fn eq(left: Expr, right: Expr) -> Expr {
440 Expr::BinaryOp {
441 left: Box::new(left),
442 op: BinaryOperator::Eq,
443 right: Box::new(right),
444 }
445}
446
447#[must_use]
449pub fn neq(left: Expr, right: Expr) -> Expr {
450 Expr::BinaryOp {
451 left: Box::new(left),
452 op: BinaryOperator::Neq,
453 right: Box::new(right),
454 }
455}
456
457#[must_use]
459pub fn lt(left: Expr, right: Expr) -> Expr {
460 Expr::BinaryOp {
461 left: Box::new(left),
462 op: BinaryOperator::Lt,
463 right: Box::new(right),
464 }
465}
466
467#[must_use]
469pub fn lte(left: Expr, right: Expr) -> Expr {
470 Expr::BinaryOp {
471 left: Box::new(left),
472 op: BinaryOperator::LtEq,
473 right: Box::new(right),
474 }
475}
476
477#[must_use]
479pub fn gt(left: Expr, right: Expr) -> Expr {
480 Expr::BinaryOp {
481 left: Box::new(left),
482 op: BinaryOperator::Gt,
483 right: Box::new(right),
484 }
485}
486
487#[must_use]
489pub fn gte(left: Expr, right: Expr) -> Expr {
490 Expr::BinaryOp {
491 left: Box::new(left),
492 op: BinaryOperator::GtEq,
493 right: Box::new(right),
494 }
495}
496
497#[must_use]
499pub fn is_null(expr: Expr) -> Expr {
500 Expr::IsNull {
501 expr: Box::new(expr),
502 negated: false,
503 }
504}
505
506#[must_use]
508pub fn is_not_null(expr: Expr) -> Expr {
509 Expr::IsNull {
510 expr: Box::new(expr),
511 negated: true,
512 }
513}
514
515#[must_use]
517pub fn between(expr: Expr, low: Expr, high: Expr) -> Expr {
518 Expr::Between {
519 expr: Box::new(expr),
520 low: Box::new(low),
521 high: Box::new(high),
522 negated: false,
523 }
524}
525
526#[must_use]
528pub fn in_list(expr: Expr, list: Vec<Expr>) -> Expr {
529 Expr::InList {
530 expr: Box::new(expr),
531 list,
532 negated: false,
533 }
534}
535
536#[must_use]
538pub fn not_in_list(expr: Expr, list: Vec<Expr>) -> Expr {
539 Expr::InList {
540 expr: Box::new(expr),
541 list,
542 negated: true,
543 }
544}
545
546#[must_use]
548pub fn in_subquery(expr: Expr, query: Statement) -> Expr {
549 Expr::InSubquery {
550 expr: Box::new(expr),
551 subquery: Box::new(query),
552 negated: false,
553 }
554}
555
556#[must_use]
558pub fn like(expr: Expr, pattern: Expr) -> Expr {
559 Expr::Like {
560 expr: Box::new(expr),
561 pattern: Box::new(pattern),
562 negated: false,
563 escape: None,
564 }
565}
566
567#[must_use]
573pub fn add(left: Expr, right: Expr) -> Expr {
574 Expr::BinaryOp {
575 left: Box::new(left),
576 op: BinaryOperator::Plus,
577 right: Box::new(right),
578 }
579}
580
581#[must_use]
583pub fn sub(left: Expr, right: Expr) -> Expr {
584 Expr::BinaryOp {
585 left: Box::new(left),
586 op: BinaryOperator::Minus,
587 right: Box::new(right),
588 }
589}
590
591#[must_use]
593pub fn mul(left: Expr, right: Expr) -> Expr {
594 Expr::BinaryOp {
595 left: Box::new(left),
596 op: BinaryOperator::Multiply,
597 right: Box::new(right),
598 }
599}
600
601#[must_use]
603pub fn div(left: Expr, right: Expr) -> Expr {
604 Expr::BinaryOp {
605 left: Box::new(left),
606 op: BinaryOperator::Divide,
607 right: Box::new(right),
608 }
609}
610
611#[must_use]
628pub fn parse_expr(sql: &str) -> Option<Expr> {
629 parse_expr_dialect(sql, Dialect::Ansi)
630}
631
632#[must_use]
634pub fn parse_expr_dialect(sql: &str, dialect: Dialect) -> Option<Expr> {
635 let query = format!("SELECT {sql}");
637 match parse(&query, dialect) {
638 Ok(Statement::Select(select)) => {
639 if let Some(SelectItem::Expr { expr, .. }) = select.columns.first() {
640 Some(expr.clone())
641 } else {
642 None
643 }
644 }
645 _ => None,
646 }
647}
648
649#[must_use]
659pub fn parse_condition(sql: &str) -> Option<Expr> {
660 parse_condition_dialect(sql, Dialect::Ansi)
661}
662
663#[must_use]
665pub fn parse_condition_dialect(sql: &str, dialect: Dialect) -> Option<Expr> {
666 let query = format!("SELECT 1 WHERE {sql}");
668 match parse(&query, dialect) {
669 Ok(Statement::Select(select)) => select.where_clause,
670 _ => None,
671 }
672}
673
674#[derive(Debug, Clone)]
691pub struct ConditionBuilder {
692 expr: Option<Expr>,
693 dialect: Dialect,
694}
695
696impl ConditionBuilder {
697 #[must_use]
699 pub fn new(condition: &str) -> Self {
700 Self::new_with_dialect(condition, Dialect::Ansi)
701 }
702
703 #[must_use]
705 pub fn new_with_dialect(condition: &str, dialect: Dialect) -> Self {
706 Self {
707 expr: parse_condition_dialect(condition, dialect),
708 dialect,
709 }
710 }
711
712 #[must_use]
714 pub fn from_expr(expr: Expr) -> Self {
715 Self {
716 expr: Some(expr),
717 dialect: Dialect::Ansi,
718 }
719 }
720
721 #[must_use]
723 pub fn and(self, condition: &str) -> Self {
724 let dialect = self.dialect;
725 self.and_expr(parse_condition_dialect(condition, dialect))
726 }
727
728 #[must_use]
730 pub fn and_expr(self, other: Option<Expr>) -> Self {
731 let expr = match (self.expr, other) {
732 (Some(left), Some(right)) => Some(Expr::BinaryOp {
733 left: Box::new(left),
734 op: BinaryOperator::And,
735 right: Box::new(right),
736 }),
737 (Some(e), None) | (None, Some(e)) => Some(e),
738 (None, None) => None,
739 };
740 Self {
741 expr,
742 dialect: self.dialect,
743 }
744 }
745
746 #[must_use]
748 pub fn or(self, condition: &str) -> Self {
749 let dialect = self.dialect;
750 self.or_expr(parse_condition_dialect(condition, dialect))
751 }
752
753 #[must_use]
755 pub fn or_expr(self, other: Option<Expr>) -> Self {
756 let expr = match (self.expr, other) {
757 (Some(left), Some(right)) => Some(Expr::BinaryOp {
758 left: Box::new(left),
759 op: BinaryOperator::Or,
760 right: Box::new(right),
761 }),
762 (Some(e), None) | (None, Some(e)) => Some(e),
763 (None, None) => None,
764 };
765 Self {
766 expr,
767 dialect: self.dialect,
768 }
769 }
770
771 #[must_use]
773 pub fn not(self) -> Self {
774 let expr = self.expr.map(|e| Expr::UnaryOp {
775 op: crate::ast::UnaryOperator::Not,
776 expr: Box::new(e),
777 });
778 Self {
779 expr,
780 dialect: self.dialect,
781 }
782 }
783
784 #[must_use]
786 pub fn build(self) -> Option<Expr> {
787 self.expr
788 }
789}
790
791#[must_use]
801pub fn condition(cond: &str) -> ConditionBuilder {
802 ConditionBuilder::new(cond)
803}
804
805#[must_use]
807pub fn condition_dialect(cond: &str, dialect: Dialect) -> ConditionBuilder {
808 ConditionBuilder::new_with_dialect(cond, dialect)
809}
810
811#[derive(Debug, Clone)]
830pub struct SelectBuilder {
831 statement: SelectStatement,
832 dialect: Dialect,
833}
834
835impl Default for SelectBuilder {
836 fn default() -> Self {
837 Self::new()
838 }
839}
840
841impl SelectBuilder {
842 #[must_use]
844 pub fn new() -> Self {
845 Self {
846 statement: SelectStatement {
847 ctes: Vec::new(),
848 distinct: false,
849 top: None,
850 columns: Vec::new(),
851 from: None,
852 joins: Vec::new(),
853 where_clause: None,
854 group_by: Vec::new(),
855 having: None,
856 order_by: Vec::new(),
857 limit: None,
858 offset: None,
859 fetch_first: None,
860 qualify: None,
861 window_definitions: Vec::new(),
862 },
863 dialect: Dialect::Ansi,
864 }
865 }
866
867 #[must_use]
869 pub fn dialect(mut self, dialect: Dialect) -> Self {
870 self.dialect = dialect;
871 self
872 }
873
874 #[must_use]
878 pub fn columns(mut self, cols: &[&str]) -> Self {
879 for col in cols {
880 if let Some(expr) = parse_expr_dialect(col, self.dialect) {
881 self.statement.columns.push(SelectItem::Expr { expr, alias: None });
882 }
883 }
884 self
885 }
886
887 #[must_use]
889 pub fn column_expr(mut self, expr: Expr, alias: Option<&str>) -> Self {
890 self.statement.columns.push(SelectItem::Expr {
891 expr,
892 alias: alias.map(String::from),
893 });
894 self
895 }
896
897 #[must_use]
899 pub fn all(mut self) -> Self {
900 self.statement.columns.push(SelectItem::Wildcard);
901 self
902 }
903
904 #[must_use]
906 pub fn all_from(mut self, table: &str) -> Self {
907 self.statement
908 .columns
909 .push(SelectItem::QualifiedWildcard { table: table.to_string() });
910 self
911 }
912
913 #[must_use]
915 pub fn distinct(mut self) -> Self {
916 self.statement.distinct = true;
917 self
918 }
919
920 #[must_use]
922 pub fn from(mut self, table_name: &str) -> Self {
923 self.statement.from = Some(FromClause {
924 source: TableSource::Table(table(table_name, None)),
925 });
926 self
927 }
928
929 #[must_use]
931 pub fn from_table(mut self, table_ref: TableRef) -> Self {
932 self.statement.from = Some(FromClause {
933 source: TableSource::Table(table_ref),
934 });
935 self
936 }
937
938 #[must_use]
940 pub fn from_subquery(mut self, query: Statement, alias: &str) -> Self {
941 self.statement.from = Some(FromClause {
942 source: TableSource::Subquery {
943 query: Box::new(query),
944 alias: Some(alias.to_string()),
945 },
946 });
947 self
948 }
949
950 #[must_use]
952 pub fn join(self, table_name: &str, on: &str) -> Self {
953 self.join_type(table_name, on, JoinType::Inner)
954 }
955
956 #[must_use]
958 pub fn left_join(self, table_name: &str, on: &str) -> Self {
959 self.join_type(table_name, on, JoinType::Left)
960 }
961
962 #[must_use]
964 pub fn right_join(self, table_name: &str, on: &str) -> Self {
965 self.join_type(table_name, on, JoinType::Right)
966 }
967
968 #[must_use]
970 pub fn full_join(self, table_name: &str, on: &str) -> Self {
971 self.join_type(table_name, on, JoinType::Full)
972 }
973
974 #[must_use]
976 pub fn cross_join(mut self, table_name: &str) -> Self {
977 self.statement.joins.push(JoinClause {
978 join_type: JoinType::Cross,
979 table: TableSource::Table(table(table_name, None)),
980 on: None,
981 using: Vec::new(),
982 });
983 self
984 }
985
986 #[must_use]
988 fn join_type(mut self, table_name: &str, on: &str, join_type: JoinType) -> Self {
989 let on_expr = parse_condition_dialect(on, self.dialect);
990 self.statement.joins.push(JoinClause {
991 join_type,
992 table: TableSource::Table(table(table_name, None)),
993 on: on_expr,
994 using: Vec::new(),
995 });
996 self
997 }
998
999 #[must_use]
1001 pub fn join_using(mut self, table_name: &str, columns: &[&str], join_type: JoinType) -> Self {
1002 self.statement.joins.push(JoinClause {
1003 join_type,
1004 table: TableSource::Table(table(table_name, None)),
1005 on: None,
1006 using: columns.iter().map(|s| s.to_string()).collect(),
1007 });
1008 self
1009 }
1010
1011 #[must_use]
1013 pub fn join_subquery(
1014 mut self,
1015 query: Statement,
1016 alias: &str,
1017 on: &str,
1018 join_type: JoinType,
1019 ) -> Self {
1020 let on_expr = parse_condition_dialect(on, self.dialect);
1021 self.statement.joins.push(JoinClause {
1022 join_type,
1023 table: TableSource::Subquery {
1024 query: Box::new(query),
1025 alias: Some(alias.to_string()),
1026 },
1027 on: on_expr,
1028 using: Vec::new(),
1029 });
1030 self
1031 }
1032
1033 #[must_use]
1035 pub fn where_clause(mut self, condition: &str) -> Self {
1036 self.statement.where_clause = parse_condition_dialect(condition, self.dialect);
1037 self
1038 }
1039
1040 #[must_use]
1042 pub fn where_expr(mut self, expr: Expr) -> Self {
1043 self.statement.where_clause = Some(expr);
1044 self
1045 }
1046
1047 #[must_use]
1049 pub fn and_where(mut self, condition: &str) -> Self {
1050 let new_cond = parse_condition_dialect(condition, self.dialect);
1051 self.statement.where_clause = match (self.statement.where_clause, new_cond) {
1052 (Some(existing), Some(new)) => Some(Expr::BinaryOp {
1053 left: Box::new(existing),
1054 op: BinaryOperator::And,
1055 right: Box::new(new),
1056 }),
1057 (Some(e), None) | (None, Some(e)) => Some(e),
1058 (None, None) => None,
1059 };
1060 self
1061 }
1062
1063 #[must_use]
1065 pub fn or_where(mut self, condition: &str) -> Self {
1066 let new_cond = parse_condition_dialect(condition, self.dialect);
1067 self.statement.where_clause = match (self.statement.where_clause, new_cond) {
1068 (Some(existing), Some(new)) => Some(Expr::BinaryOp {
1069 left: Box::new(existing),
1070 op: BinaryOperator::Or,
1071 right: Box::new(new),
1072 }),
1073 (Some(e), None) | (None, Some(e)) => Some(e),
1074 (None, None) => None,
1075 };
1076 self
1077 }
1078
1079 #[must_use]
1081 pub fn group_by(mut self, exprs: &[&str]) -> Self {
1082 self.statement.group_by = exprs
1083 .iter()
1084 .filter_map(|e| parse_expr_dialect(e, self.dialect))
1085 .collect();
1086 self
1087 }
1088
1089 #[must_use]
1091 pub fn add_group_by(mut self, expr: &str) -> Self {
1092 if let Some(e) = parse_expr_dialect(expr, self.dialect) {
1093 self.statement.group_by.push(e);
1094 }
1095 self
1096 }
1097
1098 #[must_use]
1100 pub fn having(mut self, condition: &str) -> Self {
1101 self.statement.having = parse_condition_dialect(condition, self.dialect);
1102 self
1103 }
1104
1105 #[must_use]
1107 pub fn order_by(mut self, exprs: &[&str]) -> Self {
1108 self.statement.order_by = exprs
1109 .iter()
1110 .filter_map(|e| parse_order_by_item(e, self.dialect))
1111 .collect();
1112 self
1113 }
1114
1115 #[must_use]
1117 pub fn add_order_by(mut self, expr: &str) -> Self {
1118 if let Some(item) = parse_order_by_item(expr, self.dialect) {
1119 self.statement.order_by.push(item);
1120 }
1121 self
1122 }
1123
1124 #[must_use]
1126 pub fn add_order_by_expr(mut self, expr: Expr, ascending: bool, nulls_first: Option<bool>) -> Self {
1127 self.statement.order_by.push(OrderByItem {
1128 expr,
1129 ascending,
1130 nulls_first,
1131 });
1132 self
1133 }
1134
1135 #[must_use]
1137 pub fn limit(mut self, n: i64) -> Self {
1138 self.statement.limit = Some(Expr::Number(n.to_string()));
1139 self
1140 }
1141
1142 #[must_use]
1144 pub fn limit_expr(mut self, expr: Expr) -> Self {
1145 self.statement.limit = Some(expr);
1146 self
1147 }
1148
1149 #[must_use]
1151 pub fn offset(mut self, n: i64) -> Self {
1152 self.statement.offset = Some(Expr::Number(n.to_string()));
1153 self
1154 }
1155
1156 #[must_use]
1158 pub fn offset_expr(mut self, expr: Expr) -> Self {
1159 self.statement.offset = Some(expr);
1160 self
1161 }
1162
1163 #[must_use]
1165 pub fn top(mut self, n: i64) -> Self {
1166 self.statement.top = Some(Box::new(Expr::Number(n.to_string())));
1167 self
1168 }
1169
1170 #[must_use]
1172 pub fn qualify(mut self, condition: &str) -> Self {
1173 self.statement.qualify = parse_condition_dialect(condition, self.dialect);
1174 self
1175 }
1176
1177 #[must_use]
1179 pub fn build(self) -> Statement {
1180 Statement::Select(self.statement)
1181 }
1182
1183 #[must_use]
1185 pub fn build_select(self) -> SelectStatement {
1186 self.statement
1187 }
1188}
1189
1190#[must_use]
1200pub fn select(columns: &[&str]) -> SelectBuilder {
1201 SelectBuilder::new().columns(columns)
1202}
1203
1204#[must_use]
1214pub fn select_all() -> SelectBuilder {
1215 SelectBuilder::new().all()
1216}
1217
1218#[must_use]
1228pub fn select_distinct(columns: &[&str]) -> SelectBuilder {
1229 SelectBuilder::new().distinct().columns(columns)
1230}
1231
1232impl SelectStatement {
1237 pub fn add_select(&mut self, expr_str: &str) {
1248 self.add_select_dialect(expr_str, Dialect::Ansi);
1249 }
1250
1251 pub fn add_select_dialect(&mut self, expr_str: &str, dialect: Dialect) {
1253 if let Some(expr) = parse_expr_dialect(expr_str, dialect) {
1254 self.columns.push(SelectItem::Expr { expr, alias: None });
1255 }
1256 }
1257
1258 pub fn add_select_expr(&mut self, expr: Expr, alias: Option<&str>) {
1260 self.columns.push(SelectItem::Expr {
1261 expr,
1262 alias: alias.map(String::from),
1263 });
1264 }
1265
1266 pub fn add_where(&mut self, condition: &str) {
1278 self.add_where_dialect(condition, Dialect::Ansi);
1279 }
1280
1281 pub fn add_where_dialect(&mut self, condition: &str, dialect: Dialect) {
1283 let new_cond = parse_condition_dialect(condition, dialect);
1284 self.where_clause = match (self.where_clause.take(), new_cond) {
1285 (Some(existing), Some(new)) => Some(Expr::BinaryOp {
1286 left: Box::new(existing),
1287 op: BinaryOperator::And,
1288 right: Box::new(new),
1289 }),
1290 (Some(e), None) | (None, Some(e)) => Some(e),
1291 (None, None) => None,
1292 };
1293 }
1294
1295 pub fn add_where_expr(&mut self, expr: Expr) {
1297 self.where_clause = match self.where_clause.take() {
1298 Some(existing) => Some(Expr::BinaryOp {
1299 left: Box::new(existing),
1300 op: BinaryOperator::And,
1301 right: Box::new(expr),
1302 }),
1303 None => Some(expr),
1304 };
1305 }
1306
1307 pub fn add_join(&mut self, table_name: &str, on: &str, join_type: JoinType) {
1319 self.add_join_dialect(table_name, on, join_type, Dialect::Ansi);
1320 }
1321
1322 pub fn add_join_dialect(
1324 &mut self,
1325 table_name: &str,
1326 on: &str,
1327 join_type: JoinType,
1328 dialect: Dialect,
1329 ) {
1330 let on_expr = parse_condition_dialect(on, dialect);
1331 self.joins.push(JoinClause {
1332 join_type,
1333 table: TableSource::Table(table(table_name, None)),
1334 on: on_expr,
1335 using: Vec::new(),
1336 });
1337 }
1338
1339 pub fn add_join_subquery(
1341 &mut self,
1342 query: Statement,
1343 alias: &str,
1344 on: &str,
1345 join_type: JoinType,
1346 ) {
1347 self.add_join_subquery_dialect(query, alias, on, join_type, Dialect::Ansi);
1348 }
1349
1350 pub fn add_join_subquery_dialect(
1352 &mut self,
1353 query: Statement,
1354 alias: &str,
1355 on: &str,
1356 join_type: JoinType,
1357 dialect: Dialect,
1358 ) {
1359 let on_expr = parse_condition_dialect(on, dialect);
1360 self.joins.push(JoinClause {
1361 join_type,
1362 table: TableSource::Subquery {
1363 query: Box::new(query),
1364 alias: Some(alias.to_string()),
1365 },
1366 on: on_expr,
1367 using: Vec::new(),
1368 });
1369 }
1370
1371 #[must_use]
1382 pub fn as_subquery(self, alias: &str) -> TableSource {
1383 TableSource::Subquery {
1384 query: Box::new(Statement::Select(self)),
1385 alias: Some(alias.to_string()),
1386 }
1387 }
1388}
1389
1390fn parse_order_by_item(s: &str, dialect: Dialect) -> Option<OrderByItem> {
1396 let s = s.trim();
1397 let upper = s.to_uppercase();
1398
1399 let nulls_first = if upper.contains("NULLS FIRST") {
1401 Some(true)
1402 } else if upper.contains("NULLS LAST") {
1403 Some(false)
1404 } else {
1405 None
1406 };
1407
1408 let s = s
1410 .replace("NULLS FIRST", "")
1411 .replace("NULLS LAST", "")
1412 .replace("nulls first", "")
1413 .replace("nulls last", "");
1414 let s = s.trim();
1415
1416 let (expr_str, ascending) = if s.to_uppercase().ends_with(" DESC") {
1418 (&s[..s.len() - 5], false)
1419 } else if s.to_uppercase().ends_with(" ASC") {
1420 (&s[..s.len() - 4], true)
1421 } else {
1422 (s, true)
1423 };
1424
1425 parse_expr_dialect(expr_str.trim(), dialect).map(|expr| OrderByItem {
1426 expr,
1427 ascending,
1428 nulls_first,
1429 })
1430}
1431
1432#[cfg(test)]
1433mod tests {
1434 use super::*;
1435 use crate::generate;
1436
1437 #[test]
1438 fn test_column() {
1439 let col = column("name", None);
1440 assert!(matches!(col, Expr::Column { name, table, .. } if name == "name" && table.is_none()));
1441
1442 let qualified = column("id", Some("users"));
1443 assert!(matches!(qualified, Expr::Column { name, table, .. }
1444 if name == "id" && table == Some("users".to_string())));
1445 }
1446
1447 #[test]
1448 fn test_table() {
1449 let tbl = table("users", None);
1450 assert_eq!(tbl.name, "users");
1451 assert!(tbl.schema.is_none());
1452
1453 let qualified = table("orders", Some("public"));
1454 assert_eq!(qualified.name, "orders");
1455 assert_eq!(qualified.schema, Some("public".to_string()));
1456 }
1457
1458 #[test]
1459 fn test_literals() {
1460 assert!(matches!(literal(42), Expr::Number(n) if n == "42"));
1461 assert!(matches!(string_literal("hello"), Expr::StringLiteral(s) if s == "hello"));
1462 assert!(matches!(boolean(true), Expr::Boolean(true)));
1463 assert!(matches!(null(), Expr::Null));
1464 }
1465
1466 #[test]
1467 fn test_cast() {
1468 let col = column("id", None);
1469 let casted = cast(col, DataType::BigInt);
1470 assert!(matches!(casted, Expr::Cast { data_type: DataType::BigInt, .. }));
1471 }
1472
1473 #[test]
1474 fn test_and_all() {
1475 let cond1 = eq(column("x", None), literal(1));
1476 let cond2 = eq(column("y", None), literal(2));
1477
1478 let combined = and_all(vec![cond1, cond2]).unwrap();
1479 assert!(matches!(combined, Expr::BinaryOp { op: BinaryOperator::And, .. }));
1480
1481 assert!(and_all(Vec::<Expr>::new()).is_none());
1483 }
1484
1485 #[test]
1486 fn test_or_all() {
1487 let cond1 = eq(column("x", None), literal(1));
1488 let cond2 = eq(column("y", None), literal(2));
1489
1490 let combined = or_all(vec![cond1, cond2]).unwrap();
1491 assert!(matches!(combined, Expr::BinaryOp { op: BinaryOperator::Or, .. }));
1492 }
1493
1494 #[test]
1495 fn test_parse_expr() {
1496 let expr = parse_expr("x + 1").unwrap();
1497 assert!(matches!(expr, Expr::BinaryOp { op: BinaryOperator::Plus, .. }));
1498 }
1499
1500 #[test]
1501 fn test_parse_condition() {
1502 let cond = parse_condition("x > 1 AND y < 10").unwrap();
1503 assert!(matches!(cond, Expr::BinaryOp { op: BinaryOperator::And, .. }));
1504 }
1505
1506 #[test]
1507 fn test_condition_builder() {
1508 let cond = condition("x = 1").and("y = 2").or("z = 3").build();
1509 assert!(cond.is_some());
1510 }
1511
1512 #[test]
1513 fn test_condition_builder_not() {
1514 let cond = condition("x = 1").not().build().unwrap();
1515 assert!(matches!(cond, Expr::UnaryOp { op: crate::ast::UnaryOperator::Not, .. }));
1516 }
1517
1518 #[test]
1519 fn test_select_builder_basic() {
1520 let query = select(&["a", "b"]).from("users").build();
1521 let sql = generate(&query, Dialect::Ansi);
1522 assert!(sql.contains("SELECT"));
1523 assert!(sql.contains("a"));
1524 assert!(sql.contains("b"));
1525 assert!(sql.contains("FROM users"));
1526 }
1527
1528 #[test]
1529 fn test_select_builder_where() {
1530 let query = select(&["*"])
1531 .from("users")
1532 .where_clause("active = true")
1533 .build();
1534 let sql = generate(&query, Dialect::Ansi);
1535 assert!(sql.contains("WHERE"));
1536 }
1537
1538 #[test]
1539 fn test_select_builder_join() {
1540 let query = select(&["u.name", "o.total"])
1541 .from("users")
1542 .join("orders", "users.id = orders.user_id")
1543 .build();
1544 let sql = generate(&query, Dialect::Ansi);
1545 assert!(sql.contains("JOIN"));
1546 }
1547
1548 #[test]
1549 fn test_select_builder_group_by() {
1550 let query = select(&["category", "COUNT(*)"])
1551 .from("products")
1552 .group_by(&["category"])
1553 .having("COUNT(*) > 5")
1554 .build();
1555 let sql = generate(&query, Dialect::Ansi);
1556 assert!(sql.contains("GROUP BY"));
1557 assert!(sql.contains("HAVING"));
1558 }
1559
1560 #[test]
1561 fn test_select_builder_order_limit() {
1562 let query = select(&["*"])
1563 .from("users")
1564 .order_by(&["created_at DESC"])
1565 .limit(10)
1566 .offset(5)
1567 .build();
1568 let sql = generate(&query, Dialect::Ansi);
1569 assert!(sql.contains("ORDER BY"));
1570 assert!(sql.contains("LIMIT 10"));
1571 assert!(sql.contains("OFFSET 5"));
1572 }
1573
1574 #[test]
1575 fn test_select_builder_distinct() {
1576 let query = select_distinct(&["category"]).from("products").build();
1577 let sql = generate(&query, Dialect::Ansi);
1578 assert!(sql.contains("SELECT DISTINCT"));
1579 }
1580
1581 #[test]
1582 fn test_select_all() {
1583 let query = select_all().from("users").build();
1584 let sql = generate(&query, Dialect::Ansi);
1585 assert!(sql.contains("SELECT *"));
1586 }
1587
1588 #[test]
1589 fn test_mutation_add_select() {
1590 let mut stmt = select(&["a"]).from("t").build_select();
1591 stmt.add_select("b");
1592 assert_eq!(stmt.columns.len(), 2);
1593 }
1594
1595 #[test]
1596 fn test_mutation_add_where() {
1597 let mut stmt = select(&["*"]).from("t").build_select();
1598 stmt.add_where("x > 1");
1599 stmt.add_where("y < 10");
1600 assert!(stmt.where_clause.is_some());
1602 }
1603
1604 #[test]
1605 fn test_mutation_add_join() {
1606 let mut stmt = select(&["*"]).from("users").build_select();
1607 stmt.add_join("orders", "users.id = orders.user_id", JoinType::Inner);
1608 assert_eq!(stmt.joins.len(), 1);
1609 }
1610
1611 #[test]
1612 fn test_as_subquery() {
1613 let inner = select(&["id"]).from("users").build_select();
1614 let source = inner.as_subquery("u");
1615 assert!(matches!(source, TableSource::Subquery { alias: Some(a), .. } if a == "u"));
1616 }
1617
1618 #[test]
1619 fn test_comparison_helpers() {
1620 let e = eq(column("a", None), literal(1));
1621 assert!(matches!(e, Expr::BinaryOp { op: BinaryOperator::Eq, .. }));
1622
1623 let e = neq(column("a", None), literal(1));
1624 assert!(matches!(e, Expr::BinaryOp { op: BinaryOperator::Neq, .. }));
1625
1626 let e = lt(column("a", None), literal(1));
1627 assert!(matches!(e, Expr::BinaryOp { op: BinaryOperator::Lt, .. }));
1628
1629 let e = gt(column("a", None), literal(1));
1630 assert!(matches!(e, Expr::BinaryOp { op: BinaryOperator::Gt, .. }));
1631 }
1632
1633 #[test]
1634 fn test_arithmetic_helpers() {
1635 let e = add(column("a", None), literal(1));
1636 assert!(matches!(e, Expr::BinaryOp { op: BinaryOperator::Plus, .. }));
1637
1638 let e = mul(column("a", None), literal(2));
1639 assert!(matches!(e, Expr::BinaryOp { op: BinaryOperator::Multiply, .. }));
1640 }
1641
1642 #[test]
1643 fn test_is_null_helpers() {
1644 let e = is_null(column("a", None));
1645 assert!(matches!(e, Expr::IsNull { negated: false, .. }));
1646
1647 let e = is_not_null(column("a", None));
1648 assert!(matches!(e, Expr::IsNull { negated: true, .. }));
1649 }
1650
1651 #[test]
1652 fn test_between() {
1653 let e = between(column("x", None), literal(1), literal(10));
1654 assert!(matches!(e, Expr::Between { negated: false, .. }));
1655 }
1656
1657 #[test]
1658 fn test_in_list() {
1659 let e = in_list(column("status", None), vec![string_literal("active"), string_literal("pending")]);
1660 assert!(matches!(e, Expr::InList { negated: false, .. }));
1661 }
1662
1663 #[test]
1664 fn test_like() {
1665 let e = like(column("name", None), string_literal("%John%"));
1666 assert!(matches!(e, Expr::Like { negated: false, .. }));
1667 }
1668
1669 #[test]
1670 fn test_func() {
1671 let f = func("UPPER", vec![column("name", None)]);
1672 assert!(matches!(f, Expr::Function { name, distinct: false, .. } if name == "UPPER"));
1673 }
1674
1675 #[test]
1676 fn test_func_distinct() {
1677 let f = func_distinct("COUNT", vec![column("id", None)]);
1678 assert!(matches!(f, Expr::Function { name, distinct: true, .. } if name == "COUNT"));
1679 }
1680
1681 #[test]
1682 fn test_alias() {
1683 let e = alias(column("first_name", None), "name");
1684 assert!(matches!(e, Expr::Alias { name, .. } if name == "name"));
1685 }
1686
1687 #[test]
1688 fn test_subquery_and_exists() {
1689 let inner = select(&["1"]).from("users").where_clause("id = 1").build();
1690 let sub = subquery(inner.clone());
1691 assert!(matches!(sub, Expr::Subquery(_)));
1692
1693 let ex = exists(inner, false);
1694 assert!(matches!(ex, Expr::Exists { negated: false, .. }));
1695 }
1696
1697 #[test]
1698 fn test_star_and_qualified_star() {
1699 let s = star();
1700 assert!(matches!(s, Expr::Star));
1701
1702 let qs = qualified_star("users");
1703 assert!(matches!(qs, Expr::QualifiedWildcard { table } if table == "users"));
1704 }
1705
1706 #[test]
1707 fn test_complex_query() {
1708 let query = select(&["u.id", "u.name", "COUNT(o.id) AS order_count"])
1710 .from("users")
1711 .join("orders", "u.id = o.user_id")
1712 .where_clause("u.active = true")
1713 .and_where("o.created_at > '2024-01-01'")
1714 .group_by(&["u.id", "u.name"])
1715 .having("COUNT(o.id) > 0")
1716 .order_by(&["order_count DESC"])
1717 .limit(10)
1718 .build();
1719
1720 let sql = generate(&query, Dialect::Postgres);
1721 assert!(sql.contains("SELECT"));
1722 assert!(sql.contains("JOIN"));
1723 assert!(sql.contains("WHERE"));
1724 assert!(sql.contains("GROUP BY"));
1725 assert!(sql.contains("HAVING"));
1726 assert!(sql.contains("ORDER BY"));
1727 assert!(sql.contains("LIMIT"));
1728 }
1729
1730 #[test]
1731 fn test_subquery_in_from() {
1732 let inner = select(&["id", "name"]).from("users").where_clause("active = true").build();
1733 let outer = select(&["*"]).from_subquery(inner, "active_users").build();
1734
1735 let sql = generate(&outer, Dialect::Ansi);
1736 assert!(sql.contains("FROM (SELECT"));
1737 assert!(sql.contains(") AS active_users"));
1738 }
1739}