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 alias_quote_style: QuoteStyle::None,
109 }
110}
111
112#[must_use]
127pub fn table_full(name: &str, schema: Option<&str>, catalog: Option<&str>) -> TableRef {
128 TableRef {
129 catalog: catalog.map(String::from),
130 schema: schema.map(String::from),
131 name: name.to_string(),
132 alias: None,
133 name_quote_style: QuoteStyle::None,
134 alias_quote_style: QuoteStyle::None,
135 }
136}
137
138#[must_use]
148pub fn literal<T: ToString>(value: T) -> Expr {
149 Expr::Number(value.to_string())
150}
151
152#[must_use]
162pub fn string_literal(value: &str) -> Expr {
163 Expr::StringLiteral(value.to_string())
164}
165
166#[must_use]
177pub fn boolean(value: bool) -> Expr {
178 Expr::Boolean(value)
179}
180
181#[must_use]
191pub fn null() -> Expr {
192 Expr::Null
193}
194
195#[must_use]
210pub fn cast(expr: Expr, data_type: DataType) -> Expr {
211 Expr::Cast {
212 expr: Box::new(expr),
213 data_type,
214 }
215}
216
217#[must_use]
242pub fn and_all<I>(conditions: I) -> Option<Expr>
243where
244 I: IntoIterator<Item = Expr>,
245{
246 let mut iter = conditions.into_iter();
247 let first = iter.next()?;
248 Some(iter.fold(first, |acc, cond| Expr::BinaryOp {
249 left: Box::new(acc),
250 op: BinaryOperator::And,
251 right: Box::new(cond),
252 }))
253}
254
255#[must_use]
280pub fn or_all<I>(conditions: I) -> Option<Expr>
281where
282 I: IntoIterator<Item = Expr>,
283{
284 let mut iter = conditions.into_iter();
285 let first = iter.next()?;
286 Some(iter.fold(first, |acc, cond| Expr::BinaryOp {
287 left: Box::new(acc),
288 op: BinaryOperator::Or,
289 right: Box::new(cond),
290 }))
291}
292
293#[must_use]
303pub fn not(expr: Expr) -> Expr {
304 Expr::UnaryOp {
305 op: crate::ast::UnaryOperator::Not,
306 expr: Box::new(expr),
307 }
308}
309
310#[must_use]
325pub fn func(name: &str, args: Vec<Expr>) -> Expr {
326 Expr::Function {
327 name: name.to_string(),
328 args,
329 distinct: false,
330 filter: None,
331 over: None,
332 }
333}
334
335#[must_use]
345pub fn func_distinct(name: &str, args: Vec<Expr>) -> Expr {
346 Expr::Function {
347 name: name.to_string(),
348 args,
349 distinct: true,
350 filter: None,
351 over: None,
352 }
353}
354
355#[must_use]
365pub fn star() -> Expr {
366 Expr::Star
367}
368
369#[must_use]
379pub fn qualified_star(table: &str) -> Expr {
380 Expr::QualifiedWildcard {
381 table: table.to_string(),
382 }
383}
384
385#[must_use]
396pub fn subquery(statement: Statement) -> Expr {
397 Expr::Subquery(Box::new(statement))
398}
399
400#[must_use]
411pub fn exists(statement: Statement, negated: bool) -> Expr {
412 Expr::Exists {
413 subquery: Box::new(statement),
414 negated,
415 }
416}
417
418#[must_use]
428pub fn alias(expr: Expr, name: &str) -> Expr {
429 Expr::Alias {
430 expr: Box::new(expr),
431 name: name.to_string(),
432 }
433}
434
435#[must_use]
441pub fn eq(left: Expr, right: Expr) -> Expr {
442 Expr::BinaryOp {
443 left: Box::new(left),
444 op: BinaryOperator::Eq,
445 right: Box::new(right),
446 }
447}
448
449#[must_use]
451pub fn neq(left: Expr, right: Expr) -> Expr {
452 Expr::BinaryOp {
453 left: Box::new(left),
454 op: BinaryOperator::Neq,
455 right: Box::new(right),
456 }
457}
458
459#[must_use]
461pub fn lt(left: Expr, right: Expr) -> Expr {
462 Expr::BinaryOp {
463 left: Box::new(left),
464 op: BinaryOperator::Lt,
465 right: Box::new(right),
466 }
467}
468
469#[must_use]
471pub fn lte(left: Expr, right: Expr) -> Expr {
472 Expr::BinaryOp {
473 left: Box::new(left),
474 op: BinaryOperator::LtEq,
475 right: Box::new(right),
476 }
477}
478
479#[must_use]
481pub fn gt(left: Expr, right: Expr) -> Expr {
482 Expr::BinaryOp {
483 left: Box::new(left),
484 op: BinaryOperator::Gt,
485 right: Box::new(right),
486 }
487}
488
489#[must_use]
491pub fn gte(left: Expr, right: Expr) -> Expr {
492 Expr::BinaryOp {
493 left: Box::new(left),
494 op: BinaryOperator::GtEq,
495 right: Box::new(right),
496 }
497}
498
499#[must_use]
501pub fn is_null(expr: Expr) -> Expr {
502 Expr::IsNull {
503 expr: Box::new(expr),
504 negated: false,
505 }
506}
507
508#[must_use]
510pub fn is_not_null(expr: Expr) -> Expr {
511 Expr::IsNull {
512 expr: Box::new(expr),
513 negated: true,
514 }
515}
516
517#[must_use]
519pub fn between(expr: Expr, low: Expr, high: Expr) -> Expr {
520 Expr::Between {
521 expr: Box::new(expr),
522 low: Box::new(low),
523 high: Box::new(high),
524 negated: false,
525 }
526}
527
528#[must_use]
530pub fn in_list(expr: Expr, list: Vec<Expr>) -> Expr {
531 Expr::InList {
532 expr: Box::new(expr),
533 list,
534 negated: false,
535 }
536}
537
538#[must_use]
540pub fn not_in_list(expr: Expr, list: Vec<Expr>) -> Expr {
541 Expr::InList {
542 expr: Box::new(expr),
543 list,
544 negated: true,
545 }
546}
547
548#[must_use]
550pub fn in_subquery(expr: Expr, query: Statement) -> Expr {
551 Expr::InSubquery {
552 expr: Box::new(expr),
553 subquery: Box::new(query),
554 negated: false,
555 }
556}
557
558#[must_use]
560pub fn like(expr: Expr, pattern: Expr) -> Expr {
561 Expr::Like {
562 expr: Box::new(expr),
563 pattern: Box::new(pattern),
564 negated: false,
565 escape: None,
566 }
567}
568
569#[must_use]
575pub fn add(left: Expr, right: Expr) -> Expr {
576 Expr::BinaryOp {
577 left: Box::new(left),
578 op: BinaryOperator::Plus,
579 right: Box::new(right),
580 }
581}
582
583#[must_use]
585pub fn sub(left: Expr, right: Expr) -> Expr {
586 Expr::BinaryOp {
587 left: Box::new(left),
588 op: BinaryOperator::Minus,
589 right: Box::new(right),
590 }
591}
592
593#[must_use]
595pub fn mul(left: Expr, right: Expr) -> Expr {
596 Expr::BinaryOp {
597 left: Box::new(left),
598 op: BinaryOperator::Multiply,
599 right: Box::new(right),
600 }
601}
602
603#[must_use]
605pub fn div(left: Expr, right: Expr) -> Expr {
606 Expr::BinaryOp {
607 left: Box::new(left),
608 op: BinaryOperator::Divide,
609 right: Box::new(right),
610 }
611}
612
613#[must_use]
630pub fn parse_expr(sql: &str) -> Option<Expr> {
631 parse_expr_dialect(sql, Dialect::Ansi)
632}
633
634#[must_use]
636pub fn parse_expr_dialect(sql: &str, dialect: Dialect) -> Option<Expr> {
637 let query = format!("SELECT {sql}");
639 match parse(&query, dialect) {
640 Ok(Statement::Select(select)) => {
641 if let Some(SelectItem::Expr { expr, .. }) = select.columns.first() {
642 Some(expr.clone())
643 } else {
644 None
645 }
646 }
647 _ => None,
648 }
649}
650
651#[must_use]
661pub fn parse_condition(sql: &str) -> Option<Expr> {
662 parse_condition_dialect(sql, Dialect::Ansi)
663}
664
665#[must_use]
667pub fn parse_condition_dialect(sql: &str, dialect: Dialect) -> Option<Expr> {
668 let query = format!("SELECT 1 WHERE {sql}");
670 match parse(&query, dialect) {
671 Ok(Statement::Select(select)) => select.where_clause,
672 _ => None,
673 }
674}
675
676#[derive(Debug, Clone)]
693pub struct ConditionBuilder {
694 expr: Option<Expr>,
695 dialect: Dialect,
696}
697
698impl ConditionBuilder {
699 #[must_use]
701 pub fn new(condition: &str) -> Self {
702 Self::new_with_dialect(condition, Dialect::Ansi)
703 }
704
705 #[must_use]
707 pub fn new_with_dialect(condition: &str, dialect: Dialect) -> Self {
708 Self {
709 expr: parse_condition_dialect(condition, dialect),
710 dialect,
711 }
712 }
713
714 #[must_use]
716 pub fn from_expr(expr: Expr) -> Self {
717 Self {
718 expr: Some(expr),
719 dialect: Dialect::Ansi,
720 }
721 }
722
723 #[must_use]
725 pub fn and(self, condition: &str) -> Self {
726 let dialect = self.dialect;
727 self.and_expr(parse_condition_dialect(condition, dialect))
728 }
729
730 #[must_use]
732 pub fn and_expr(self, other: Option<Expr>) -> Self {
733 let expr = match (self.expr, other) {
734 (Some(left), Some(right)) => Some(Expr::BinaryOp {
735 left: Box::new(left),
736 op: BinaryOperator::And,
737 right: Box::new(right),
738 }),
739 (Some(e), None) | (None, Some(e)) => Some(e),
740 (None, None) => None,
741 };
742 Self {
743 expr,
744 dialect: self.dialect,
745 }
746 }
747
748 #[must_use]
750 pub fn or(self, condition: &str) -> Self {
751 let dialect = self.dialect;
752 self.or_expr(parse_condition_dialect(condition, dialect))
753 }
754
755 #[must_use]
757 pub fn or_expr(self, other: Option<Expr>) -> Self {
758 let expr = match (self.expr, other) {
759 (Some(left), Some(right)) => Some(Expr::BinaryOp {
760 left: Box::new(left),
761 op: BinaryOperator::Or,
762 right: Box::new(right),
763 }),
764 (Some(e), None) | (None, Some(e)) => Some(e),
765 (None, None) => None,
766 };
767 Self {
768 expr,
769 dialect: self.dialect,
770 }
771 }
772
773 #[must_use]
775 pub fn not(self) -> Self {
776 let expr = self.expr.map(|e| Expr::UnaryOp {
777 op: crate::ast::UnaryOperator::Not,
778 expr: Box::new(e),
779 });
780 Self {
781 expr,
782 dialect: self.dialect,
783 }
784 }
785
786 #[must_use]
788 pub fn build(self) -> Option<Expr> {
789 self.expr
790 }
791}
792
793#[must_use]
803pub fn condition(cond: &str) -> ConditionBuilder {
804 ConditionBuilder::new(cond)
805}
806
807#[must_use]
809pub fn condition_dialect(cond: &str, dialect: Dialect) -> ConditionBuilder {
810 ConditionBuilder::new_with_dialect(cond, dialect)
811}
812
813#[derive(Debug, Clone)]
832pub struct SelectBuilder {
833 statement: SelectStatement,
834 dialect: Dialect,
835}
836
837impl Default for SelectBuilder {
838 fn default() -> Self {
839 Self::new()
840 }
841}
842
843impl SelectBuilder {
844 #[must_use]
846 pub fn new() -> Self {
847 Self {
848 statement: SelectStatement {
849 comments: Vec::new(),
850 ctes: Vec::new(),
851 distinct: false,
852 top: None,
853 columns: Vec::new(),
854 from: None,
855 joins: Vec::new(),
856 where_clause: None,
857 group_by: Vec::new(),
858 having: None,
859 order_by: Vec::new(),
860 limit: None,
861 offset: None,
862 fetch_first: None,
863 qualify: None,
864 window_definitions: Vec::new(),
865 },
866 dialect: Dialect::Ansi,
867 }
868 }
869
870 #[must_use]
872 pub fn dialect(mut self, dialect: Dialect) -> Self {
873 self.dialect = dialect;
874 self
875 }
876
877 #[must_use]
881 pub fn columns(mut self, cols: &[&str]) -> Self {
882 for col in cols {
883 if let Some(expr) = parse_expr_dialect(col, self.dialect) {
884 self.statement.columns.push(SelectItem::Expr {
885 expr,
886 alias: None,
887 alias_quote_style: QuoteStyle::None,
888 });
889 }
890 }
891 self
892 }
893
894 #[must_use]
896 pub fn column_expr(mut self, expr: Expr, alias: Option<&str>) -> Self {
897 self.statement.columns.push(SelectItem::Expr {
898 expr,
899 alias: alias.map(String::from),
900 alias_quote_style: QuoteStyle::None,
901 });
902 self
903 }
904
905 #[must_use]
907 pub fn all(mut self) -> Self {
908 self.statement.columns.push(SelectItem::Wildcard);
909 self
910 }
911
912 #[must_use]
914 pub fn all_from(mut self, table: &str) -> Self {
915 self.statement.columns.push(SelectItem::QualifiedWildcard {
916 table: table.to_string(),
917 });
918 self
919 }
920
921 #[must_use]
923 pub fn distinct(mut self) -> Self {
924 self.statement.distinct = true;
925 self
926 }
927
928 #[must_use]
930 pub fn from(mut self, table_name: &str) -> Self {
931 self.statement.from = Some(FromClause {
932 source: TableSource::Table(table(table_name, None)),
933 });
934 self
935 }
936
937 #[must_use]
939 pub fn from_table(mut self, table_ref: TableRef) -> Self {
940 self.statement.from = Some(FromClause {
941 source: TableSource::Table(table_ref),
942 });
943 self
944 }
945
946 #[must_use]
948 pub fn from_subquery(mut self, query: Statement, alias: &str) -> Self {
949 self.statement.from = Some(FromClause {
950 source: TableSource::Subquery {
951 query: Box::new(query),
952 alias: Some(alias.to_string()),
953 alias_quote_style: QuoteStyle::None,
954 },
955 });
956 self
957 }
958
959 #[must_use]
961 pub fn join(self, table_name: &str, on: &str) -> Self {
962 self.join_type(table_name, on, JoinType::Inner)
963 }
964
965 #[must_use]
967 pub fn left_join(self, table_name: &str, on: &str) -> Self {
968 self.join_type(table_name, on, JoinType::Left)
969 }
970
971 #[must_use]
973 pub fn right_join(self, table_name: &str, on: &str) -> Self {
974 self.join_type(table_name, on, JoinType::Right)
975 }
976
977 #[must_use]
979 pub fn full_join(self, table_name: &str, on: &str) -> Self {
980 self.join_type(table_name, on, JoinType::Full)
981 }
982
983 #[must_use]
985 pub fn cross_join(mut self, table_name: &str) -> Self {
986 self.statement.joins.push(JoinClause {
987 join_type: JoinType::Cross,
988 table: TableSource::Table(table(table_name, None)),
989 on: None,
990 using: Vec::new(),
991 });
992 self
993 }
994
995 #[must_use]
997 fn join_type(mut self, table_name: &str, on: &str, join_type: JoinType) -> Self {
998 let on_expr = parse_condition_dialect(on, self.dialect);
999 self.statement.joins.push(JoinClause {
1000 join_type,
1001 table: TableSource::Table(table(table_name, None)),
1002 on: on_expr,
1003 using: Vec::new(),
1004 });
1005 self
1006 }
1007
1008 #[must_use]
1010 pub fn join_using(mut self, table_name: &str, columns: &[&str], join_type: JoinType) -> Self {
1011 self.statement.joins.push(JoinClause {
1012 join_type,
1013 table: TableSource::Table(table(table_name, None)),
1014 on: None,
1015 using: columns.iter().map(|s| s.to_string()).collect(),
1016 });
1017 self
1018 }
1019
1020 #[must_use]
1022 pub fn join_subquery(
1023 mut self,
1024 query: Statement,
1025 alias: &str,
1026 on: &str,
1027 join_type: JoinType,
1028 ) -> Self {
1029 let on_expr = parse_condition_dialect(on, self.dialect);
1030 self.statement.joins.push(JoinClause {
1031 join_type,
1032 table: TableSource::Subquery {
1033 query: Box::new(query),
1034 alias: Some(alias.to_string()),
1035 alias_quote_style: QuoteStyle::None,
1036 },
1037 on: on_expr,
1038 using: Vec::new(),
1039 });
1040 self
1041 }
1042
1043 #[must_use]
1045 pub fn where_clause(mut self, condition: &str) -> Self {
1046 self.statement.where_clause = parse_condition_dialect(condition, self.dialect);
1047 self
1048 }
1049
1050 #[must_use]
1052 pub fn where_expr(mut self, expr: Expr) -> Self {
1053 self.statement.where_clause = Some(expr);
1054 self
1055 }
1056
1057 #[must_use]
1059 pub fn and_where(mut self, condition: &str) -> Self {
1060 let new_cond = parse_condition_dialect(condition, self.dialect);
1061 self.statement.where_clause = match (self.statement.where_clause, new_cond) {
1062 (Some(existing), Some(new)) => Some(Expr::BinaryOp {
1063 left: Box::new(existing),
1064 op: BinaryOperator::And,
1065 right: Box::new(new),
1066 }),
1067 (Some(e), None) | (None, Some(e)) => Some(e),
1068 (None, None) => None,
1069 };
1070 self
1071 }
1072
1073 #[must_use]
1075 pub fn or_where(mut self, condition: &str) -> Self {
1076 let new_cond = parse_condition_dialect(condition, self.dialect);
1077 self.statement.where_clause = match (self.statement.where_clause, new_cond) {
1078 (Some(existing), Some(new)) => Some(Expr::BinaryOp {
1079 left: Box::new(existing),
1080 op: BinaryOperator::Or,
1081 right: Box::new(new),
1082 }),
1083 (Some(e), None) | (None, Some(e)) => Some(e),
1084 (None, None) => None,
1085 };
1086 self
1087 }
1088
1089 #[must_use]
1091 pub fn group_by(mut self, exprs: &[&str]) -> Self {
1092 self.statement.group_by = exprs
1093 .iter()
1094 .filter_map(|e| parse_expr_dialect(e, self.dialect))
1095 .collect();
1096 self
1097 }
1098
1099 #[must_use]
1101 pub fn add_group_by(mut self, expr: &str) -> Self {
1102 if let Some(e) = parse_expr_dialect(expr, self.dialect) {
1103 self.statement.group_by.push(e);
1104 }
1105 self
1106 }
1107
1108 #[must_use]
1110 pub fn having(mut self, condition: &str) -> Self {
1111 self.statement.having = parse_condition_dialect(condition, self.dialect);
1112 self
1113 }
1114
1115 #[must_use]
1117 pub fn order_by(mut self, exprs: &[&str]) -> Self {
1118 self.statement.order_by = exprs
1119 .iter()
1120 .filter_map(|e| parse_order_by_item(e, self.dialect))
1121 .collect();
1122 self
1123 }
1124
1125 #[must_use]
1127 pub fn add_order_by(mut self, expr: &str) -> Self {
1128 if let Some(item) = parse_order_by_item(expr, self.dialect) {
1129 self.statement.order_by.push(item);
1130 }
1131 self
1132 }
1133
1134 #[must_use]
1136 pub fn add_order_by_expr(
1137 mut self,
1138 expr: Expr,
1139 ascending: bool,
1140 nulls_first: Option<bool>,
1141 ) -> Self {
1142 self.statement.order_by.push(OrderByItem {
1143 expr,
1144 ascending,
1145 nulls_first,
1146 });
1147 self
1148 }
1149
1150 #[must_use]
1152 pub fn limit(mut self, n: i64) -> Self {
1153 self.statement.limit = Some(Expr::Number(n.to_string()));
1154 self
1155 }
1156
1157 #[must_use]
1159 pub fn limit_expr(mut self, expr: Expr) -> Self {
1160 self.statement.limit = Some(expr);
1161 self
1162 }
1163
1164 #[must_use]
1166 pub fn offset(mut self, n: i64) -> Self {
1167 self.statement.offset = Some(Expr::Number(n.to_string()));
1168 self
1169 }
1170
1171 #[must_use]
1173 pub fn offset_expr(mut self, expr: Expr) -> Self {
1174 self.statement.offset = Some(expr);
1175 self
1176 }
1177
1178 #[must_use]
1180 pub fn top(mut self, n: i64) -> Self {
1181 self.statement.top = Some(Box::new(Expr::Number(n.to_string())));
1182 self
1183 }
1184
1185 #[must_use]
1187 pub fn qualify(mut self, condition: &str) -> Self {
1188 self.statement.qualify = parse_condition_dialect(condition, self.dialect);
1189 self
1190 }
1191
1192 #[must_use]
1194 pub fn build(self) -> Statement {
1195 Statement::Select(self.statement)
1196 }
1197
1198 #[must_use]
1200 pub fn build_select(self) -> SelectStatement {
1201 self.statement
1202 }
1203}
1204
1205#[must_use]
1215pub fn select(columns: &[&str]) -> SelectBuilder {
1216 SelectBuilder::new().columns(columns)
1217}
1218
1219#[must_use]
1229pub fn select_all() -> SelectBuilder {
1230 SelectBuilder::new().all()
1231}
1232
1233#[must_use]
1243pub fn select_distinct(columns: &[&str]) -> SelectBuilder {
1244 SelectBuilder::new().distinct().columns(columns)
1245}
1246
1247impl SelectStatement {
1252 pub fn add_select(&mut self, expr_str: &str) {
1263 self.add_select_dialect(expr_str, Dialect::Ansi);
1264 }
1265
1266 pub fn add_select_dialect(&mut self, expr_str: &str, dialect: Dialect) {
1268 if let Some(expr) = parse_expr_dialect(expr_str, dialect) {
1269 self.columns.push(SelectItem::Expr {
1270 expr,
1271 alias: None,
1272 alias_quote_style: QuoteStyle::None,
1273 });
1274 }
1275 }
1276
1277 pub fn add_select_expr(&mut self, expr: Expr, alias: Option<&str>) {
1279 self.columns.push(SelectItem::Expr {
1280 expr,
1281 alias: alias.map(String::from),
1282 alias_quote_style: QuoteStyle::None,
1283 });
1284 }
1285
1286 pub fn add_where(&mut self, condition: &str) {
1298 self.add_where_dialect(condition, Dialect::Ansi);
1299 }
1300
1301 pub fn add_where_dialect(&mut self, condition: &str, dialect: Dialect) {
1303 let new_cond = parse_condition_dialect(condition, dialect);
1304 self.where_clause = match (self.where_clause.take(), new_cond) {
1305 (Some(existing), Some(new)) => Some(Expr::BinaryOp {
1306 left: Box::new(existing),
1307 op: BinaryOperator::And,
1308 right: Box::new(new),
1309 }),
1310 (Some(e), None) | (None, Some(e)) => Some(e),
1311 (None, None) => None,
1312 };
1313 }
1314
1315 pub fn add_where_expr(&mut self, expr: Expr) {
1317 self.where_clause = match self.where_clause.take() {
1318 Some(existing) => Some(Expr::BinaryOp {
1319 left: Box::new(existing),
1320 op: BinaryOperator::And,
1321 right: Box::new(expr),
1322 }),
1323 None => Some(expr),
1324 };
1325 }
1326
1327 pub fn add_join(&mut self, table_name: &str, on: &str, join_type: JoinType) {
1339 self.add_join_dialect(table_name, on, join_type, Dialect::Ansi);
1340 }
1341
1342 pub fn add_join_dialect(
1344 &mut self,
1345 table_name: &str,
1346 on: &str,
1347 join_type: JoinType,
1348 dialect: Dialect,
1349 ) {
1350 let on_expr = parse_condition_dialect(on, dialect);
1351 self.joins.push(JoinClause {
1352 join_type,
1353 table: TableSource::Table(table(table_name, None)),
1354 on: on_expr,
1355 using: Vec::new(),
1356 });
1357 }
1358
1359 pub fn add_join_subquery(
1361 &mut self,
1362 query: Statement,
1363 alias: &str,
1364 on: &str,
1365 join_type: JoinType,
1366 ) {
1367 self.add_join_subquery_dialect(query, alias, on, join_type, Dialect::Ansi);
1368 }
1369
1370 pub fn add_join_subquery_dialect(
1372 &mut self,
1373 query: Statement,
1374 alias: &str,
1375 on: &str,
1376 join_type: JoinType,
1377 dialect: Dialect,
1378 ) {
1379 let on_expr = parse_condition_dialect(on, dialect);
1380 self.joins.push(JoinClause {
1381 join_type,
1382 table: TableSource::Subquery {
1383 query: Box::new(query),
1384 alias: Some(alias.to_string()),
1385 alias_quote_style: QuoteStyle::None,
1386 },
1387 on: on_expr,
1388 using: Vec::new(),
1389 });
1390 }
1391
1392 #[must_use]
1403 pub fn as_subquery(self, alias: &str) -> TableSource {
1404 TableSource::Subquery {
1405 query: Box::new(Statement::Select(self)),
1406 alias: Some(alias.to_string()),
1407 alias_quote_style: QuoteStyle::None,
1408 }
1409 }
1410}
1411
1412fn parse_order_by_item(s: &str, dialect: Dialect) -> Option<OrderByItem> {
1418 let s = s.trim();
1419 let upper = s.to_uppercase();
1420
1421 let nulls_first = if upper.contains("NULLS FIRST") {
1423 Some(true)
1424 } else if upper.contains("NULLS LAST") {
1425 Some(false)
1426 } else {
1427 None
1428 };
1429
1430 let s = s
1432 .replace("NULLS FIRST", "")
1433 .replace("NULLS LAST", "")
1434 .replace("nulls first", "")
1435 .replace("nulls last", "");
1436 let s = s.trim();
1437
1438 let (expr_str, ascending) = if s.to_uppercase().ends_with(" DESC") {
1440 (&s[..s.len() - 5], false)
1441 } else if s.to_uppercase().ends_with(" ASC") {
1442 (&s[..s.len() - 4], true)
1443 } else {
1444 (s, true)
1445 };
1446
1447 parse_expr_dialect(expr_str.trim(), dialect).map(|expr| OrderByItem {
1448 expr,
1449 ascending,
1450 nulls_first,
1451 })
1452}
1453
1454#[cfg(test)]
1455mod tests {
1456 use super::*;
1457 use crate::generate;
1458
1459 #[test]
1460 fn test_column() {
1461 let col = column("name", None);
1462 assert!(
1463 matches!(col, Expr::Column { name, table, .. } if name == "name" && table.is_none())
1464 );
1465
1466 let qualified = column("id", Some("users"));
1467 assert!(matches!(qualified, Expr::Column { name, table, .. }
1468 if name == "id" && table == Some("users".to_string())));
1469 }
1470
1471 #[test]
1472 fn test_table() {
1473 let tbl = table("users", None);
1474 assert_eq!(tbl.name, "users");
1475 assert!(tbl.schema.is_none());
1476
1477 let qualified = table("orders", Some("public"));
1478 assert_eq!(qualified.name, "orders");
1479 assert_eq!(qualified.schema, Some("public".to_string()));
1480 }
1481
1482 #[test]
1483 fn test_literals() {
1484 assert!(matches!(literal(42), Expr::Number(n) if n == "42"));
1485 assert!(matches!(string_literal("hello"), Expr::StringLiteral(s) if s == "hello"));
1486 assert!(matches!(boolean(true), Expr::Boolean(true)));
1487 assert!(matches!(null(), Expr::Null));
1488 }
1489
1490 #[test]
1491 fn test_cast() {
1492 let col = column("id", None);
1493 let casted = cast(col, DataType::BigInt);
1494 assert!(matches!(
1495 casted,
1496 Expr::Cast {
1497 data_type: DataType::BigInt,
1498 ..
1499 }
1500 ));
1501 }
1502
1503 #[test]
1504 fn test_and_all() {
1505 let cond1 = eq(column("x", None), literal(1));
1506 let cond2 = eq(column("y", None), literal(2));
1507
1508 let combined = and_all(vec![cond1, cond2]).unwrap();
1509 assert!(matches!(
1510 combined,
1511 Expr::BinaryOp {
1512 op: BinaryOperator::And,
1513 ..
1514 }
1515 ));
1516
1517 assert!(and_all(Vec::<Expr>::new()).is_none());
1519 }
1520
1521 #[test]
1522 fn test_or_all() {
1523 let cond1 = eq(column("x", None), literal(1));
1524 let cond2 = eq(column("y", None), literal(2));
1525
1526 let combined = or_all(vec![cond1, cond2]).unwrap();
1527 assert!(matches!(
1528 combined,
1529 Expr::BinaryOp {
1530 op: BinaryOperator::Or,
1531 ..
1532 }
1533 ));
1534 }
1535
1536 #[test]
1537 fn test_parse_expr() {
1538 let expr = parse_expr("x + 1").unwrap();
1539 assert!(matches!(
1540 expr,
1541 Expr::BinaryOp {
1542 op: BinaryOperator::Plus,
1543 ..
1544 }
1545 ));
1546 }
1547
1548 #[test]
1549 fn test_parse_condition() {
1550 let cond = parse_condition("x > 1 AND y < 10").unwrap();
1551 assert!(matches!(
1552 cond,
1553 Expr::BinaryOp {
1554 op: BinaryOperator::And,
1555 ..
1556 }
1557 ));
1558 }
1559
1560 #[test]
1561 fn test_condition_builder() {
1562 let cond = condition("x = 1").and("y = 2").or("z = 3").build();
1563 assert!(cond.is_some());
1564 }
1565
1566 #[test]
1567 fn test_condition_builder_not() {
1568 let cond = condition("x = 1").not().build().unwrap();
1569 assert!(matches!(
1570 cond,
1571 Expr::UnaryOp {
1572 op: crate::ast::UnaryOperator::Not,
1573 ..
1574 }
1575 ));
1576 }
1577
1578 #[test]
1579 fn test_select_builder_basic() {
1580 let query = select(&["a", "b"]).from("users").build();
1581 let sql = generate(&query, Dialect::Ansi);
1582 assert!(sql.contains("SELECT"));
1583 assert!(sql.contains("a"));
1584 assert!(sql.contains("b"));
1585 assert!(sql.contains("FROM users"));
1586 }
1587
1588 #[test]
1589 fn test_select_builder_where() {
1590 let query = select(&["*"])
1591 .from("users")
1592 .where_clause("active = true")
1593 .build();
1594 let sql = generate(&query, Dialect::Ansi);
1595 assert!(sql.contains("WHERE"));
1596 }
1597
1598 #[test]
1599 fn test_select_builder_join() {
1600 let query = select(&["u.name", "o.total"])
1601 .from("users")
1602 .join("orders", "users.id = orders.user_id")
1603 .build();
1604 let sql = generate(&query, Dialect::Ansi);
1605 assert!(sql.contains("JOIN"));
1606 }
1607
1608 #[test]
1609 fn test_select_builder_group_by() {
1610 let query = select(&["category", "COUNT(*)"])
1611 .from("products")
1612 .group_by(&["category"])
1613 .having("COUNT(*) > 5")
1614 .build();
1615 let sql = generate(&query, Dialect::Ansi);
1616 assert!(sql.contains("GROUP BY"));
1617 assert!(sql.contains("HAVING"));
1618 }
1619
1620 #[test]
1621 fn test_select_builder_order_limit() {
1622 let query = select(&["*"])
1623 .from("users")
1624 .order_by(&["created_at DESC"])
1625 .limit(10)
1626 .offset(5)
1627 .build();
1628 let sql = generate(&query, Dialect::Ansi);
1629 assert!(sql.contains("ORDER BY"));
1630 assert!(sql.contains("LIMIT 10"));
1631 assert!(sql.contains("OFFSET 5"));
1632 }
1633
1634 #[test]
1635 fn test_select_builder_distinct() {
1636 let query = select_distinct(&["category"]).from("products").build();
1637 let sql = generate(&query, Dialect::Ansi);
1638 assert!(sql.contains("SELECT DISTINCT"));
1639 }
1640
1641 #[test]
1642 fn test_select_all() {
1643 let query = select_all().from("users").build();
1644 let sql = generate(&query, Dialect::Ansi);
1645 assert!(sql.contains("SELECT *"));
1646 }
1647
1648 #[test]
1649 fn test_mutation_add_select() {
1650 let mut stmt = select(&["a"]).from("t").build_select();
1651 stmt.add_select("b");
1652 assert_eq!(stmt.columns.len(), 2);
1653 }
1654
1655 #[test]
1656 fn test_mutation_add_where() {
1657 let mut stmt = select(&["*"]).from("t").build_select();
1658 stmt.add_where("x > 1");
1659 stmt.add_where("y < 10");
1660 assert!(stmt.where_clause.is_some());
1662 }
1663
1664 #[test]
1665 fn test_mutation_add_join() {
1666 let mut stmt = select(&["*"]).from("users").build_select();
1667 stmt.add_join("orders", "users.id = orders.user_id", JoinType::Inner);
1668 assert_eq!(stmt.joins.len(), 1);
1669 }
1670
1671 #[test]
1672 fn test_as_subquery() {
1673 let inner = select(&["id"]).from("users").build_select();
1674 let source = inner.as_subquery("u");
1675 assert!(matches!(source, TableSource::Subquery { alias: Some(a), .. } if a == "u"));
1676 }
1677
1678 #[test]
1679 fn test_comparison_helpers() {
1680 let e = eq(column("a", None), literal(1));
1681 assert!(matches!(
1682 e,
1683 Expr::BinaryOp {
1684 op: BinaryOperator::Eq,
1685 ..
1686 }
1687 ));
1688
1689 let e = neq(column("a", None), literal(1));
1690 assert!(matches!(
1691 e,
1692 Expr::BinaryOp {
1693 op: BinaryOperator::Neq,
1694 ..
1695 }
1696 ));
1697
1698 let e = lt(column("a", None), literal(1));
1699 assert!(matches!(
1700 e,
1701 Expr::BinaryOp {
1702 op: BinaryOperator::Lt,
1703 ..
1704 }
1705 ));
1706
1707 let e = gt(column("a", None), literal(1));
1708 assert!(matches!(
1709 e,
1710 Expr::BinaryOp {
1711 op: BinaryOperator::Gt,
1712 ..
1713 }
1714 ));
1715 }
1716
1717 #[test]
1718 fn test_arithmetic_helpers() {
1719 let e = add(column("a", None), literal(1));
1720 assert!(matches!(
1721 e,
1722 Expr::BinaryOp {
1723 op: BinaryOperator::Plus,
1724 ..
1725 }
1726 ));
1727
1728 let e = mul(column("a", None), literal(2));
1729 assert!(matches!(
1730 e,
1731 Expr::BinaryOp {
1732 op: BinaryOperator::Multiply,
1733 ..
1734 }
1735 ));
1736 }
1737
1738 #[test]
1739 fn test_is_null_helpers() {
1740 let e = is_null(column("a", None));
1741 assert!(matches!(e, Expr::IsNull { negated: false, .. }));
1742
1743 let e = is_not_null(column("a", None));
1744 assert!(matches!(e, Expr::IsNull { negated: true, .. }));
1745 }
1746
1747 #[test]
1748 fn test_between() {
1749 let e = between(column("x", None), literal(1), literal(10));
1750 assert!(matches!(e, Expr::Between { negated: false, .. }));
1751 }
1752
1753 #[test]
1754 fn test_in_list() {
1755 let e = in_list(
1756 column("status", None),
1757 vec![string_literal("active"), string_literal("pending")],
1758 );
1759 assert!(matches!(e, Expr::InList { negated: false, .. }));
1760 }
1761
1762 #[test]
1763 fn test_like() {
1764 let e = like(column("name", None), string_literal("%John%"));
1765 assert!(matches!(e, Expr::Like { negated: false, .. }));
1766 }
1767
1768 #[test]
1769 fn test_func() {
1770 let f = func("UPPER", vec![column("name", None)]);
1771 assert!(matches!(f, Expr::Function { name, distinct: false, .. } if name == "UPPER"));
1772 }
1773
1774 #[test]
1775 fn test_func_distinct() {
1776 let f = func_distinct("COUNT", vec![column("id", None)]);
1777 assert!(matches!(f, Expr::Function { name, distinct: true, .. } if name == "COUNT"));
1778 }
1779
1780 #[test]
1781 fn test_alias() {
1782 let e = alias(column("first_name", None), "name");
1783 assert!(matches!(e, Expr::Alias { name, .. } if name == "name"));
1784 }
1785
1786 #[test]
1787 fn test_subquery_and_exists() {
1788 let inner = select(&["1"]).from("users").where_clause("id = 1").build();
1789 let sub = subquery(inner.clone());
1790 assert!(matches!(sub, Expr::Subquery(_)));
1791
1792 let ex = exists(inner, false);
1793 assert!(matches!(ex, Expr::Exists { negated: false, .. }));
1794 }
1795
1796 #[test]
1797 fn test_star_and_qualified_star() {
1798 let s = star();
1799 assert!(matches!(s, Expr::Star));
1800
1801 let qs = qualified_star("users");
1802 assert!(matches!(qs, Expr::QualifiedWildcard { table } if table == "users"));
1803 }
1804
1805 #[test]
1806 fn test_complex_query() {
1807 let query = select(&["u.id", "u.name", "COUNT(o.id) AS order_count"])
1809 .from("users")
1810 .join("orders", "u.id = o.user_id")
1811 .where_clause("u.active = true")
1812 .and_where("o.created_at > '2024-01-01'")
1813 .group_by(&["u.id", "u.name"])
1814 .having("COUNT(o.id) > 0")
1815 .order_by(&["order_count DESC"])
1816 .limit(10)
1817 .build();
1818
1819 let sql = generate(&query, Dialect::Postgres);
1820 assert!(sql.contains("SELECT"));
1821 assert!(sql.contains("JOIN"));
1822 assert!(sql.contains("WHERE"));
1823 assert!(sql.contains("GROUP BY"));
1824 assert!(sql.contains("HAVING"));
1825 assert!(sql.contains("ORDER BY"));
1826 assert!(sql.contains("LIMIT"));
1827 }
1828
1829 #[test]
1830 fn test_subquery_in_from() {
1831 let inner = select(&["id", "name"])
1832 .from("users")
1833 .where_clause("active = true")
1834 .build();
1835 let outer = select(&["*"]).from_subquery(inner, "active_users").build();
1836
1837 let sql = generate(&outer, Dialect::Ansi);
1838 assert!(sql.contains("FROM (SELECT"));
1839 assert!(sql.contains(") AS active_users"));
1840 }
1841}