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