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 comments: Vec::new(),
848 ctes: Vec::new(),
849 distinct: false,
850 top: None,
851 columns: Vec::new(),
852 from: None,
853 joins: Vec::new(),
854 where_clause: None,
855 group_by: Vec::new(),
856 having: None,
857 order_by: Vec::new(),
858 limit: None,
859 offset: None,
860 fetch_first: None,
861 qualify: None,
862 window_definitions: Vec::new(),
863 },
864 dialect: Dialect::Ansi,
865 }
866 }
867
868 #[must_use]
870 pub fn dialect(mut self, dialect: Dialect) -> Self {
871 self.dialect = dialect;
872 self
873 }
874
875 #[must_use]
879 pub fn columns(mut self, cols: &[&str]) -> Self {
880 for col in cols {
881 if let Some(expr) = parse_expr_dialect(col, self.dialect) {
882 self.statement
883 .columns
884 .push(SelectItem::Expr { expr, alias: None });
885 }
886 }
887 self
888 }
889
890 #[must_use]
892 pub fn column_expr(mut self, expr: Expr, alias: Option<&str>) -> Self {
893 self.statement.columns.push(SelectItem::Expr {
894 expr,
895 alias: alias.map(String::from),
896 });
897 self
898 }
899
900 #[must_use]
902 pub fn all(mut self) -> Self {
903 self.statement.columns.push(SelectItem::Wildcard);
904 self
905 }
906
907 #[must_use]
909 pub fn all_from(mut self, table: &str) -> Self {
910 self.statement.columns.push(SelectItem::QualifiedWildcard {
911 table: table.to_string(),
912 });
913 self
914 }
915
916 #[must_use]
918 pub fn distinct(mut self) -> Self {
919 self.statement.distinct = true;
920 self
921 }
922
923 #[must_use]
925 pub fn from(mut self, table_name: &str) -> Self {
926 self.statement.from = Some(FromClause {
927 source: TableSource::Table(table(table_name, None)),
928 });
929 self
930 }
931
932 #[must_use]
934 pub fn from_table(mut self, table_ref: TableRef) -> Self {
935 self.statement.from = Some(FromClause {
936 source: TableSource::Table(table_ref),
937 });
938 self
939 }
940
941 #[must_use]
943 pub fn from_subquery(mut self, query: Statement, alias: &str) -> Self {
944 self.statement.from = Some(FromClause {
945 source: TableSource::Subquery {
946 query: Box::new(query),
947 alias: Some(alias.to_string()),
948 },
949 });
950 self
951 }
952
953 #[must_use]
955 pub fn join(self, table_name: &str, on: &str) -> Self {
956 self.join_type(table_name, on, JoinType::Inner)
957 }
958
959 #[must_use]
961 pub fn left_join(self, table_name: &str, on: &str) -> Self {
962 self.join_type(table_name, on, JoinType::Left)
963 }
964
965 #[must_use]
967 pub fn right_join(self, table_name: &str, on: &str) -> Self {
968 self.join_type(table_name, on, JoinType::Right)
969 }
970
971 #[must_use]
973 pub fn full_join(self, table_name: &str, on: &str) -> Self {
974 self.join_type(table_name, on, JoinType::Full)
975 }
976
977 #[must_use]
979 pub fn cross_join(mut self, table_name: &str) -> Self {
980 self.statement.joins.push(JoinClause {
981 join_type: JoinType::Cross,
982 table: TableSource::Table(table(table_name, None)),
983 on: None,
984 using: Vec::new(),
985 });
986 self
987 }
988
989 #[must_use]
991 fn join_type(mut self, table_name: &str, on: &str, join_type: JoinType) -> Self {
992 let on_expr = parse_condition_dialect(on, self.dialect);
993 self.statement.joins.push(JoinClause {
994 join_type,
995 table: TableSource::Table(table(table_name, None)),
996 on: on_expr,
997 using: Vec::new(),
998 });
999 self
1000 }
1001
1002 #[must_use]
1004 pub fn join_using(mut self, table_name: &str, columns: &[&str], join_type: JoinType) -> Self {
1005 self.statement.joins.push(JoinClause {
1006 join_type,
1007 table: TableSource::Table(table(table_name, None)),
1008 on: None,
1009 using: columns.iter().map(|s| s.to_string()).collect(),
1010 });
1011 self
1012 }
1013
1014 #[must_use]
1016 pub fn join_subquery(
1017 mut self,
1018 query: Statement,
1019 alias: &str,
1020 on: &str,
1021 join_type: JoinType,
1022 ) -> Self {
1023 let on_expr = parse_condition_dialect(on, self.dialect);
1024 self.statement.joins.push(JoinClause {
1025 join_type,
1026 table: TableSource::Subquery {
1027 query: Box::new(query),
1028 alias: Some(alias.to_string()),
1029 },
1030 on: on_expr,
1031 using: Vec::new(),
1032 });
1033 self
1034 }
1035
1036 #[must_use]
1038 pub fn where_clause(mut self, condition: &str) -> Self {
1039 self.statement.where_clause = parse_condition_dialect(condition, self.dialect);
1040 self
1041 }
1042
1043 #[must_use]
1045 pub fn where_expr(mut self, expr: Expr) -> Self {
1046 self.statement.where_clause = Some(expr);
1047 self
1048 }
1049
1050 #[must_use]
1052 pub fn and_where(mut self, condition: &str) -> Self {
1053 let new_cond = parse_condition_dialect(condition, self.dialect);
1054 self.statement.where_clause = match (self.statement.where_clause, new_cond) {
1055 (Some(existing), Some(new)) => Some(Expr::BinaryOp {
1056 left: Box::new(existing),
1057 op: BinaryOperator::And,
1058 right: Box::new(new),
1059 }),
1060 (Some(e), None) | (None, Some(e)) => Some(e),
1061 (None, None) => None,
1062 };
1063 self
1064 }
1065
1066 #[must_use]
1068 pub fn or_where(mut self, condition: &str) -> Self {
1069 let new_cond = parse_condition_dialect(condition, self.dialect);
1070 self.statement.where_clause = match (self.statement.where_clause, new_cond) {
1071 (Some(existing), Some(new)) => Some(Expr::BinaryOp {
1072 left: Box::new(existing),
1073 op: BinaryOperator::Or,
1074 right: Box::new(new),
1075 }),
1076 (Some(e), None) | (None, Some(e)) => Some(e),
1077 (None, None) => None,
1078 };
1079 self
1080 }
1081
1082 #[must_use]
1084 pub fn group_by(mut self, exprs: &[&str]) -> Self {
1085 self.statement.group_by = exprs
1086 .iter()
1087 .filter_map(|e| parse_expr_dialect(e, self.dialect))
1088 .collect();
1089 self
1090 }
1091
1092 #[must_use]
1094 pub fn add_group_by(mut self, expr: &str) -> Self {
1095 if let Some(e) = parse_expr_dialect(expr, self.dialect) {
1096 self.statement.group_by.push(e);
1097 }
1098 self
1099 }
1100
1101 #[must_use]
1103 pub fn having(mut self, condition: &str) -> Self {
1104 self.statement.having = parse_condition_dialect(condition, self.dialect);
1105 self
1106 }
1107
1108 #[must_use]
1110 pub fn order_by(mut self, exprs: &[&str]) -> Self {
1111 self.statement.order_by = exprs
1112 .iter()
1113 .filter_map(|e| parse_order_by_item(e, self.dialect))
1114 .collect();
1115 self
1116 }
1117
1118 #[must_use]
1120 pub fn add_order_by(mut self, expr: &str) -> Self {
1121 if let Some(item) = parse_order_by_item(expr, self.dialect) {
1122 self.statement.order_by.push(item);
1123 }
1124 self
1125 }
1126
1127 #[must_use]
1129 pub fn add_order_by_expr(
1130 mut self,
1131 expr: Expr,
1132 ascending: bool,
1133 nulls_first: Option<bool>,
1134 ) -> Self {
1135 self.statement.order_by.push(OrderByItem {
1136 expr,
1137 ascending,
1138 nulls_first,
1139 });
1140 self
1141 }
1142
1143 #[must_use]
1145 pub fn limit(mut self, n: i64) -> Self {
1146 self.statement.limit = Some(Expr::Number(n.to_string()));
1147 self
1148 }
1149
1150 #[must_use]
1152 pub fn limit_expr(mut self, expr: Expr) -> Self {
1153 self.statement.limit = Some(expr);
1154 self
1155 }
1156
1157 #[must_use]
1159 pub fn offset(mut self, n: i64) -> Self {
1160 self.statement.offset = Some(Expr::Number(n.to_string()));
1161 self
1162 }
1163
1164 #[must_use]
1166 pub fn offset_expr(mut self, expr: Expr) -> Self {
1167 self.statement.offset = Some(expr);
1168 self
1169 }
1170
1171 #[must_use]
1173 pub fn top(mut self, n: i64) -> Self {
1174 self.statement.top = Some(Box::new(Expr::Number(n.to_string())));
1175 self
1176 }
1177
1178 #[must_use]
1180 pub fn qualify(mut self, condition: &str) -> Self {
1181 self.statement.qualify = parse_condition_dialect(condition, self.dialect);
1182 self
1183 }
1184
1185 #[must_use]
1187 pub fn build(self) -> Statement {
1188 Statement::Select(self.statement)
1189 }
1190
1191 #[must_use]
1193 pub fn build_select(self) -> SelectStatement {
1194 self.statement
1195 }
1196}
1197
1198#[must_use]
1208pub fn select(columns: &[&str]) -> SelectBuilder {
1209 SelectBuilder::new().columns(columns)
1210}
1211
1212#[must_use]
1222pub fn select_all() -> SelectBuilder {
1223 SelectBuilder::new().all()
1224}
1225
1226#[must_use]
1236pub fn select_distinct(columns: &[&str]) -> SelectBuilder {
1237 SelectBuilder::new().distinct().columns(columns)
1238}
1239
1240impl SelectStatement {
1245 pub fn add_select(&mut self, expr_str: &str) {
1256 self.add_select_dialect(expr_str, Dialect::Ansi);
1257 }
1258
1259 pub fn add_select_dialect(&mut self, expr_str: &str, dialect: Dialect) {
1261 if let Some(expr) = parse_expr_dialect(expr_str, dialect) {
1262 self.columns.push(SelectItem::Expr { expr, alias: None });
1263 }
1264 }
1265
1266 pub fn add_select_expr(&mut self, expr: Expr, alias: Option<&str>) {
1268 self.columns.push(SelectItem::Expr {
1269 expr,
1270 alias: alias.map(String::from),
1271 });
1272 }
1273
1274 pub fn add_where(&mut self, condition: &str) {
1286 self.add_where_dialect(condition, Dialect::Ansi);
1287 }
1288
1289 pub fn add_where_dialect(&mut self, condition: &str, dialect: Dialect) {
1291 let new_cond = parse_condition_dialect(condition, dialect);
1292 self.where_clause = match (self.where_clause.take(), new_cond) {
1293 (Some(existing), Some(new)) => Some(Expr::BinaryOp {
1294 left: Box::new(existing),
1295 op: BinaryOperator::And,
1296 right: Box::new(new),
1297 }),
1298 (Some(e), None) | (None, Some(e)) => Some(e),
1299 (None, None) => None,
1300 };
1301 }
1302
1303 pub fn add_where_expr(&mut self, expr: Expr) {
1305 self.where_clause = match self.where_clause.take() {
1306 Some(existing) => Some(Expr::BinaryOp {
1307 left: Box::new(existing),
1308 op: BinaryOperator::And,
1309 right: Box::new(expr),
1310 }),
1311 None => Some(expr),
1312 };
1313 }
1314
1315 pub fn add_join(&mut self, table_name: &str, on: &str, join_type: JoinType) {
1327 self.add_join_dialect(table_name, on, join_type, Dialect::Ansi);
1328 }
1329
1330 pub fn add_join_dialect(
1332 &mut self,
1333 table_name: &str,
1334 on: &str,
1335 join_type: JoinType,
1336 dialect: Dialect,
1337 ) {
1338 let on_expr = parse_condition_dialect(on, dialect);
1339 self.joins.push(JoinClause {
1340 join_type,
1341 table: TableSource::Table(table(table_name, None)),
1342 on: on_expr,
1343 using: Vec::new(),
1344 });
1345 }
1346
1347 pub fn add_join_subquery(
1349 &mut self,
1350 query: Statement,
1351 alias: &str,
1352 on: &str,
1353 join_type: JoinType,
1354 ) {
1355 self.add_join_subquery_dialect(query, alias, on, join_type, Dialect::Ansi);
1356 }
1357
1358 pub fn add_join_subquery_dialect(
1360 &mut self,
1361 query: Statement,
1362 alias: &str,
1363 on: &str,
1364 join_type: JoinType,
1365 dialect: Dialect,
1366 ) {
1367 let on_expr = parse_condition_dialect(on, dialect);
1368 self.joins.push(JoinClause {
1369 join_type,
1370 table: TableSource::Subquery {
1371 query: Box::new(query),
1372 alias: Some(alias.to_string()),
1373 },
1374 on: on_expr,
1375 using: Vec::new(),
1376 });
1377 }
1378
1379 #[must_use]
1390 pub fn as_subquery(self, alias: &str) -> TableSource {
1391 TableSource::Subquery {
1392 query: Box::new(Statement::Select(self)),
1393 alias: Some(alias.to_string()),
1394 }
1395 }
1396}
1397
1398fn parse_order_by_item(s: &str, dialect: Dialect) -> Option<OrderByItem> {
1404 let s = s.trim();
1405 let upper = s.to_uppercase();
1406
1407 let nulls_first = if upper.contains("NULLS FIRST") {
1409 Some(true)
1410 } else if upper.contains("NULLS LAST") {
1411 Some(false)
1412 } else {
1413 None
1414 };
1415
1416 let s = s
1418 .replace("NULLS FIRST", "")
1419 .replace("NULLS LAST", "")
1420 .replace("nulls first", "")
1421 .replace("nulls last", "");
1422 let s = s.trim();
1423
1424 let (expr_str, ascending) = if s.to_uppercase().ends_with(" DESC") {
1426 (&s[..s.len() - 5], false)
1427 } else if s.to_uppercase().ends_with(" ASC") {
1428 (&s[..s.len() - 4], true)
1429 } else {
1430 (s, true)
1431 };
1432
1433 parse_expr_dialect(expr_str.trim(), dialect).map(|expr| OrderByItem {
1434 expr,
1435 ascending,
1436 nulls_first,
1437 })
1438}
1439
1440#[cfg(test)]
1441mod tests {
1442 use super::*;
1443 use crate::generate;
1444
1445 #[test]
1446 fn test_column() {
1447 let col = column("name", None);
1448 assert!(
1449 matches!(col, Expr::Column { name, table, .. } if name == "name" && table.is_none())
1450 );
1451
1452 let qualified = column("id", Some("users"));
1453 assert!(matches!(qualified, Expr::Column { name, table, .. }
1454 if name == "id" && table == Some("users".to_string())));
1455 }
1456
1457 #[test]
1458 fn test_table() {
1459 let tbl = table("users", None);
1460 assert_eq!(tbl.name, "users");
1461 assert!(tbl.schema.is_none());
1462
1463 let qualified = table("orders", Some("public"));
1464 assert_eq!(qualified.name, "orders");
1465 assert_eq!(qualified.schema, Some("public".to_string()));
1466 }
1467
1468 #[test]
1469 fn test_literals() {
1470 assert!(matches!(literal(42), Expr::Number(n) if n == "42"));
1471 assert!(matches!(string_literal("hello"), Expr::StringLiteral(s) if s == "hello"));
1472 assert!(matches!(boolean(true), Expr::Boolean(true)));
1473 assert!(matches!(null(), Expr::Null));
1474 }
1475
1476 #[test]
1477 fn test_cast() {
1478 let col = column("id", None);
1479 let casted = cast(col, DataType::BigInt);
1480 assert!(matches!(
1481 casted,
1482 Expr::Cast {
1483 data_type: DataType::BigInt,
1484 ..
1485 }
1486 ));
1487 }
1488
1489 #[test]
1490 fn test_and_all() {
1491 let cond1 = eq(column("x", None), literal(1));
1492 let cond2 = eq(column("y", None), literal(2));
1493
1494 let combined = and_all(vec![cond1, cond2]).unwrap();
1495 assert!(matches!(
1496 combined,
1497 Expr::BinaryOp {
1498 op: BinaryOperator::And,
1499 ..
1500 }
1501 ));
1502
1503 assert!(and_all(Vec::<Expr>::new()).is_none());
1505 }
1506
1507 #[test]
1508 fn test_or_all() {
1509 let cond1 = eq(column("x", None), literal(1));
1510 let cond2 = eq(column("y", None), literal(2));
1511
1512 let combined = or_all(vec![cond1, cond2]).unwrap();
1513 assert!(matches!(
1514 combined,
1515 Expr::BinaryOp {
1516 op: BinaryOperator::Or,
1517 ..
1518 }
1519 ));
1520 }
1521
1522 #[test]
1523 fn test_parse_expr() {
1524 let expr = parse_expr("x + 1").unwrap();
1525 assert!(matches!(
1526 expr,
1527 Expr::BinaryOp {
1528 op: BinaryOperator::Plus,
1529 ..
1530 }
1531 ));
1532 }
1533
1534 #[test]
1535 fn test_parse_condition() {
1536 let cond = parse_condition("x > 1 AND y < 10").unwrap();
1537 assert!(matches!(
1538 cond,
1539 Expr::BinaryOp {
1540 op: BinaryOperator::And,
1541 ..
1542 }
1543 ));
1544 }
1545
1546 #[test]
1547 fn test_condition_builder() {
1548 let cond = condition("x = 1").and("y = 2").or("z = 3").build();
1549 assert!(cond.is_some());
1550 }
1551
1552 #[test]
1553 fn test_condition_builder_not() {
1554 let cond = condition("x = 1").not().build().unwrap();
1555 assert!(matches!(
1556 cond,
1557 Expr::UnaryOp {
1558 op: crate::ast::UnaryOperator::Not,
1559 ..
1560 }
1561 ));
1562 }
1563
1564 #[test]
1565 fn test_select_builder_basic() {
1566 let query = select(&["a", "b"]).from("users").build();
1567 let sql = generate(&query, Dialect::Ansi);
1568 assert!(sql.contains("SELECT"));
1569 assert!(sql.contains("a"));
1570 assert!(sql.contains("b"));
1571 assert!(sql.contains("FROM users"));
1572 }
1573
1574 #[test]
1575 fn test_select_builder_where() {
1576 let query = select(&["*"])
1577 .from("users")
1578 .where_clause("active = true")
1579 .build();
1580 let sql = generate(&query, Dialect::Ansi);
1581 assert!(sql.contains("WHERE"));
1582 }
1583
1584 #[test]
1585 fn test_select_builder_join() {
1586 let query = select(&["u.name", "o.total"])
1587 .from("users")
1588 .join("orders", "users.id = orders.user_id")
1589 .build();
1590 let sql = generate(&query, Dialect::Ansi);
1591 assert!(sql.contains("JOIN"));
1592 }
1593
1594 #[test]
1595 fn test_select_builder_group_by() {
1596 let query = select(&["category", "COUNT(*)"])
1597 .from("products")
1598 .group_by(&["category"])
1599 .having("COUNT(*) > 5")
1600 .build();
1601 let sql = generate(&query, Dialect::Ansi);
1602 assert!(sql.contains("GROUP BY"));
1603 assert!(sql.contains("HAVING"));
1604 }
1605
1606 #[test]
1607 fn test_select_builder_order_limit() {
1608 let query = select(&["*"])
1609 .from("users")
1610 .order_by(&["created_at DESC"])
1611 .limit(10)
1612 .offset(5)
1613 .build();
1614 let sql = generate(&query, Dialect::Ansi);
1615 assert!(sql.contains("ORDER BY"));
1616 assert!(sql.contains("LIMIT 10"));
1617 assert!(sql.contains("OFFSET 5"));
1618 }
1619
1620 #[test]
1621 fn test_select_builder_distinct() {
1622 let query = select_distinct(&["category"]).from("products").build();
1623 let sql = generate(&query, Dialect::Ansi);
1624 assert!(sql.contains("SELECT DISTINCT"));
1625 }
1626
1627 #[test]
1628 fn test_select_all() {
1629 let query = select_all().from("users").build();
1630 let sql = generate(&query, Dialect::Ansi);
1631 assert!(sql.contains("SELECT *"));
1632 }
1633
1634 #[test]
1635 fn test_mutation_add_select() {
1636 let mut stmt = select(&["a"]).from("t").build_select();
1637 stmt.add_select("b");
1638 assert_eq!(stmt.columns.len(), 2);
1639 }
1640
1641 #[test]
1642 fn test_mutation_add_where() {
1643 let mut stmt = select(&["*"]).from("t").build_select();
1644 stmt.add_where("x > 1");
1645 stmt.add_where("y < 10");
1646 assert!(stmt.where_clause.is_some());
1648 }
1649
1650 #[test]
1651 fn test_mutation_add_join() {
1652 let mut stmt = select(&["*"]).from("users").build_select();
1653 stmt.add_join("orders", "users.id = orders.user_id", JoinType::Inner);
1654 assert_eq!(stmt.joins.len(), 1);
1655 }
1656
1657 #[test]
1658 fn test_as_subquery() {
1659 let inner = select(&["id"]).from("users").build_select();
1660 let source = inner.as_subquery("u");
1661 assert!(matches!(source, TableSource::Subquery { alias: Some(a), .. } if a == "u"));
1662 }
1663
1664 #[test]
1665 fn test_comparison_helpers() {
1666 let e = eq(column("a", None), literal(1));
1667 assert!(matches!(
1668 e,
1669 Expr::BinaryOp {
1670 op: BinaryOperator::Eq,
1671 ..
1672 }
1673 ));
1674
1675 let e = neq(column("a", None), literal(1));
1676 assert!(matches!(
1677 e,
1678 Expr::BinaryOp {
1679 op: BinaryOperator::Neq,
1680 ..
1681 }
1682 ));
1683
1684 let e = lt(column("a", None), literal(1));
1685 assert!(matches!(
1686 e,
1687 Expr::BinaryOp {
1688 op: BinaryOperator::Lt,
1689 ..
1690 }
1691 ));
1692
1693 let e = gt(column("a", None), literal(1));
1694 assert!(matches!(
1695 e,
1696 Expr::BinaryOp {
1697 op: BinaryOperator::Gt,
1698 ..
1699 }
1700 ));
1701 }
1702
1703 #[test]
1704 fn test_arithmetic_helpers() {
1705 let e = add(column("a", None), literal(1));
1706 assert!(matches!(
1707 e,
1708 Expr::BinaryOp {
1709 op: BinaryOperator::Plus,
1710 ..
1711 }
1712 ));
1713
1714 let e = mul(column("a", None), literal(2));
1715 assert!(matches!(
1716 e,
1717 Expr::BinaryOp {
1718 op: BinaryOperator::Multiply,
1719 ..
1720 }
1721 ));
1722 }
1723
1724 #[test]
1725 fn test_is_null_helpers() {
1726 let e = is_null(column("a", None));
1727 assert!(matches!(e, Expr::IsNull { negated: false, .. }));
1728
1729 let e = is_not_null(column("a", None));
1730 assert!(matches!(e, Expr::IsNull { negated: true, .. }));
1731 }
1732
1733 #[test]
1734 fn test_between() {
1735 let e = between(column("x", None), literal(1), literal(10));
1736 assert!(matches!(e, Expr::Between { negated: false, .. }));
1737 }
1738
1739 #[test]
1740 fn test_in_list() {
1741 let e = in_list(
1742 column("status", None),
1743 vec![string_literal("active"), string_literal("pending")],
1744 );
1745 assert!(matches!(e, Expr::InList { negated: false, .. }));
1746 }
1747
1748 #[test]
1749 fn test_like() {
1750 let e = like(column("name", None), string_literal("%John%"));
1751 assert!(matches!(e, Expr::Like { negated: false, .. }));
1752 }
1753
1754 #[test]
1755 fn test_func() {
1756 let f = func("UPPER", vec![column("name", None)]);
1757 assert!(matches!(f, Expr::Function { name, distinct: false, .. } if name == "UPPER"));
1758 }
1759
1760 #[test]
1761 fn test_func_distinct() {
1762 let f = func_distinct("COUNT", vec![column("id", None)]);
1763 assert!(matches!(f, Expr::Function { name, distinct: true, .. } if name == "COUNT"));
1764 }
1765
1766 #[test]
1767 fn test_alias() {
1768 let e = alias(column("first_name", None), "name");
1769 assert!(matches!(e, Expr::Alias { name, .. } if name == "name"));
1770 }
1771
1772 #[test]
1773 fn test_subquery_and_exists() {
1774 let inner = select(&["1"]).from("users").where_clause("id = 1").build();
1775 let sub = subquery(inner.clone());
1776 assert!(matches!(sub, Expr::Subquery(_)));
1777
1778 let ex = exists(inner, false);
1779 assert!(matches!(ex, Expr::Exists { negated: false, .. }));
1780 }
1781
1782 #[test]
1783 fn test_star_and_qualified_star() {
1784 let s = star();
1785 assert!(matches!(s, Expr::Star));
1786
1787 let qs = qualified_star("users");
1788 assert!(matches!(qs, Expr::QualifiedWildcard { table } if table == "users"));
1789 }
1790
1791 #[test]
1792 fn test_complex_query() {
1793 let query = select(&["u.id", "u.name", "COUNT(o.id) AS order_count"])
1795 .from("users")
1796 .join("orders", "u.id = o.user_id")
1797 .where_clause("u.active = true")
1798 .and_where("o.created_at > '2024-01-01'")
1799 .group_by(&["u.id", "u.name"])
1800 .having("COUNT(o.id) > 0")
1801 .order_by(&["order_count DESC"])
1802 .limit(10)
1803 .build();
1804
1805 let sql = generate(&query, Dialect::Postgres);
1806 assert!(sql.contains("SELECT"));
1807 assert!(sql.contains("JOIN"));
1808 assert!(sql.contains("WHERE"));
1809 assert!(sql.contains("GROUP BY"));
1810 assert!(sql.contains("HAVING"));
1811 assert!(sql.contains("ORDER BY"));
1812 assert!(sql.contains("LIMIT"));
1813 }
1814
1815 #[test]
1816 fn test_subquery_in_from() {
1817 let inner = select(&["id", "name"])
1818 .from("users")
1819 .where_clause("active = true")
1820 .build();
1821 let outer = select(&["*"]).from_subquery(inner, "active_users").build();
1822
1823 let sql = generate(&outer, Dialect::Ansi);
1824 assert!(sql.contains("FROM (SELECT"));
1825 assert!(sql.contains(") AS active_users"));
1826 }
1827}