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}