1use crate::core::{add_to_where, sql_where_items, Whereable};
2use crate::core::{OrderItem, WhereItem};
3use crate::sqlx_exec;
4use crate::utils::{x_column_name, x_table_name};
5use crate::{SqlBuilder, SqlxBindable};
6use async_trait::async_trait;
7use sqlx::{Executor, FromRow, Postgres};
8
9pub fn select<'a>() -> SelectSqlBuilder<'a> {
10 SelectSqlBuilder {
11 table: None,
12 columns: None,
13 and_wheres: Vec::new(),
14 order_bys: None,
15 limit: None,
16 offset: None,
17 }
18}
19
20pub struct SelectSqlBuilder<'a> {
21 table: Option<String>,
22 columns: Option<Vec<String>>,
23 and_wheres: Vec<WhereItem<'a>>,
24 order_bys: Option<Vec<OrderItem>>,
25 limit: Option<i64>,
26 offset: Option<i64>,
27}
28
29impl<'a> SelectSqlBuilder<'a> {
30 pub fn and_where_eq<T: 'a + SqlxBindable + Send + Sync>(mut self, name: &str, val: T) -> Self {
31 add_to_where(&mut self.and_wheres, name, "=", val);
32 self
33 }
34
35 pub fn and_where<T: 'a + SqlxBindable + Send + Sync>(mut self, name: &str, op: &'static str, val: T) -> Self {
36 add_to_where(&mut self.and_wheres, name, op, val);
37 self
38 }
39
40 pub fn table(mut self, table: &str) -> Self {
41 self.table = Some(table.to_string());
42 self
43 }
44
45 pub fn columns(mut self, names: &[&str]) -> Self {
46 self.columns = Some(names.iter().map(|s| s.to_string()).collect());
47 self
48 }
49
50 pub fn order_bys(mut self, odrs: &[&str]) -> Self {
51 self.order_bys = Some(odrs.iter().copied().map(|o| o.into()).collect());
52 self
53 }
54
55 pub fn order_by(mut self, odr: &str) -> Self {
56 self.order_bys = Some(vec![odr.into()]);
57 self
58 }
59
60 pub fn limit(mut self, limit: i64) -> Self {
61 self.limit = Some(limit);
62 self
63 }
64
65 pub fn offset(mut self, offset: i64) -> Self {
66 self.offset = Some(offset);
67 self
68 }
69
70 pub async fn exec<'q, DB>(&'a self, db_pool: DB) -> Result<u64, sqlx::Error>
71 where
72 DB: Executor<'q, Database = Postgres>,
73 {
74 sqlx_exec::exec(db_pool, self).await
75 }
76
77 pub async fn fetch_one<'e, DB, D>(&'a self, db_pool: DB) -> Result<D, sqlx::Error>
78 where
79 DB: Executor<'e, Database = Postgres>,
80 D: for<'r> FromRow<'r, sqlx::postgres::PgRow> + Unpin + Send,
81 {
82 sqlx_exec::fetch_as_one::<DB, D, _>(db_pool, self).await
83 }
84
85 pub async fn fetch_optional<'e, DB, D>(&'a self, db_pool: DB) -> Result<Option<D>, sqlx::Error>
86 where
87 DB: Executor<'e, Database = Postgres>,
88 D: for<'r> FromRow<'r, sqlx::postgres::PgRow> + Unpin + Send,
89 {
90 sqlx_exec::fetch_as_optional::<DB, D, _>(db_pool, self).await
91 }
92
93 pub async fn fetch_all<'e, DB, D>(&'a self, db_pool: DB) -> Result<Vec<D>, sqlx::Error>
94 where
95 DB: Executor<'e, Database = Postgres>,
96 D: for<'r> FromRow<'r, sqlx::postgres::PgRow> + Unpin + Send,
97 {
98 sqlx_exec::fetch_as_all::<DB, D, _>(db_pool, self).await
99 }
100}
101
102impl<'a> Whereable<'a> for SelectSqlBuilder<'a> {
103 fn and_where_eq<V: 'a + SqlxBindable + Send + Sync>(self, name: &str, val: V) -> Self {
104 SelectSqlBuilder::and_where_eq(self, name, val)
105 }
106
107 fn and_where<V: 'a + SqlxBindable + Send + Sync>(self, name: &str, op: &'static str, val: V) -> Self {
108 SelectSqlBuilder::and_where(self, name, op, val)
109 }
110}
111
112#[async_trait]
113impl<'a> SqlBuilder<'a> for SelectSqlBuilder<'a> {
114 fn sql(&self) -> String {
115 let mut sql = String::from("SELECT ");
119
120 match &self.columns {
123 Some(columns) => {
124 let names = columns.iter().map(|c| x_column_name(c)).collect::<Vec<String>>().join(", ");
125 sql.push_str(&format!("{} ", names));
126 }
127 None => sql.push_str(&format!("{} ", "*")),
128 };
129
130 if let Some(table) = &self.table {
132 sql.push_str("FROM ");
133 sql.push_str(&x_table_name(table));
134 }
135
136 if !self.and_wheres.is_empty() {
138 let sql_where = sql_where_items(&self.and_wheres, 1);
139 sql.push_str(&format!("WHERE {} ", &sql_where));
140 }
141
142 if let Some(order_bys) = &self.order_bys {
144 let sql_order_bys = order_bys
145 .iter()
146 .map::<String, _>(|o| o.into())
147 .collect::<Vec<String>>()
148 .join(", ");
149 sql.push_str(&format!("ORDER BY {} ", sql_order_bys))
150 }
151
152 if let Some(limit) = &self.limit {
154 sql.push_str(&format!("LIMIT {limit} "))
155 }
156
157 if let Some(offset) = &self.offset {
159 sql.push_str(&format!("OFFSET {offset} "))
160 }
161
162 sql
163 }
164
165 fn vals(&'a self) -> Box<dyn Iterator<Item = &Box<dyn SqlxBindable + 'a + Send + Sync>> + 'a + Send> {
166 let iter = self.and_wheres.iter().map(|wi| &wi.val);
167 Box::new(iter)
168 }
169
170 async fn exec<'q, DB>(&'a self, db_pool: DB) -> Result<u64, sqlx::Error>
171 where
172 DB: Executor<'q, Database = Postgres>,
173 {
174 Self::exec(self, db_pool).await
175 }
176
177 async fn fetch_one<'e, DB, D>(&'a self, db_pool: DB) -> Result<D, sqlx::Error>
178 where
179 DB: Executor<'e, Database = Postgres>,
180 D: for<'r> FromRow<'r, sqlx::postgres::PgRow> + Unpin + Send,
181 {
182 Self::fetch_one::<DB, D>(self, db_pool).await
183 }
184
185 async fn fetch_optional<'e, DB, D>(&'a self, db_pool: DB) -> Result<Option<D>, sqlx::Error>
186 where
187 DB: Executor<'e, Database = Postgres>,
188 D: for<'r> FromRow<'r, sqlx::postgres::PgRow> + Unpin + Send,
189 {
190 Self::fetch_optional::<DB, D>(self, db_pool).await
191 }
192
193 async fn fetch_all<'e, DB, D>(&'a self, db_pool: DB) -> Result<Vec<D>, sqlx::Error>
194 where
195 DB: Executor<'e, Database = Postgres>,
196 D: for<'r> FromRow<'r, sqlx::postgres::PgRow> + Unpin + Send,
197 {
198 Self::fetch_all::<DB, D>(self, db_pool).await
199 }
200}