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