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