diesel/expression/mod.rs
1//! AST types representing various typed SQL expressions.
2//!
3//! Almost all types implement either [`Expression`] or
4//! [`AsExpression`].
5//!
6//! The most common expression to work with is a
7//! [`Column`](crate::query_source::Column). There are various methods
8//! that you can call on these, found in
9//! [`expression_methods`](crate::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`](crate::serialize::ToSql) will
15//! also implement [`AsExpression`], allowing it to be
16//! used as an argument to any of the methods described here.
17#[macro_use]
18pub(crate) mod ops;
19pub mod functions;
20
21#[cfg(not(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"))]
22pub(crate) mod array_comparison;
23#[cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")]
24pub mod array_comparison;
25pub(crate) mod assume_not_null;
26pub(crate) mod bound;
27mod coerce;
28pub(crate) mod count;
29#[cfg(not(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes"))]
30pub(crate) mod exists;
31#[cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")]
32pub mod exists;
33pub(crate) mod grouped;
34pub(crate) mod helper_types;
35mod not;
36pub(crate) mod nullable;
37#[macro_use]
38pub(crate) mod operators;
39mod case_when;
40pub(crate) mod select_by;
41mod sql_literal;
42pub(crate) mod subselect;
43
44#[cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")]
45pub use self::operators::Concat;
46
47// we allow unreachable_pub here
48// as rustc otherwise shows false positives
49// for every item in this module. We reexport
50// everything from `crate::helper_types::`
51#[allow(non_camel_case_types, unreachable_pub)]
52pub(crate) mod dsl {
53 use crate::dsl::SqlTypeOf;
54
55 #[doc(inline)]
56 pub use super::case_when::case_when;
57 #[doc(inline)]
58 pub use super::count::*;
59 #[doc(inline)]
60 pub use super::exists::exists;
61 #[doc(inline)]
62 pub use super::functions::aggregate_folding::*;
63 #[doc(inline)]
64 pub use super::functions::aggregate_ordering::*;
65 #[doc(inline)]
66 pub use super::functions::date_and_time::*;
67 #[doc(inline)]
68 pub use super::helper_types::{case_when, IntoSql, Otherwise, When};
69 #[doc(inline)]
70 pub use super::not::not;
71 #[doc(inline)]
72 pub use super::sql_literal::sql;
73
74 #[cfg(feature = "postgres_backend")]
75 pub use crate::pg::expression::dsl::*;
76
77 #[cfg(feature = "sqlite")]
78 pub use crate::sqlite::expression::dsl::*;
79
80 /// The return type of [`count(expr)`](crate::dsl::count())
81 pub type count<Expr> = super::count::count<SqlTypeOf<Expr>, Expr>;
82
83 /// The return type of [`count_star()`](crate::dsl::count_star())
84 pub type count_star = super::count::CountStar;
85
86 /// The return type of [`count_distinct()`](crate::dsl::count_distinct())
87 pub type count_distinct<Expr> = super::count::CountDistinct<SqlTypeOf<Expr>, Expr>;
88
89 /// The return type of [`date(expr)`](crate::dsl::date())
90 pub type date<Expr> = super::functions::date_and_time::date<Expr>;
91
92 #[cfg(feature = "mysql_backend")]
93 pub use crate::mysql::query_builder::DuplicatedKeys;
94}
95
96#[doc(inline)]
97pub use self::case_when::CaseWhen;
98#[doc(inline)]
99pub use self::sql_literal::{SqlLiteral, UncheckedBind};
100
101use crate::backend::Backend;
102use crate::dsl::{AsExprOf, AsSelect};
103use crate::sql_types::{HasSqlType, SingleValue, SqlType};
104
105/// Represents a typed fragment of SQL.
106///
107/// Apps should not need to implement this type directly, but it may be common
108/// to use this in where clauses. Libraries should consider using
109/// [`infix_operator!`](crate::infix_operator!) or
110/// [`postfix_operator!`](crate::postfix_operator!) instead of
111/// implementing this directly.
112pub trait Expression {
113 /// The type that this expression represents in SQL
114 type SqlType: TypedExpressionType;
115}
116
117/// Marker trait for possible types of [`Expression::SqlType`]
118///
119pub trait TypedExpressionType {}
120
121/// Possible types for []`Expression::SqlType`]
122///
123pub mod expression_types {
124 use super::{QueryMetadata, TypedExpressionType};
125 use crate::backend::Backend;
126 use crate::sql_types::SingleValue;
127
128 /// Query nodes with this expression type do not have a statically at compile
129 /// time known expression type.
130 ///
131 /// An example for such a query node in diesel itself, is `sql_query` as
132 /// we do not know which fields are returned from such a query at compile time.
133 ///
134 /// For loading values from queries returning a type of this expression, consider
135 /// using [`#[derive(QueryableByName)]`](derive@crate::deserialize::QueryableByName)
136 /// on the corresponding result type.
137 ///
138 #[derive(Clone, Copy, Debug)]
139 pub struct Untyped;
140
141 /// Query nodes which cannot be part of a select clause.
142 ///
143 /// If you see an error message containing `FromSqlRow` and this type
144 /// recheck that you have written a valid select clause
145 ///
146 /// These may notably be used as intermediate Expression nodes of the query builder
147 /// which do not map to actual SQL expressions (for implementation simplicity).
148 #[derive(Debug, Clone, Copy)]
149 pub struct NotSelectable;
150
151 impl TypedExpressionType for Untyped {}
152 impl TypedExpressionType for NotSelectable {}
153
154 impl<ST> TypedExpressionType for ST where ST: SingleValue {}
155
156 impl<DB: Backend> QueryMetadata<Untyped> for DB {
157 fn row_metadata(_: &mut DB::MetadataLookup, row: &mut Vec<Option<DB::TypeMetadata>>) {
158 row.push(None)
159 }
160 }
161}
162
163impl<T: Expression + ?Sized> Expression for Box<T> {
164 type SqlType = T::SqlType;
165}
166
167impl<T: Expression + ?Sized> Expression for &T {
168 type SqlType = T::SqlType;
169}
170
171/// A helper to translate type level sql type information into
172/// runtime type information for specific queries
173///
174/// If you do not implement a custom backend implementation
175/// this trait is likely not relevant for you.
176pub trait QueryMetadata<T>: Backend {
177 /// The exact return value of this function is considered to be a
178 /// backend specific implementation detail. You should not rely on those
179 /// values if you not own the corresponding backend
180 fn row_metadata(lookup: &mut Self::MetadataLookup, out: &mut Vec<Option<Self::TypeMetadata>>);
181}
182
183impl<T, DB> QueryMetadata<T> for DB
184where
185 DB: Backend + HasSqlType<T>,
186 T: SingleValue,
187{
188 fn row_metadata(lookup: &mut Self::MetadataLookup, out: &mut Vec<Option<Self::TypeMetadata>>) {
189 out.push(Some(<DB as HasSqlType<T>>::metadata(lookup)))
190 }
191}
192
193/// Converts a type to its representation for use in Diesel's query builder.
194///
195/// This trait is used directly. Apps should typically use [`IntoSql`] instead.
196///
197/// Implementations of this trait will generally do one of 3 things:
198///
199/// - Return `self` for types which are already parts of Diesel's query builder
200/// - Perform some implicit coercion (for example, allowing [`now`] to be used as
201/// both [`Timestamp`] and [`Timestamptz`].
202/// - Indicate that the type has data which will be sent separately from the
203/// query. This is generally referred as a "bind parameter". Types which
204/// implement [`ToSql`] will generally implement `AsExpression` this way.
205///
206/// [`IntoSql`]: crate::IntoSql
207/// [`now`]: crate::dsl::now
208/// [`Timestamp`]: crate::sql_types::Timestamp
209/// [`Timestamptz`]: ../pg/types/sql_types/struct.Timestamptz.html
210/// [`ToSql`]: crate::serialize::ToSql
211///
212/// This trait could be [derived](derive@AsExpression)
213pub trait AsExpression<T>
214where
215 T: SqlType + TypedExpressionType,
216{
217 /// The expression being returned
218 type Expression: Expression<SqlType = T>;
219
220 /// Perform the conversion
221 #[allow(clippy::wrong_self_convention)]
222 // That's public API we cannot change it to appease clippy
223 fn as_expression(self) -> Self::Expression;
224}
225
226#[doc(inline)]
227pub use diesel_derives::AsExpression;
228
229impl<T, ST> AsExpression<ST> for T
230where
231 T: Expression<SqlType = ST>,
232 ST: SqlType + TypedExpressionType,
233{
234 type Expression = T;
235
236 fn as_expression(self) -> T {
237 self
238 }
239}
240
241/// Converts a type to its representation for use in Diesel's query builder.
242///
243/// This trait only exists to make usage of `AsExpression` more ergonomic when
244/// the `SqlType` cannot be inferred. It is generally used when you need to use
245/// a Rust value as the left hand side of an expression, or when you want to
246/// select a constant value.
247///
248/// # Example
249///
250/// ```rust
251/// # include!("../doctest_setup.rs");
252/// # use schema::users;
253/// #
254/// # fn main() {
255/// use diesel::sql_types::Text;
256/// # let conn = &mut establish_connection();
257/// let names = users::table
258/// .select("The Amazing ".into_sql::<Text>().concat(users::name))
259/// .load(conn);
260/// let expected_names = vec![
261/// "The Amazing Sean".to_string(),
262/// "The Amazing Tess".to_string(),
263/// ];
264/// assert_eq!(Ok(expected_names), names);
265/// # }
266/// ```
267pub trait IntoSql {
268 /// Convert `self` to an expression for Diesel's query builder.
269 ///
270 /// There is no difference in behavior between `x.into_sql::<Y>()` and
271 /// `AsExpression::<Y>::as_expression(x)`.
272 fn into_sql<T>(self) -> AsExprOf<Self, T>
273 where
274 Self: AsExpression<T> + Sized,
275 T: SqlType + TypedExpressionType,
276 {
277 self.as_expression()
278 }
279
280 /// Convert `&self` to an expression for Diesel's query builder.
281 ///
282 /// There is no difference in behavior between `x.as_sql::<Y>()` and
283 /// `AsExpression::<Y>::as_expression(&x)`.
284 fn as_sql<'a, T>(&'a self) -> AsExprOf<&'a Self, T>
285 where
286 &'a Self: AsExpression<T>,
287 T: SqlType + TypedExpressionType,
288 {
289 <&'a Self as AsExpression<T>>::as_expression(self)
290 }
291}
292
293impl<T> IntoSql for T {}
294
295/// Indicates that all elements of an expression are valid given a from clause.
296///
297/// This is used to ensure that `users.filter(posts::id.eq(1))` fails to
298/// compile. This constraint is only used in places where the nullability of a
299/// SQL type doesn't matter (everything except `select` and `returning`). For
300/// places where nullability is important, `SelectableExpression` is used
301/// instead.
302pub trait AppearsOnTable<QS: ?Sized>: Expression {}
303
304impl<T: ?Sized, QS> AppearsOnTable<QS> for Box<T>
305where
306 T: AppearsOnTable<QS>,
307 Box<T>: Expression,
308{
309}
310
311impl<'a, T: ?Sized, QS> AppearsOnTable<QS> for &'a T
312where
313 T: AppearsOnTable<QS>,
314 &'a T: Expression,
315{
316}
317
318/// Indicates that an expression can be selected from a source.
319///
320/// Columns will implement this for their table. Certain special types, like
321/// `CountStar` and `Bound` will implement this for all sources. Most compound
322/// expressions will implement this if each of their parts implement it.
323///
324/// Notably, columns will not implement this trait for the right side of a left
325/// join. To select a column or expression using a column from the right side of
326/// a left join, you must call `.nullable()` on it.
327#[diagnostic::on_unimplemented(
328 message = "Cannot select `{Self}` from `{QS}`",
329 note = "`{Self}` is no valid selection for `{QS}`"
330)]
331pub trait SelectableExpression<QS: ?Sized>: AppearsOnTable<QS> {}
332
333impl<T: ?Sized, QS> SelectableExpression<QS> for Box<T>
334where
335 T: SelectableExpression<QS>,
336 Box<T>: AppearsOnTable<QS>,
337{
338}
339
340impl<'a, T: ?Sized, QS> SelectableExpression<QS> for &'a T
341where
342 T: SelectableExpression<QS>,
343 &'a T: AppearsOnTable<QS>,
344{
345}
346
347/// Trait indicating that a record can be selected and queried from the database.
348///
349/// Types which implement `Selectable` represent the select clause of a SQL query.
350/// Use [`SelectableHelper::as_select()`] to construct the select clause. Once you
351/// called `.select(YourType::as_select())` we enforce at the type system level that you
352/// use the same type to load the query result into.
353///
354/// The constructed select clause can contain arbitrary expressions coming from different
355/// tables. The corresponding [derive](derive@Selectable) provides a simple way to
356/// construct a select clause matching fields to the corresponding table columns.
357///
358/// # Examples
359///
360/// If you just want to construct a select clause using an existing struct, you can use
361/// `#[derive(Selectable)]`, See [`#[derive(Selectable)]`](derive@Selectable) for details.
362///
363///
364/// ```rust
365/// # include!("../doctest_setup.rs");
366/// #
367/// use schema::users;
368///
369/// #[derive(Queryable, PartialEq, Debug, Selectable)]
370/// struct User {
371/// id: i32,
372/// name: String,
373/// }
374///
375/// # fn main() {
376/// # run_test();
377/// # }
378/// #
379/// # fn run_test() -> QueryResult<()> {
380/// # use schema::users::dsl::*;
381/// # let connection = &mut establish_connection();
382/// let first_user = users.select(User::as_select()).first(connection)?;
383/// let expected = User { id: 1, name: "Sean".into() };
384/// assert_eq!(expected, first_user);
385/// # Ok(())
386/// # }
387/// ```
388///
389/// Alternatively, we can implement the trait for our struct manually.
390///
391/// ```rust
392/// # include!("../doctest_setup.rs");
393/// #
394/// use schema::users;
395/// use diesel::prelude::{Queryable, Selectable};
396/// use diesel::backend::Backend;
397///
398/// #[derive(Queryable, PartialEq, Debug)]
399/// struct User {
400/// id: i32,
401/// name: String,
402/// }
403///
404/// impl<DB> Selectable<DB> for User
405/// where
406/// DB: Backend
407/// {
408/// type SelectExpression = (users::id, users::name);
409///
410/// fn construct_selection() -> Self::SelectExpression {
411/// (users::id, users::name)
412/// }
413/// }
414///
415/// # fn main() {
416/// # run_test();
417/// # }
418/// #
419/// # fn run_test() -> QueryResult<()> {
420/// # use schema::users::dsl::*;
421/// # let connection = &mut establish_connection();
422/// let first_user = users.select(User::as_select()).first(connection)?;
423/// let expected = User { id: 1, name: "Sean".into() };
424/// assert_eq!(expected, first_user);
425/// # Ok(())
426/// # }
427/// ```
428///
429/// When selecting from joined tables, you can select from a
430/// composition of types that implement `Selectable`. The simplest way
431/// is to use a tuple of all the types you wish to select.
432///
433/// ```rust
434/// # include!("../doctest_setup.rs");
435/// use schema::{users, posts};
436///
437/// #[derive(Debug, PartialEq, Queryable, Selectable)]
438/// struct User {
439/// id: i32,
440/// name: String,
441/// }
442///
443/// #[derive(Debug, PartialEq, Queryable, Selectable)]
444/// struct Post {
445/// id: i32,
446/// user_id: i32,
447/// title: String,
448/// }
449///
450/// # fn main() -> QueryResult<()> {
451/// # let connection = &mut establish_connection();
452/// #
453/// let (first_user, first_post) = users::table
454/// .inner_join(posts::table)
455/// .select(<(User, Post)>::as_select())
456/// .first(connection)?;
457///
458/// let expected_user = User { id: 1, name: "Sean".into() };
459/// assert_eq!(expected_user, first_user);
460///
461/// let expected_post = Post { id: 1, user_id: 1, title: "My first post".into() };
462/// assert_eq!(expected_post, first_post);
463/// #
464/// # Ok(())
465/// # }
466/// ```
467///
468/// If you want to load only a subset of fields, you can create types
469/// with those fields and use them in the composition.
470///
471/// ```rust
472/// # include!("../doctest_setup.rs");
473/// use schema::{users, posts};
474///
475/// #[derive(Debug, PartialEq, Queryable, Selectable)]
476/// struct User {
477/// id: i32,
478/// name: String,
479/// }
480///
481/// #[derive(Debug, PartialEq, Queryable, Selectable)]
482/// #[diesel(table_name = posts)]
483/// struct PostTitle {
484/// title: String,
485/// }
486///
487/// # fn main() -> QueryResult<()> {
488/// # let connection = &mut establish_connection();
489/// #
490/// let (first_user, first_post_title) = users::table
491/// .inner_join(posts::table)
492/// .select(<(User, PostTitle)>::as_select())
493/// .first(connection)?;
494///
495/// let expected_user = User { id: 1, name: "Sean".into() };
496/// assert_eq!(expected_user, first_user);
497///
498/// let expected_post_title = PostTitle { title: "My first post".into() };
499/// assert_eq!(expected_post_title, first_post_title);
500/// #
501/// # Ok(())
502/// # }
503/// ```
504///
505/// You are not limited to using only tuples to build the composed
506/// type. The [`Selectable`](derive@Selectable) derive macro allows
507/// you to *embed* other types. This is useful when you want to
508/// implement methods or traits on the composed type.
509///
510/// ```rust
511/// # include!("../doctest_setup.rs");
512/// use schema::{users, posts};
513///
514/// #[derive(Debug, PartialEq, Queryable, Selectable)]
515/// struct User {
516/// id: i32,
517/// name: String,
518/// }
519///
520/// #[derive(Debug, PartialEq, Queryable, Selectable)]
521/// #[diesel(table_name = posts)]
522/// struct PostTitle {
523/// title: String,
524/// }
525///
526/// #[derive(Debug, PartialEq, Queryable, Selectable)]
527/// struct UserPost {
528/// #[diesel(embed)]
529/// user: User,
530/// #[diesel(embed)]
531/// post_title: PostTitle,
532/// }
533///
534/// # fn main() -> QueryResult<()> {
535/// # let connection = &mut establish_connection();
536/// #
537/// let first_user_post = users::table
538/// .inner_join(posts::table)
539/// .select(UserPost::as_select())
540/// .first(connection)?;
541///
542/// let expected_user_post = UserPost {
543/// user: User {
544/// id: 1,
545/// name: "Sean".into(),
546/// },
547/// post_title: PostTitle {
548/// title: "My first post".into(),
549/// },
550/// };
551/// assert_eq!(expected_user_post, first_user_post);
552/// #
553/// # Ok(())
554/// # }
555/// ```
556///
557/// It is also possible to specify an entirely custom select expression
558/// for fields when deriving [`Selectable`](derive@Selectable).
559/// This is useful for example to
560///
561/// * avoid nesting types, or to
562/// * populate fields with values other than table columns, such as
563/// the result of an SQL function like `CURRENT_TIMESTAMP()`
564/// or a custom SQL function.
565///
566/// The select expression is specified via the `select_expression` parameter.
567///
568/// Query fragments created using [`dsl::auto_type`](crate::dsl::auto_type) are supported, which
569/// may be useful as the select expression gets large: it may not be practical to inline it in
570/// the attribute then.
571///
572/// The type of the expression is usually inferred. If it can't be fully inferred automatically,
573/// one may either:
574/// - Put type annotations in inline blocks in the query fragment itself
575/// - Use a dedicated [`dsl::auto_type`](crate::dsl::auto_type) function as `select_expression`
576/// and use [`dsl::auto_type`'s type annotation features](crate::dsl::auto_type)
577/// - Specify the type of the expression using the `select_expression_type` attribute
578///
579/// ```rust
580/// # include!("../doctest_setup.rs");
581/// use schema::{users, posts};
582/// use diesel::dsl;
583///
584/// #[derive(Debug, PartialEq, Queryable, Selectable)]
585/// struct User {
586/// id: i32,
587/// name: String,
588/// }
589///
590/// #[derive(Debug, PartialEq, Queryable, Selectable)]
591/// #[diesel(table_name = posts)]
592/// struct PostTitle {
593/// title: String,
594/// }
595///
596/// #[derive(Debug, PartialEq, Queryable, Selectable)]
597/// struct UserPost {
598/// #[diesel(select_expression = users::columns::id)]
599/// #[diesel(select_expression_type = users::columns::id)]
600/// id: i32,
601/// #[diesel(select_expression = users::columns::name)]
602/// name: String,
603/// #[diesel(select_expression = complex_fragment_for_title())]
604/// title: String,
605/// # #[cfg(feature = "chrono")]
606/// #[diesel(select_expression = diesel::dsl::now)]
607/// access_time: chrono::NaiveDateTime,
608/// #[diesel(select_expression = users::columns::id.eq({let id: i32 = FOO; id}))]
609/// user_id_is_foo: bool,
610/// }
611/// const FOO: i32 = 42; // Type of FOO can't be inferred automatically in the select_expression
612/// #[dsl::auto_type]
613/// fn complex_fragment_for_title() -> _ {
614/// // See the `#[dsl::auto_type]` documentation for examples of more complex usage
615/// posts::columns::title
616/// }
617///
618/// # fn main() -> QueryResult<()> {
619/// # let connection = &mut establish_connection();
620/// #
621/// let first_user_post = users::table
622/// .inner_join(posts::table)
623/// .select(UserPost::as_select())
624/// .first(connection)?;
625///
626/// let expected_user_post = UserPost {
627/// id: 1,
628/// name: "Sean".into(),
629/// title: "My first post".into(),
630/// # #[cfg(feature = "chrono")]
631/// access_time: first_user_post.access_time,
632/// user_id_is_foo: false,
633/// };
634/// assert_eq!(expected_user_post, first_user_post);
635/// #
636/// # Ok(())
637/// # }
638/// ```
639///
640pub trait Selectable<DB: Backend> {
641 /// The expression you'd like to select.
642 ///
643 /// This is typically a tuple of corresponding to the table columns of your struct's fields.
644 type SelectExpression: Expression;
645
646 /// Construct an instance of the expression
647 fn construct_selection() -> Self::SelectExpression;
648}
649
650#[doc(inline)]
651pub use diesel_derives::Selectable;
652
653/// This helper trait provides several methods for
654/// constructing a select or returning clause based on a
655/// [`Selectable`] implementation.
656pub trait SelectableHelper<DB: Backend>: Selectable<DB> + Sized {
657 /// Construct a select clause based on a [`Selectable`] implementation.
658 ///
659 /// The returned select clause enforces that you use the same type
660 /// for constructing the select clause and for loading the query result into.
661 fn as_select() -> AsSelect<Self, DB>;
662
663 /// An alias for `as_select` that can be used with returning clauses
664 fn as_returning() -> AsSelect<Self, DB> {
665 Self::as_select()
666 }
667}
668
669impl<T, DB> SelectableHelper<DB> for T
670where
671 T: Selectable<DB>,
672 DB: Backend,
673{
674 fn as_select() -> AsSelect<Self, DB> {
675 select_by::SelectBy::new()
676 }
677}
678
679/// Is this expression valid for a given group by clause?
680///
681/// Implementations of this trait must ensure that aggregate expressions are
682/// not mixed with non-aggregate expressions.
683///
684/// For generic types, you can determine if your sub-expressions can appear
685/// together using the [`MixedAggregates`] trait.
686///
687/// `GroupByClause` will be a tuple containing the set of expressions appearing
688/// in the `GROUP BY` portion of the query. If there is no `GROUP BY`, it will
689/// be `()`.
690///
691/// This trait can be [derived]
692///
693/// [derived]: derive@ValidGrouping
694pub trait ValidGrouping<GroupByClause> {
695 /// Is this expression aggregate?
696 ///
697 /// This type should always be one of the structs in the [`is_aggregate`]
698 /// module. See the documentation of those structs for more details.
699 ///
700 type IsAggregate;
701}
702
703impl<T: ValidGrouping<GB> + ?Sized, GB> ValidGrouping<GB> for Box<T> {
704 type IsAggregate = T::IsAggregate;
705}
706
707impl<T: ValidGrouping<GB> + ?Sized, GB> ValidGrouping<GB> for &T {
708 type IsAggregate = T::IsAggregate;
709}
710
711#[doc(inline)]
712pub use diesel_derives::ValidGrouping;
713
714#[doc(hidden)]
715pub trait IsContainedInGroupBy<T> {
716 type Output;
717}
718
719#[doc(hidden)]
720#[allow(missing_debug_implementations, missing_copy_implementations)]
721pub mod is_contained_in_group_by {
722 pub struct Yes;
723 pub struct No;
724
725 pub trait IsAny<O> {
726 type Output;
727 }
728
729 impl<T> IsAny<T> for Yes {
730 type Output = Yes;
731 }
732
733 impl IsAny<Yes> for No {
734 type Output = Yes;
735 }
736
737 impl IsAny<No> for No {
738 type Output = No;
739 }
740}
741
742/// Can two `IsAggregate` types appear in the same expression?
743///
744/// You should never implement this trait. It will eventually become a trait
745/// alias.
746///
747/// [`is_aggregate::Yes`] and [`is_aggregate::No`] can only appear with
748/// themselves or [`is_aggregate::Never`]. [`is_aggregate::Never`] can appear
749/// with anything.
750///
751pub trait MixedAggregates<Other> {
752 /// What is the resulting `IsAggregate` type?
753 type Output;
754}
755
756#[allow(missing_debug_implementations, missing_copy_implementations)]
757/// Possible values for `ValidGrouping::IsAggregate`
758pub mod is_aggregate {
759 use super::MixedAggregates;
760
761 /// Yes, this expression is aggregate for the given group by clause.
762 pub struct Yes;
763
764 /// No, this expression is not aggregate with the given group by clause,
765 /// but it might be aggregate with a different group by clause.
766 pub struct No;
767
768 /// This expression is never aggregate, and can appear with any other
769 /// expression, regardless of whether it is aggregate.
770 ///
771 /// Examples of this are literals. `1` does not care about aggregation.
772 /// `foo + 1` is always valid, regardless of whether `foo` appears in the
773 /// group by clause or not.
774 pub struct Never;
775
776 impl MixedAggregates<Yes> for Yes {
777 type Output = Yes;
778 }
779
780 impl MixedAggregates<Never> for Yes {
781 type Output = Yes;
782 }
783
784 impl MixedAggregates<No> for No {
785 type Output = No;
786 }
787
788 impl MixedAggregates<Never> for No {
789 type Output = No;
790 }
791
792 impl<T> MixedAggregates<T> for Never {
793 type Output = T;
794 }
795}
796
797#[cfg(feature = "unstable")]
798// this needs to be a separate module for the reasons given in
799// https://github.com/rust-lang/rust/issues/65860
800mod unstable;
801
802#[cfg(feature = "unstable")]
803#[doc(inline)]
804pub use self::unstable::NonAggregate;
805
806// Note that these docs are similar to but slightly different than the unstable
807// docs above. Make sure if you change these that you also change the docs
808// above.
809/// Trait alias to represent an expression that isn't aggregate by default.
810///
811/// This trait should never be implemented directly. It is replaced with a
812/// trait alias when the `unstable` feature is enabled.
813///
814/// This alias represents a type which is not aggregate if there is no group by
815/// clause. More specifically, it represents for types which implement
816/// [`ValidGrouping<()>`] where `IsAggregate` is [`is_aggregate::No`] or
817/// [`is_aggregate::Yes`].
818///
819/// While this trait is a useful stand-in for common cases, `T: NonAggregate`
820/// cannot always be used when `T: ValidGrouping<(), IsAggregate = No>` or
821/// `T: ValidGrouping<(), IsAggregate = Never>` could be. For that reason,
822/// unless you need to abstract over both columns and literals, you should
823/// prefer to use [`ValidGrouping<()>`] in your bounds instead.
824///
825/// [`ValidGrouping<()>`]: ValidGrouping
826#[cfg(not(feature = "unstable"))]
827pub trait NonAggregate: ValidGrouping<()> {}
828
829#[cfg(not(feature = "unstable"))]
830impl<T> NonAggregate for T
831where
832 T: ValidGrouping<()>,
833 T::IsAggregate: MixedAggregates<is_aggregate::No, Output = is_aggregate::No>,
834{
835}
836
837use crate::query_builder::{QueryFragment, QueryId};
838
839/// Helper trait used when boxing expressions.
840///
841/// In Rust you cannot create a trait object with more than one trait.
842/// This type has all of the additional traits you would want when using
843/// `Box<Expression>` as a single trait object.
844///
845/// By default `BoxableExpression` is not usable in queries that have a custom
846/// group by clause. Setting the generic parameters `GB` and `IsAggregate` allows
847/// to configure the expression to be used with a specific group by clause.
848///
849/// This is typically used as the return type of a function.
850/// For cases where you want to dynamically construct a query,
851/// [boxing the query] is usually more ergonomic.
852///
853/// [boxing the query]: crate::query_dsl::QueryDsl::into_boxed()
854///
855/// # Examples
856///
857/// ## Usage without group by clause
858///
859/// ```rust
860/// # include!("../doctest_setup.rs");
861/// # use schema::users;
862/// use diesel::sql_types::Bool;
863///
864/// # fn main() {
865/// # run_test().unwrap();
866/// # }
867/// #
868/// # fn run_test() -> QueryResult<()> {
869/// # let conn = &mut establish_connection();
870/// enum Search {
871/// Id(i32),
872/// Name(String),
873/// }
874///
875/// # /*
876/// type DB = diesel::sqlite::Sqlite;
877/// # */
878///
879/// fn find_user(search: Search) -> Box<dyn BoxableExpression<users::table, DB, SqlType = Bool>> {
880/// match search {
881/// Search::Id(id) => Box::new(users::id.eq(id)),
882/// Search::Name(name) => Box::new(users::name.eq(name)),
883/// }
884/// }
885///
886/// let user_one = users::table
887/// .filter(find_user(Search::Id(1)))
888/// .first(conn)?;
889/// assert_eq!((1, String::from("Sean")), user_one);
890///
891/// let tess = users::table
892/// .filter(find_user(Search::Name("Tess".into())))
893/// .first(conn)?;
894/// assert_eq!((2, String::from("Tess")), tess);
895/// # Ok(())
896/// # }
897/// ```
898///
899/// ## Allow usage with group by clause
900///
901/// ```rust
902/// # include!("../doctest_setup.rs");
903///
904/// # use schema::users;
905/// use diesel::sql_types::Text;
906/// use diesel::dsl;
907/// use diesel::expression::ValidGrouping;
908///
909/// # fn main() {
910/// # run_test().unwrap();
911/// # }
912/// #
913/// # fn run_test() -> QueryResult<()> {
914/// # let conn = &mut establish_connection();
915/// enum NameOrConst {
916/// Name,
917/// Const(String),
918/// }
919///
920/// # /*
921/// type DB = diesel::sqlite::Sqlite;
922/// # */
923///
924/// fn selection<GB>(
925/// selection: NameOrConst
926/// ) -> Box<
927/// dyn BoxableExpression<
928/// users::table,
929/// DB,
930/// GB,
931/// <users::name as ValidGrouping<GB>>::IsAggregate,
932/// SqlType = Text
933/// >
934/// >
935/// where
936/// users::name: BoxableExpression<
937/// users::table,
938/// DB,
939/// GB,
940/// <users::name as ValidGrouping<GB>>::IsAggregate,
941/// SqlType = Text
942/// > + ValidGrouping<GB>,
943/// {
944/// match selection {
945/// NameOrConst::Name => Box::new(users::name),
946/// NameOrConst::Const(name) => Box::new(name.into_sql::<Text>()),
947/// }
948/// }
949///
950/// let user_one = users::table
951/// .select(selection(NameOrConst::Name))
952/// .first::<String>(conn)?;
953/// assert_eq!(String::from("Sean"), user_one);
954///
955/// let with_name = users::table
956/// .group_by(users::name)
957/// .select(selection(NameOrConst::Const("Jane Doe".into())))
958/// .first::<String>(conn)?;
959/// assert_eq!(String::from("Jane Doe"), with_name);
960/// # Ok(())
961/// # }
962/// ```
963///
964/// ## More advanced query source
965///
966/// This example is a bit contrived, but in general, if you want to for example filter based on
967/// different criteria on a joined table, you can use `InnerJoinQuerySource` and
968/// `LeftJoinQuerySource` in the QS parameter of `BoxableExpression`.
969///
970/// ```rust
971/// # include!("../doctest_setup.rs");
972/// # use schema::{users, posts};
973/// use diesel::sql_types::Bool;
974/// use diesel::dsl::InnerJoinQuerySource;
975///
976/// # fn main() {
977/// # run_test().unwrap();
978/// # }
979/// #
980/// # fn run_test() -> QueryResult<()> {
981/// # let conn = &mut establish_connection();
982/// enum UserPostFilter {
983/// User(i32),
984/// Post(i32),
985/// }
986///
987/// # /*
988/// type DB = diesel::sqlite::Sqlite;
989/// # */
990///
991/// fn filter_user_posts(
992/// filter: UserPostFilter,
993/// ) -> Box<dyn BoxableExpression<InnerJoinQuerySource<users::table, posts::table>, DB, SqlType = Bool>>
994/// {
995/// match filter {
996/// UserPostFilter::User(user_id) => Box::new(users::id.eq(user_id)),
997/// UserPostFilter::Post(post_id) => Box::new(posts::id.eq(post_id)),
998/// }
999/// }
1000///
1001/// let post_by_user_one = users::table
1002/// .inner_join(posts::table)
1003/// .filter(filter_user_posts(UserPostFilter::User(2)))
1004/// .select((posts::title, users::name))
1005/// .first::<(String, String)>(conn)?;
1006///
1007/// assert_eq!(
1008/// ("My first post too".to_string(), "Tess".to_string()),
1009/// post_by_user_one
1010/// );
1011/// # Ok(())
1012/// # }
1013/// ```
1014pub trait BoxableExpression<QS, DB, GB = (), IsAggregate = is_aggregate::No>
1015where
1016 DB: Backend,
1017 Self: Expression,
1018 Self: SelectableExpression<QS>,
1019 Self: QueryFragment<DB>,
1020 Self: Send,
1021{
1022}
1023
1024impl<QS, T, DB, GB, IsAggregate> BoxableExpression<QS, DB, GB, IsAggregate> for T
1025where
1026 DB: Backend,
1027 T: Expression,
1028 T: SelectableExpression<QS>,
1029 T: ValidGrouping<GB>,
1030 T: QueryFragment<DB>,
1031 T: Send,
1032 T::IsAggregate: MixedAggregates<IsAggregate, Output = IsAggregate>,
1033{
1034}
1035
1036impl<QS, ST, DB, GB, IsAggregate> QueryId
1037 for dyn BoxableExpression<QS, DB, GB, IsAggregate, SqlType = ST> + '_
1038{
1039 type QueryId = ();
1040
1041 const HAS_STATIC_QUERY_ID: bool = false;
1042}
1043
1044impl<QS, ST, DB, GB, IsAggregate> ValidGrouping<GB>
1045 for dyn BoxableExpression<QS, DB, GB, IsAggregate, SqlType = ST> + '_
1046{
1047 type IsAggregate = IsAggregate;
1048}
1049
1050// Some amount of backwards-compat
1051// We used to require `AsExpressionList` on the `array` function.
1052// Now we require `IntoArrayExpression` instead, which means something very different.
1053// However for most people just checking this bound to call `array`, this won't break.
1054// Only people who directly implement `AsExpressionList` would break, but I expect that to be
1055// nobody.
1056#[doc(hidden)]
1057#[cfg(feature = "postgres_backend")]
1058pub use crate::pg::expression::array::IntoArrayExpression as AsExpressionList;