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