ormlite_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::{Expr, OrderBy, ToSql};
6
7use crate::join::{criteria, select_columns, JoinDescription};
8use sqlmo::{query::Where, Select};
9use sqlx::{Executor, IntoArguments};
10use std::marker::PhantomData;
11
12pub use sqlmo::query::Direction;
13
14pub trait DatabaseMetadata {
16 fn dialect() -> sqlmo::Dialect;
17 fn placeholder() -> Placeholder;
18}
19
20#[cfg(feature = "postgres")]
21impl DatabaseMetadata for sqlx::postgres::Postgres {
22 fn dialect() -> sqlmo::Dialect {
23 sqlmo::Dialect::Postgres
24 }
25
26 fn placeholder() -> Placeholder {
27 Placeholder::dollar_sign()
28 }
29}
30
31#[cfg(feature = "sqlite")]
32impl DatabaseMetadata for sqlx::sqlite::Sqlite {
33 fn dialect() -> sqlmo::Dialect {
34 sqlmo::Dialect::Sqlite
35 }
36
37 fn placeholder() -> Placeholder {
38 Placeholder::question_mark()
39 }
40}
41
42pub struct SelectQueryBuilder<'args, DB, Model>
43where
44 DB: sqlx::Database,
45{
46 pub query: Select,
47 arguments: QueryBuilderArgs<'args, DB>,
48 model: PhantomData<Model>,
49 gen: Placeholder,
50}
51
52impl<'args, DB, M> SelectQueryBuilder<'args, DB, M>
53where
54 M: Sized + Send + Sync + Unpin + for<'r> sqlx::FromRow<'r, DB::Row> + 'static + Model<DB>,
55 DB: sqlx::Database + DatabaseMetadata,
56 DB::Arguments<'args>: IntoArguments<'args, DB>,
57{
58 pub async fn fetch_all<'executor, E>(self, db: E) -> Result<Vec<M>>
59 where
60 E: Executor<'executor, Database = DB>,
61 {
62 let (text, args) = self.into_query_and_args()?;
63 let z: &str = &text;
64 util::query_as_with_recast_lifetime::<DB, M>(z, args)
65 .fetch_all(db)
66 .await
67 .map_err(Error::from)
68 }
69
70 pub async fn fetch_one<'executor, E>(mut self, db: E) -> Result<M>
71 where
72 E: Executor<'executor, Database = DB>,
73 {
74 if self.query.limit.is_none() {
75 self.query.limit = Some(1);
76 }
77 let (text, args) = self.into_query_and_args()?;
78 let z: &str = &text;
79 util::query_as_with_recast_lifetime::<DB, M>(z, args)
80 .fetch_one(db)
81 .await
82 .map_err(Error::from)
83 }
84
85 pub async fn fetch_optional<'executor, E>(mut self, db: E) -> Result<Option<M>>
86 where
87 E: Executor<'executor, Database = DB>,
88 {
89 if self.query.limit.is_none() {
90 self.query.limit = Some(1);
91 }
92 let (text, args) = self.into_query_and_args()?;
93 let z: &str = &text;
94 util::query_as_with_recast_lifetime::<DB, M>(z, args)
95 .fetch_optional(db)
96 .await
97 .map_err(Error::from)
98 }
99
100 pub fn with(mut self, name: &str, query: &str) -> Self {
101 self.query = self.query.with_raw(name, query);
102 self
103 }
104
105 pub fn select(mut self, column: impl Into<String>) -> Self {
111 self.query = self.query.select_raw(column.into());
112 self
113 }
114
115 pub fn where_(mut self, clause: &'static str) -> Self {
129 self.query = self.query.where_raw(clause);
130 self
131 }
132
133 pub fn where_bind<T>(mut self, clause: &'static str, value: T) -> Self
135 where
136 T: 'args + Send + sqlx::Type<DB> + sqlx::Encode<'args, DB>,
137 {
138 self.query = self.query.where_raw(clause);
139 self.arguments.add(value);
140 self
141 }
142 pub fn dangerous_where(mut self, clause: &str) -> Self {
145 self.query = self.query.where_raw(clause);
146 self
147 }
148
149 pub fn join(mut self, join_description: JoinDescription) -> Self {
150 match &join_description {
151 JoinDescription::ManyToOne {
152 columns,
153 foreign_table,
154 field,
155 foreign_key,
156 local_column,
157 } => {
158 let join = sqlmo::query::Join {
159 typ: sqlmo::query::JoinType::Left,
160 table: sqlmo::query::JoinTable::Table {
161 schema: None,
162 table: foreign_table.to_string(),
163 },
164 alias: Some(field.to_string()),
165 criteria: criteria(M::table_name(), local_column, field, foreign_key),
166 };
167 self.query.join.push(join);
168 self.query.columns.extend(select_columns(columns, field))
169 }
170 }
171 self
172 }
173
174 #[doc(hidden)]
175 #[deprecated(note = "Please use `where_` instead")]
176 pub fn filter(self, clause: &'static str) -> Self {
177 self.where_(clause)
178 }
179
180 pub fn having(mut self, clause: &str) -> Self {
182 self.query = self.query.having(Where::Expr(Expr::Raw(clause.to_string())));
183 self
184 }
185
186 pub fn group_by(mut self, clause: &str) -> Self {
191 self.query = self.query.group_by(clause);
192 self
193 }
194
195 pub fn order_by(mut self, order: OrderBy) -> Self {
201 self.query = self.query.order_by(order);
202 self
203 }
204
205 pub fn order_asc(mut self, clause: &str) -> Self {
206 self.query = self.query.order_asc(clause);
207 self
208 }
209
210 pub fn order_desc(mut self, clause: &str) -> Self {
211 self.query = self.query.order_desc(clause);
212 self
213 }
214
215 pub fn limit(mut self, limit: usize) -> Self {
217 self.query = self.query.limit(limit);
218 self
219 }
220
221 pub fn offset(mut self, offset: usize) -> Self {
223 self.query = self.query.offset(offset);
224 self
225 }
226
227 pub fn bind<T>(mut self, value: T) -> Self
229 where
230 T: 'args + Send + sqlx::Type<DB> + sqlx::Encode<'args, DB>,
231 {
232 self.arguments.add(value);
233 self
234 }
235
236 pub fn into_query_and_args(mut self) -> Result<(String, QueryBuilderArgs<'args, DB>)> {
237 let q = self.query.to_sql(DB::dialect());
238 let args = self.arguments;
239 let (q, placeholder_count) = util::replace_placeholders(&q, &mut self.gen)?;
240 if placeholder_count != args.len() {
241 return Err(Error::OrmliteError(format!(
242 "Failing to build query. {} placeholders were found in the query, but \
243 {} arguments were provided.",
244 placeholder_count,
245 args.len(),
246 )));
247 }
248 Ok((q, args))
249 }
250}
251
252impl<'args, DB: sqlx::Database + DatabaseMetadata, M: Model<DB>> Default for SelectQueryBuilder<'args, DB, M> {
253 fn default() -> Self {
254 Self {
255 query: Select::default().from(M::table_name()),
256 arguments: QueryBuilderArgs::default(),
257 model: PhantomData,
258 gen: DB::placeholder(),
259 }
260 }
261}