1use std::marker::PhantomData;
4
5use sea_query::{Expr, Order, PostgresQueryBuilder, Query, SimpleExpr};
6use sea_query_binder::SqlxBinder;
7use sqlx::{FromRow, postgres::PgRow};
8
9use crate::column::Column;
10use crate::model::Model;
11use crate::pool::Pool;
12use crate::Error;
13
14pub struct QueryBuilder<M: Model> {
15 select: sea_query::SelectStatement,
16 _marker: PhantomData<M>,
17}
18
19impl<M: Model> Default for QueryBuilder<M> {
20 fn default() -> Self {
21 Self::new()
22 }
23}
24
25impl<M: Model> QueryBuilder<M>
26where
27 for<'r> M: FromRow<'r, PgRow>,
28{
29 pub fn new() -> Self {
30 let mut select = Query::select();
31 select
32 .from(sea_query::Alias::new(M::TABLE))
33 .columns(M::COLUMNS.iter().map(|c| sea_query::Alias::new(*c)));
34 Self {
35 select,
36 _marker: PhantomData,
37 }
38 }
39
40 pub fn where_eq<T>(mut self, column: Column<M, T>, value: T) -> Self
42 where
43 T: Into<sea_query::Value>,
44 {
45 self.select
46 .and_where(Expr::col(sea_query::Alias::new(column.name())).eq(value));
47 self
48 }
49
50 pub fn where_ne<T>(mut self, column: Column<M, T>, value: T) -> Self
51 where
52 T: Into<sea_query::Value>,
53 {
54 self.select
55 .and_where(Expr::col(sea_query::Alias::new(column.name())).ne(value));
56 self
57 }
58
59 pub fn where_gt<T>(mut self, column: Column<M, T>, value: T) -> Self
60 where
61 T: Into<sea_query::Value>,
62 {
63 self.select
64 .and_where(Expr::col(sea_query::Alias::new(column.name())).gt(value));
65 self
66 }
67
68 pub fn where_lt<T>(mut self, column: Column<M, T>, value: T) -> Self
69 where
70 T: Into<sea_query::Value>,
71 {
72 self.select
73 .and_where(Expr::col(sea_query::Alias::new(column.name())).lt(value));
74 self
75 }
76
77 pub fn where_in<T, I>(mut self, column: Column<M, T>, values: I) -> Self
78 where
79 T: Into<sea_query::Value>,
80 I: IntoIterator<Item = T>,
81 {
82 self.select
83 .and_where(Expr::col(sea_query::Alias::new(column.name())).is_in(values));
84 self
85 }
86
87 pub fn where_raw(mut self, raw: SimpleExpr) -> Self {
88 self.select.and_where(raw);
89 self
90 }
91
92 pub fn order_by<T>(mut self, column: Column<M, T>, ascending: bool) -> Self {
93 self.select.order_by(
94 sea_query::Alias::new(column.name()),
95 if ascending { Order::Asc } else { Order::Desc },
96 );
97 self
98 }
99
100 pub fn order_by_asc<T>(self, column: Column<M, T>) -> Self {
101 self.order_by(column, true)
102 }
103
104 pub fn order_by_desc<T>(self, column: Column<M, T>) -> Self {
105 self.order_by(column, false)
106 }
107
108 pub fn limit(mut self, n: u64) -> Self {
109 self.select.limit(n);
110 self
111 }
112
113 pub fn offset(mut self, n: u64) -> Self {
114 self.select.offset(n);
115 self
116 }
117
118 pub async fn get(self, pool: &Pool) -> Result<Vec<M>, Error> {
119 let (sql, values) = self.select.build_sqlx(PostgresQueryBuilder);
120 let rows = sqlx::query_as_with::<_, M, _>(&sql, values)
121 .fetch_all(pool)
122 .await?;
123 Ok(rows)
124 }
125
126 pub async fn first(mut self, pool: &Pool) -> Result<Option<M>, Error> {
127 self.select.limit(1);
128 let (sql, values) = self.select.build_sqlx(PostgresQueryBuilder);
129 let row = sqlx::query_as_with::<_, M, _>(&sql, values)
130 .fetch_optional(pool)
131 .await?;
132 Ok(row)
133 }
134
135 pub async fn count(self, pool: &Pool) -> Result<i64, Error> {
136 let mut count_query = self.select.clone();
137 count_query.clear_selects();
138 count_query.expr(Expr::count(Expr::col(sea_query::Alias::new("*"))));
139 let (sql, values) = count_query.build_sqlx(PostgresQueryBuilder);
140 let (count,): (i64,) = sqlx::query_as_with(&sql, values).fetch_one(pool).await?;
141 Ok(count)
142 }
143}