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