diesel/expression/mod.rs
1//! AST types representing various typed SQL expressions.
2//!
3//! Almost all types implement either [`Expression`](trait.Expression.html) or
4//! [`AsExpression`](trait.AsExpression.html).
5//!
6//! The most common expression to work with is a
7//! [`Column`](../query_source/trait.Column.html). There are various methods
8//! that you can call on these, found in
9//! [`expression_methods`](../expression_methods).
10//!
11//! You can also use numeric operators such as `+` on expressions of the
12//! appropriate type.
13//!
14//! Any primitive which implements [`ToSql`](../serialize/trait.ToSql.html) will
15//! also implement [`AsExpression`](trait.AsExpression.html), allowing it to be
16//! used as an argument to any of the methods described here.
17#[macro_use]
18#[doc(hidden)]
19pub mod ops;
20#[doc(hidden)]
21#[macro_use]
22pub mod functions;
23
24#[doc(hidden)]
25pub mod array_comparison;
26#[doc(hidden)]
27pub mod bound;
28#[doc(hidden)]
29pub mod coerce;
30#[doc(hidden)]
31pub mod count;
32#[doc(hidden)]
33pub mod exists;
34#[doc(hidden)]
35pub mod grouped;
36#[doc(hidden)]
37pub mod helper_types;
38mod not;
39#[doc(hidden)]
40pub mod nullable;
41#[doc(hidden)]
42#[macro_use]
43pub mod operators;
44#[doc(hidden)]
45pub mod sql_literal;
46#[doc(hidden)]
47pub mod subselect;
48
49#[doc(hidden)]
50#[allow(non_camel_case_types)]
51pub mod dsl {
52 use dsl::SqlTypeOf;
53
54 #[doc(inline)]
55 pub use super::count::*;
56 #[doc(inline)]
57 pub use super::exists::exists;
58 #[doc(inline)]
59 pub use super::functions::aggregate_folding::*;
60 #[doc(inline)]
61 pub use super::functions::aggregate_ordering::*;
62 #[doc(inline)]
63 pub use super::functions::date_and_time::*;
64 #[doc(inline)]
65 pub use super::not::not;
66 #[doc(inline)]
67 pub use super::sql_literal::sql;
68
69 #[cfg(feature = "postgres")]
70 pub use pg::expression::dsl::*;
71
72 /// The return type of [`count(expr)`](../dsl/fn.count.html)
73 pub type count<Expr> = super::count::count::HelperType<SqlTypeOf<Expr>, Expr>;
74
75 /// The return type of [`count_star)(`](../dsl/fn.count_star.html)
76 pub type count_star = super::count::CountStar;
77
78 /// The return type of [`date(expr)`](../dsl/fn.date.html)
79 pub type date<Expr> = super::functions::date_and_time::date::HelperType<Expr>;
80}
81
82#[doc(inline)]
83pub use self::sql_literal::{SqlLiteral, UncheckedBind};
84
85use backend::Backend;
86use dsl::AsExprOf;
87
88/// Represents a typed fragment of SQL.
89///
90/// Apps should not need to implement this type directly, but it may be common
91/// to use this in where clauses. Libraries should consider using
92/// [`diesel_infix_operator!`](../macro.diesel_infix_operator.html) or
93/// [`diesel_postfix_operator!`](../macro.diesel_postfix_operator.html) instead of
94/// implementing this directly.
95pub trait Expression {
96 /// The type that this expression represents in SQL
97 type SqlType;
98}
99
100impl<T: Expression + ?Sized> Expression for Box<T> {
101 type SqlType = T::SqlType;
102}
103
104impl<'a, T: Expression + ?Sized> Expression for &'a T {
105 type SqlType = T::SqlType;
106}
107
108/// Converts a type to its representation for use in Diesel's query builder.
109///
110/// This trait is used directly. Apps should typically use [`IntoSql`] instead.
111///
112/// Implementations of this trait will generally do one of 3 things:
113///
114/// - Return `self` for types which are already parts of Diesel's query builder
115/// - Perform some implicit coercion (for example, allowing [`now`] to be used as
116/// both [`Timestamp`] and [`Timestamptz`].
117/// - Indicate that the type has data which will be sent separately from the
118/// query. This is generally referred as a "bind parameter". Types which
119/// implement [`ToSql`] will generally implement `AsExpression` this way.
120///
121/// [`IntoSql`]: trait.IntoSql.html
122/// [`now`]: ../dsl/struct.now.html
123/// [`Timestamp`]: ../sql_types/struct.Timestamp.html
124/// [`Timestamptz`]: ../pg/types/sql_types/struct.Timestamptz.html
125/// [`ToSql`]: ../serialize/trait.ToSql.html
126///
127/// ## Deriving
128///
129/// This trait can be automatically derived for any type which implements `ToSql`.
130/// The type must be annotated with `#[sql_type = "SomeType"]`.
131/// If that annotation appears multiple times,
132/// implementations will be generated for each one of them.
133///
134/// This will generate the following impls:
135///
136/// - `impl AsExpression<SqlType> for YourType`
137/// - `impl AsExpression<Nullable<SqlType>> for YourType`
138/// - `impl AsExpression<SqlType> for &'a YourType`
139/// - `impl AsExpression<Nullable<SqlType>> for &'a YourType`
140/// - `impl AsExpression<SqlType> for &'a &'b YourType`
141/// - `impl AsExpression<Nullable<SqlType>> for &'a &'b YourType`
142///
143/// If your type is unsized,
144/// you can specify this by adding the annotation `#[diesel(not_sized)]`.
145/// This will skip the impls for non-reference types.
146pub trait AsExpression<T> {
147 /// The expression being returned
148 type Expression: Expression<SqlType = T>;
149
150 /// Perform the conversion
151 fn as_expression(self) -> Self::Expression;
152}
153
154impl<T: Expression> AsExpression<T::SqlType> for T {
155 type Expression = Self;
156
157 fn as_expression(self) -> Self {
158 self
159 }
160}
161
162/// Converts a type to its representation for use in Diesel's query builder.
163///
164/// This trait only exists to make usage of `AsExpression` more ergonomic when
165/// the `SqlType` cannot be inferred. It is generally used when you need to use
166/// a Rust value as the left hand side of an expression, or when you want to
167/// select a constant value.
168///
169/// # Example
170///
171/// ```rust
172/// # #[macro_use] extern crate diesel;
173/// # include!("../doctest_setup.rs");
174/// # use schema::users;
175/// #
176/// # fn main() {
177/// use diesel::sql_types::Text;
178/// # let conn = establish_connection();
179/// let names = users::table
180/// .select("The Amazing ".into_sql::<Text>().concat(users::name))
181/// .load(&conn);
182/// let expected_names = vec![
183/// "The Amazing Sean".to_string(),
184/// "The Amazing Tess".to_string(),
185/// ];
186/// assert_eq!(Ok(expected_names), names);
187/// # }
188/// ```
189pub trait IntoSql {
190 /// Convert `self` to an expression for Diesel's query builder.
191 ///
192 /// There is no difference in behavior between `x.into_sql::<Y>()` and
193 /// `AsExpression::<Y>::as_expression(x)`.
194 fn into_sql<T>(self) -> AsExprOf<Self, T>
195 where
196 Self: AsExpression<T> + Sized,
197 {
198 self.as_expression()
199 }
200
201 /// Convert `&self` to an expression for Diesel's query builder.
202 ///
203 /// There is no difference in behavior between `x.as_sql::<Y>()` and
204 /// `AsExpression::<Y>::as_expression(&x)`.
205 fn as_sql<'a, T>(&'a self) -> AsExprOf<&'a Self, T>
206 where
207 &'a Self: AsExpression<T>,
208 {
209 self.as_expression()
210 }
211}
212
213impl<T> IntoSql for T {}
214
215/// Indicates that all elements of an expression are valid given a from clause.
216///
217/// This is used to ensure that `users.filter(posts::id.eq(1))` fails to
218/// compile. This constraint is only used in places where the nullability of a
219/// SQL type doesn't matter (everything except `select` and `returning`). For
220/// places where nullability is important, `SelectableExpression` is used
221/// instead.
222pub trait AppearsOnTable<QS: ?Sized>: Expression {}
223
224impl<T: ?Sized, QS> AppearsOnTable<QS> for Box<T>
225where
226 T: AppearsOnTable<QS>,
227 Box<T>: Expression,
228{
229}
230
231impl<'a, T: ?Sized, QS> AppearsOnTable<QS> for &'a T
232where
233 T: AppearsOnTable<QS>,
234 &'a T: Expression,
235{
236}
237
238/// Indicates that an expression can be selected from a source.
239///
240/// Columns will implement this for their table. Certain special types, like
241/// `CountStar` and `Bound` will implement this for all sources. Most compound
242/// expressions will implement this if each of their parts implement it.
243///
244/// Notably, columns will not implement this trait for the right side of a left
245/// join. To select a column or expression using a column from the right side of
246/// a left join, you must call `.nullable()` on it.
247pub trait SelectableExpression<QS: ?Sized>: AppearsOnTable<QS> {}
248
249impl<T: ?Sized, QS> SelectableExpression<QS> for Box<T>
250where
251 T: SelectableExpression<QS>,
252 Box<T>: AppearsOnTable<QS>,
253{
254}
255
256impl<'a, T: ?Sized, QS> SelectableExpression<QS> for &'a T
257where
258 T: SelectableExpression<QS>,
259 &'a T: AppearsOnTable<QS>,
260{
261}
262
263/// Marker trait to indicate that an expression does not include any aggregate
264/// functions.
265///
266/// Used to ensure that aggregate expressions aren't mixed with
267/// non-aggregate expressions in a select clause, and that they're never
268/// included in a where clause.
269pub trait NonAggregate {}
270
271impl<T: NonAggregate + ?Sized> NonAggregate for Box<T> {}
272
273impl<'a, T: NonAggregate + ?Sized> NonAggregate for &'a T {}
274
275use query_builder::{QueryFragment, QueryId};
276
277/// Helper trait used when boxing expressions.
278///
279/// In Rust you cannot create a trait object with more than one trait.
280/// This type has all of the additional traits you would want when using
281/// `Box<Expression>` as a single trait object.
282///
283/// This is typically used as the return type of a function.
284/// For cases where you want to dynamically construct a query,
285/// [boxing the query] is usually more ergonomic.
286///
287/// [boxing the query]: ../query_dsl/trait.QueryDsl.html#method.into_boxed
288///
289/// # Examples
290///
291/// ```rust
292/// # #[macro_use] extern crate diesel;
293/// # include!("../doctest_setup.rs");
294/// # use schema::users;
295/// use diesel::sql_types::Bool;
296///
297/// # fn main() {
298/// # run_test().unwrap();
299/// # }
300/// #
301/// # fn run_test() -> QueryResult<()> {
302/// # let conn = establish_connection();
303/// enum Search {
304/// Id(i32),
305/// Name(String),
306/// }
307///
308/// # /*
309/// type DB = diesel::sqlite::Sqlite;
310/// # */
311///
312/// fn find_user(search: Search) -> Box<BoxableExpression<users::table, DB, SqlType = Bool>> {
313/// match search {
314/// Search::Id(id) => Box::new(users::id.eq(id)),
315/// Search::Name(name) => Box::new(users::name.eq(name)),
316/// }
317/// }
318///
319/// let user_one = users::table
320/// .filter(find_user(Search::Id(1)))
321/// .first(&conn)?;
322/// assert_eq!((1, String::from("Sean")), user_one);
323///
324/// let tess = users::table
325/// .filter(find_user(Search::Name("Tess".into())))
326/// .first(&conn)?;
327/// assert_eq!((2, String::from("Tess")), tess);
328/// # Ok(())
329/// # }
330/// ```
331pub trait BoxableExpression<QS, DB>
332where
333 DB: Backend,
334 Self: Expression,
335 Self: SelectableExpression<QS>,
336 Self: NonAggregate,
337 Self: QueryFragment<DB>,
338{
339}
340
341impl<QS, T, DB> BoxableExpression<QS, DB> for T
342where
343 DB: Backend,
344 T: Expression,
345 T: SelectableExpression<QS>,
346 T: NonAggregate,
347 T: QueryFragment<DB>,
348{
349}
350
351impl<'a, QS, ST, DB> QueryId for dyn BoxableExpression<QS, DB, SqlType = ST> + 'a {
352 type QueryId = ();
353
354 const HAS_STATIC_QUERY_ID: bool = false;
355}
356
357/// Converts a tuple of values into a tuple of Diesel expressions.
358///
359/// This trait is similar to [`AsExpression`], but it operates on tuples.
360/// The expressions must all be of the same SQL type.
361///
362/// [`AsExpression`]: trait.AsExpression.html
363pub trait AsExpressionList<ST> {
364 /// The final output expression
365 type Expression;
366
367 /// Perform the conversion
368 fn as_expression_list(self) -> Self::Expression;
369}