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::{AssertSqlSafe, Executor};
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<DB, Model>
41where
42 DB: sqlx::Database,
43{
44 pub query: Select,
45 arguments: QueryBuilderArgs<DB>,
46 model: PhantomData<Model>,
47 placeholder: Placeholder,
48}
49
50impl<DB, M> SelectQueryBuilder<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{
55 pub async fn fetch_all<'executor, E>(self, db: E) -> Result<Vec<M>>
56 where
57 E: Executor<'executor, Database = DB>,
58 {
59 let (text, args) = self.into_query_and_args()?;
60 sqlx::query_as_with::<DB, M, _>(AssertSqlSafe(text), args)
61 .fetch_all(db)
62 .await
63 .map_err(Error::from)
64 }
65
66 pub async fn fetch_one<'executor, E>(mut self, db: E) -> Result<M>
67 where
68 E: Executor<'executor, Database = DB>,
69 {
70 if self.query.limit.is_none() {
71 self.query.limit = Some(1);
72 }
73 let (text, args) = self.into_query_and_args()?;
74 sqlx::query_as_with::<DB, M, _>(AssertSqlSafe(text), args)
75 .fetch_one(db)
76 .await
77 .map_err(Error::from)
78 }
79
80 pub async fn fetch_optional<'executor, E>(mut self, db: E) -> Result<Option<M>>
81 where
82 E: Executor<'executor, Database = DB>,
83 {
84 if self.query.limit.is_none() {
85 self.query.limit = Some(1);
86 }
87 let (text, args) = self.into_query_and_args()?;
88 sqlx::query_as_with::<DB, M, _>(AssertSqlSafe(text), args)
89 .fetch_optional(db)
90 .await
91 .map_err(Error::from)
92 }
93
94 pub fn with(mut self, name: &str, query: &str) -> Self {
95 self.query = self.query.with_raw(name, query);
96 self
97 }
98
99 pub fn select(mut self, column: impl Into<String>) -> Self {
105 self.query = self.query.select_raw(column.into());
106 self
107 }
108
109 pub fn where_(mut self, clause: &'static str) -> Self {
123 self.query = self.query.where_raw(clause);
124 self
125 }
126
127 pub fn where_bind<'t, T>(mut self, clause: &'static str, value: T) -> Self
129 where
130 T: Send + sqlx::Type<DB> + sqlx::Encode<'t, DB>,
131 {
132 self.query = self.query.where_raw(clause);
133 self.arguments.add(value);
134 self
135 }
136 pub fn dangerous_where(mut self, clause: &str) -> Self {
139 self.query = self.query.where_raw(clause);
140 self
141 }
142
143 pub fn join(mut self, join_description: JoinDescription) -> Self {
144 match &join_description {
145 JoinDescription::ManyToOne {
146 columns,
147 foreign_table,
148 field,
149 foreign_key,
150 local_column,
151 } => {
152 let join = sql::query::Join {
153 typ: sql::query::JoinType::Left,
154 table: sql::query::JoinTable::Table {
155 schema: None,
156 table: foreign_table.to_string(),
157 },
158 alias: Some(field.to_string()),
159 criteria: criteria(M::table_name(), local_column, field, foreign_key),
160 };
161 self.query.join.push(join);
162 self.query.columns.extend(select_columns(columns, field))
163 }
164 }
165 self
166 }
167
168 #[doc(hidden)]
169 #[deprecated(note = "Please use `where_` instead")]
170 pub fn filter(self, clause: &'static str) -> Self {
171 self.where_(clause)
172 }
173
174 pub fn having(mut self, clause: &str) -> Self {
176 self.query = self.query.having(Where::Expr(Expr::Raw(clause.to_string())));
177 self
178 }
179
180 pub fn group_by(mut self, clause: &str) -> Self {
185 self.query = self.query.group_by(clause);
186 self
187 }
188
189 pub fn order_by(mut self, order: OrderBy) -> Self {
195 self.query = self.query.order_by(order);
196 self
197 }
198
199 pub fn order_asc(mut self, clause: &str) -> Self {
200 self.query = self.query.order_asc(clause);
201 self
202 }
203
204 pub fn order_desc(mut self, clause: &str) -> Self {
205 self.query = self.query.order_desc(clause);
206 self
207 }
208
209 pub fn limit(mut self, limit: usize) -> Self {
211 self.query = self.query.limit(limit);
212 self
213 }
214
215 pub fn offset(mut self, offset: usize) -> Self {
217 self.query = self.query.offset(offset);
218 self
219 }
220
221 pub fn bind<'t, T>(mut self, value: T) -> Self
223 where
224 T: Send + sqlx::Type<DB> + sqlx::Encode<'t, DB>,
225 {
226 self.arguments.add(value);
227 self
228 }
229
230 pub fn into_query_and_args(mut self) -> Result<(String, QueryBuilderArgs<DB>)> {
231 let q = self.query.to_sql(DB::dialect());
232 let args = self.arguments;
233 let (q, placeholder_count) = util::replace_placeholders(&q, &mut self.placeholder)?;
234 if placeholder_count != args.len() {
235 return Err(Error::OrmliteError(format!(
236 "Failing to build query. {} placeholders were found in the query, but \
237 {} arguments were provided.",
238 placeholder_count,
239 args.len(),
240 )));
241 }
242 Ok((q, args))
243 }
244}
245
246impl<DB: sqlx::Database + DatabaseMetadata, M: Model<DB>> Default for SelectQueryBuilder<DB, M> {
247 fn default() -> Self {
248 Self {
249 query: Select::default().from(M::table_name()),
250 arguments: QueryBuilderArgs::default(),
251 model: PhantomData,
252 placeholder: DB::placeholder(),
253 }
254 }
255}