ormlitex_core/query_builder/
select.rs1use crate::error::{Error, Result};
2use crate::model::Model;
3use crate::query_builder::args::QueryBuilderArgs;
4use crate::query_builder::{util, Placeholder};
5use sqlmo::ToSql;
6
7use sqlx::database::HasArguments;
8
9use crate::join::JoinDescription;
10use sqlmo::{query::Where, Select};
11use sqlx::{Executor, IntoArguments};
12use std::marker::PhantomData;
13
14pub use sqlmo::query::Direction;
15
16pub trait DatabaseMetadata {
18 fn dialect() -> sqlmo::Dialect;
19 fn placeholder() -> Placeholder;
20}
21
22#[cfg(feature = "postgres")]
23impl DatabaseMetadata for sqlx::postgres::Postgres {
24 fn dialect() -> sqlmo::Dialect {
25 sqlmo::Dialect::Postgres
26 }
27
28 fn placeholder() -> Placeholder {
29 Placeholder::dollar_sign()
30 }
31}
32
33#[cfg(feature = "sqlite")]
34impl DatabaseMetadata for sqlx::sqlite::Sqlite {
35 fn dialect() -> sqlmo::Dialect {
36 sqlmo::Dialect::Sqlite
37 }
38
39 fn placeholder() -> Placeholder {
40 Placeholder::question_mark()
41 }
42}
43
44pub struct SelectQueryBuilder<'args, DB, Model>
45where
46 DB: sqlx::Database,
47{
48 pub query: Select,
49 arguments: QueryBuilderArgs<'args, DB>,
50 model: PhantomData<Model>,
51 gen: Placeholder,
52}
53
54impl<'args, DB, M> SelectQueryBuilder<'args, DB, M>
55where
56 M: Sized + Send + Sync + Unpin + for<'r> sqlx::FromRow<'r, DB::Row> + 'static + Model<DB>,
57 DB: sqlx::Database + DatabaseMetadata,
58 <DB as HasArguments<'args>>::Arguments: IntoArguments<'args, DB>,
59{
60 pub async fn fetch_all<'executor, E>(self, db: E) -> Result<Vec<M>>
61 where
62 E: Executor<'executor, Database = DB>,
63 {
64 let (text, args) = self.into_query_and_args()?;
65 let z: &str = &text;
66 util::query_as_with_recast_lifetime::<DB, M>(z, args)
67 .fetch_all(db)
68 .await
69 .map_err(Error::from)
70 }
71
72 pub async fn fetch_one<'executor, E>(self, db: E) -> Result<M>
73 where
74 E: Executor<'executor, Database = DB>,
75 {
76 let (text, args) = self.into_query_and_args()?;
77 let z: &str = &text;
78 util::query_as_with_recast_lifetime::<DB, M>(z, args)
79 .fetch_one(db)
80 .await
81 .map_err(Error::from)
82 }
83
84 pub async fn fetch_optional<'executor, E>(self, db: E) -> Result<Option<M>>
85 where
86 E: Executor<'executor, Database = DB>,
87 {
88 let (text, args) = self.into_query_and_args()?;
89 let z: &str = &text;
90 util::query_as_with_recast_lifetime::<DB, M>(z, args)
91 .fetch_optional(db)
92 .await
93 .map_err(Error::from)
94 }
95
96 pub fn with(mut self, name: &str, query: &str) -> Self {
97 self.query = self.query.with_raw(name, query);
98 self
99 }
100
101 pub fn select(mut self, column: impl Into<String>) -> Self {
107 self.query = self.query.select_raw(column.into());
108 self
109 }
110
111 pub fn where_(mut self, clause: &'static str) -> Self {
125 self.query = self.query.where_raw(clause);
126 self
127 }
128
129 pub fn where_bind<T>(mut self, clause: &'static str, value: T) -> Self
131 where
132 T: 'args + Send + sqlx::Type<DB> + sqlx::Encode<'args, DB>,
133 {
134 self.query = self.query.where_raw(clause);
135 self.arguments.add(value);
136 self
137 }
138
139 pub fn where_bind_option<T>(self, clause: &'static str, value: Option<T>) -> Self
142 where
143 T: 'args + Send + sqlx::Type<DB> + sqlx::Encode<'args, DB>,
144 {
145 match value {
146 Some(value) => self.where_bind(clause, value),
147 None => self,
148 }
149 }
150
151 pub fn dangerous_where(mut self, clause: &str) -> Self {
154 self.query = self.query.where_raw(clause);
155 self
156 }
157
158 pub fn join(mut self, join_description: JoinDescription) -> Self {
159 self.query = self
160 .query
161 .join(join_description.to_join_clause(M::table_name()));
162 self.query.columns.extend(join_description.select_clause());
163 self
164 }
165
166 #[doc(hidden)]
167 #[deprecated(note = "Please use `where_` instead")]
168 pub fn filter(self, clause: &'static str) -> Self {
169 self.where_(clause)
170 }
171
172 pub fn having(mut self, clause: &str) -> Self {
174 self.query = self.query.having(Where::Raw(clause.to_string()));
175 self
176 }
177
178 pub fn group_by(mut self, clause: &str) -> Self {
183 self.query = self.query.group_by(clause);
184 self
185 }
186
187 pub fn order_by(mut self, clause: &str, direction: Direction) -> Self {
193 self.query = self.query.order_by(clause, direction);
194 self
195 }
196
197 pub fn order_asc(mut self, clause: &str) -> Self {
198 self.query = self.query.order_asc(clause);
199 self
200 }
201
202 pub fn order_desc(mut self, clause: &str) -> Self {
203 self.query = self.query.order_desc(clause);
204 self
205 }
206
207 pub fn limit(mut self, limit: usize) -> Self {
209 self.query = self.query.limit(limit);
210 self
211 }
212
213 pub fn offset(mut self, offset: usize) -> Self {
215 self.query = self.query.offset(offset);
216 self
217 }
218
219 pub fn bind<T>(mut self, value: T) -> Self
221 where
222 T: 'args + Send + sqlx::Type<DB> + sqlx::Encode<'args, DB>,
223 {
224 self.arguments.add(value);
225 self
226 }
227
228 pub fn into_query_and_args(mut self) -> Result<(String, QueryBuilderArgs<'args, DB>)> {
229 let q = self.query.to_sql(DB::dialect());
230 let args = self.arguments;
231 let (q, placeholder_count) = util::replace_placeholders(&q, &mut self.gen)?;
232 if placeholder_count != args.len() {
233 return Err(Error::ormlitexError(format!(
234 "Failing to build query. {} placeholders were found in the query, but \
235 {} arguments were provided.",
236 placeholder_count,
237 args.len(),
238 )));
239 }
240 Ok((q, args))
241 }
242}
243
244impl<'args, DB: sqlx::Database + DatabaseMetadata, M: Model<DB>> Default
245 for SelectQueryBuilder<'args, DB, M>
246{
247 fn default() -> Self {
248 Self {
249 query: Select::default().from(M::table_name()),
250 arguments: QueryBuilderArgs::default(),
251 model: PhantomData,
252 gen: DB::placeholder(),
253 }
254 }
255}