Skip to main content

diesel/query_builder/returning/
returning_query_source.rs

1//! The `ReturningQuerySource<StmtKind, T>` wrapper used to type-check `RETURNING`
2//! clauses, the statement-kind markers it is parameterized over, and the
3//! [`InsertStmtKind`] dispatch trait.
4//!
5//! This module holds the items needed to type-check `RETURNING` clauses that are not specific
6//! to a particular backend.
7
8use crate::expression::nullable::Nullable;
9use crate::expression::{AppearsOnTable, BoxableExpression, Expression, SelectableExpression};
10use crate::query_source::{
11    AppearsInFromClause, Never, Once, QueryRelation, QuerySource, TableNotEqual,
12};
13use alloc::boxed::Box;
14use core::marker::PhantomData;
15
16/// Statement-kind marker
17#[derive(#[automatically_derived]
impl ::core::fmt::Debug for InsertStmtWithoutOnConflictDoUpdate {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            "InsertStmtWithoutOnConflictDoUpdate")
    }
}Debug, #[automatically_derived]
impl ::core::marker::Copy for InsertStmtWithoutOnConflictDoUpdate { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for
    InsertStmtWithoutOnConflictDoUpdate {
}
#[automatically_derived]
impl ::core::clone::Clone for InsertStmtWithoutOnConflictDoUpdate {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone)]
18pub struct InsertStmtWithoutOnConflictDoUpdate;
19
20/// Statement-kind marker
21#[derive(#[automatically_derived]
impl ::core::fmt::Debug for UpdateStmt {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "UpdateStmt")
    }
}Debug, #[automatically_derived]
impl ::core::marker::Copy for UpdateStmt { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for UpdateStmt { }
#[automatically_derived]
impl ::core::clone::Clone for UpdateStmt {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone)]
22pub struct UpdateStmt;
23
24/// Statement-kind marker
25#[derive(#[automatically_derived]
impl ::core::fmt::Debug for DeleteStmt {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "DeleteStmt")
    }
}Debug, #[automatically_derived]
impl ::core::marker::Copy for DeleteStmt { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for DeleteStmt { }
#[automatically_derived]
impl ::core::clone::Clone for DeleteStmt {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone)]
26pub struct DeleteStmt;
27
28/// Statement-kind marker
29#[derive(#[automatically_derived]
impl ::core::fmt::Debug for InsertStmtWithOnConflictDoUpdate {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            "InsertStmtWithOnConflictDoUpdate")
    }
}Debug, #[automatically_derived]
impl ::core::marker::Copy for InsertStmtWithOnConflictDoUpdate { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for InsertStmtWithOnConflictDoUpdate {
}
#[automatically_derived]
impl ::core::clone::Clone for InsertStmtWithOnConflictDoUpdate {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone)]
30pub struct InsertStmtWithOnConflictDoUpdate;
31
32/// Synthetic query source used as the `QS` parameter of
33/// [`SelectableExpression`](crate::expression::SelectableExpression) /
34/// [`AppearsOnTable`](crate::expression::AppearsOnTable) when type-checking
35/// `RETURNING` clauses.
36///
37/// `StmtKind` is one of the marker structs above; `T` is the table that the
38/// `INSERT`/`UPDATE`/`DELETE` is acting on.
39#[derive(#[automatically_derived]
impl<StmtKind: ::core::fmt::Debug, T: ::core::fmt::Debug> ::core::fmt::Debug
    for ReturningQuerySource<StmtKind, T> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f,
            "ReturningQuerySource", &&self.0)
    }
}Debug, #[automatically_derived]
impl<StmtKind: ::core::clone::Clone, T: ::core::clone::Clone>
    ::core::clone::Clone for ReturningQuerySource<StmtKind, T> {
    #[inline]
    fn clone(&self) -> Self { Self(::core::clone::Clone::clone(&self.0)) }
}Clone, #[automatically_derived]
impl<StmtKind: ::core::marker::Copy, T: ::core::marker::Copy>
    ::core::marker::Copy for ReturningQuerySource<StmtKind, T> {
}Copy)]
40pub struct ReturningQuerySource<StmtKind, T>(PhantomData<(StmtKind, T)>);
41
42impl<StmtKind, T> QuerySource for ReturningQuerySource<StmtKind, T>
43where
44    T: QuerySource + Default,
45    T::DefaultSelection: SelectableExpression<Self>,
46{
47    type FromClause = T::FromClause;
48    type DefaultSelection = T::DefaultSelection;
49
50    fn from_clause(&self) -> Self::FromClause {
51        T::default().from_clause()
52    }
53
54    fn default_selection(&self) -> Self::DefaultSelection {
55        T::default().default_selection()
56    }
57}
58
59impl<StmtKind, T1, T2> AppearsInFromClause<T1> for ReturningQuerySource<StmtKind, T2>
60where
61    T1: TableNotEqual<T2> + QueryRelation,
62    T2: QueryRelation,
63{
64    type Count = Never;
65}
66
67/// Maps an `InsertStatement` `Values` shape to the statement-kind marker that
68/// should be used when type-checking that statement's `RETURNING` clause.
69///
70/// This is what makes `RETURNING old(col)` accept `INSERT ... ON CONFLICT
71/// ... DO UPDATE` (where the marker is [`InsertStmtWithOnConflictDoUpdate`], for
72/// which `Nullable<Old<C>>` is a valid `RETURNING` element) but reject plain
73/// `INSERT` (where the marker is [`InsertStmtWithoutOnConflictDoUpdate`], for which `Old<C>` does not
74/// implement `SelectableExpression`).
75///
76/// The trait is sealed in spirit — it only has impls for the values shapes
77/// `diesel` itself produces — but it is exposed publicly under the
78/// `i-implement-a-third-party-backend-and-opt-into-breaking-changes` feature
79/// so third-party backends that introduce new values shapes can add their own
80/// impls.
81pub trait InsertStmtKind {
82    /// The statement-kind marker (see e.g. [`InsertStmtWithoutOnConflictDoUpdate`],
83    /// [`InsertStmtWithOnConflictDoUpdate`]) used as the `StmtKind` parameter of
84    /// [`ReturningQuerySource`] for `INSERT` statements with this `Values`
85    /// shape.
86    type StmtKind;
87}
88
89impl<T, Tab> InsertStmtKind for crate::query_builder::ValuesClause<T, Tab> {
90    type StmtKind = InsertStmtWithoutOnConflictDoUpdate;
91}
92
93impl<V, Tab, QId, const STABLE_QUERY_ID: bool> InsertStmtKind
94    for crate::query_builder::BatchInsert<V, Tab, QId, STABLE_QUERY_ID>
95{
96    type StmtKind = InsertStmtWithoutOnConflictDoUpdate;
97}
98
99impl InsertStmtKind for crate::query_builder::insert_statement::DefaultValues {
100    type StmtKind = InsertStmtWithoutOnConflictDoUpdate;
101}
102
103impl<S, C> InsertStmtKind for crate::query_builder::insert_statement::InsertFromSelect<S, C> {
104    type StmtKind = InsertStmtWithoutOnConflictDoUpdate;
105}
106
107impl<V, Target, T, WhereClause> InsertStmtKind
108    for crate::query_builder::upsert::on_conflict_clause::OnConflictValues<
109        V,
110        Target,
111        crate::query_builder::upsert::on_conflict_actions::DoNothing<T>,
112        WhereClause,
113    >
114{
115    // ON CONFLICT DO NOTHING does not return the lines that conflicted if using RETURNING
116    // so it's unnecessary (and would even be misleading) to allow RETURNING old.xxx
117    // in this case.
118    type StmtKind = InsertStmtWithoutOnConflictDoUpdate;
119}
120
121impl<V, Target, Changeset, Tab, WhereClause> InsertStmtKind
122    for crate::query_builder::upsert::on_conflict_clause::OnConflictValues<
123        V,
124        Target,
125        crate::query_builder::upsert::on_conflict_actions::DoUpdate<Changeset, Tab>,
126        WhereClause,
127    >
128{
129    type StmtKind = InsertStmtWithOnConflictDoUpdate;
130}
131
132/// Make `Box<dyn BoxableExpression<table>>` be `SelectableExpression` in returning clauses.
133/// This is necessary for backwards-compatibility.
134///
135/// Unfortunately we cannot implement this directly for `dyn BoxableExpression`
136/// (and rely on our existing generic impls for `Box<T>`) because the compiler
137/// complains that there is already an automatic implementation of `SelectableExpression` for
138/// `dyn BoxableExpression`, even though the `QS` type is different.
139/// As a workaround, we implement it for `Box<dyn BoxableExpression<table>>`, which should
140/// cover for most users.
141impl<'a, QS, ST, DB, GB, IsAggregate, StmtKind>
142    SelectableExpression<ReturningQuerySource<StmtKind, QS>>
143    for Box<dyn BoxableExpression<QS, DB, GB, IsAggregate, SqlType = ST> + 'a>
144where
145    Box<dyn BoxableExpression<QS, DB, GB, IsAggregate, SqlType = ST> + 'a>: Expression,
146{
147}
148/// See comment on `SelectableExpression` impl above.
149impl<'a, QS, ST, DB, GB, IsAggregate, StmtKind> AppearsOnTable<ReturningQuerySource<StmtKind, QS>>
150    for Box<dyn BoxableExpression<QS, DB, GB, IsAggregate, SqlType = ST> + 'a>
151where
152    Box<dyn BoxableExpression<QS, DB, GB, IsAggregate, SqlType = ST> + 'a>: Expression,
153{
154}
155
156impl<StmtKind, E, T> SelectableExpression<ReturningQuerySource<StmtKind, T>> for Nullable<E>
157where
158    Self: AppearsOnTable<ReturningQuerySource<StmtKind, T>>,
159    E: SelectableExpression<ReturningQuerySource<StmtKind, T>>,
160{
161}
162
163impl<StmtKind, E, T> SelectableExpression<ReturningQuerySource<StmtKind, T>>
164    for crate::expression::assume_not_null::AssumeNotNull<E>
165where
166    Self: AppearsOnTable<ReturningQuerySource<StmtKind, T>>,
167    E: SelectableExpression<ReturningQuerySource<StmtKind, T>>,
168{
169}
170
171/// Represents the identifier `old` or `old_value` in the `RETURNING` clause.
172/// It is independent of the table of the column, and used as QS in marker in AppearsInFromClause.
173///
174/// We use this to typecheck that there is only one `old` or `old_value` identifier when we use `old` or `old_value`, so that
175/// there is no ambiguity, and also as a generic
176/// "any valid OLD statement-kind marker for ReturningQuerySource".
177#[derive(#[automatically_derived]
impl ::core::fmt::Debug for OldIdent {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f, "OldIdent")
    }
}Debug, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for OldIdent { }
#[automatically_derived]
impl ::core::clone::Clone for OldIdent {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for OldIdent { }Copy)]
178pub struct OldIdent;
179
180/// There is an `old.` or `old_value()` in ReturningQuerySource<UpdateStmt, T>
181///
182/// Useful to check non-ambiguity of `old` or `old_value`
183impl<StmtKind, T> AppearsInFromClause<OldIdent> for ReturningQuerySource<StmtKind, T> {
184    type Count = Once;
185}
186/// There isn't one directly on tables
187/// (this is useful for typechecking `old` or `old_value` in subqueries in returning)
188impl<T> AppearsInFromClause<OldIdent> for T
189where
190    T: QueryRelation,
191{
192    type Count = Never;
193}
194/// There is an `old.` or `old_value` for T in ReturningQuerySource<UpdateStmt, T>
195impl<T> AppearsInFromClause<ReturningQuerySource<OldIdent, T>>
196    for ReturningQuerySource<UpdateStmt, T>
197{
198    type Count = Once;
199}
200/// There is an `old.` or `old_value` for T in ReturningQuerySource<InsertStmtWithOnConflictDoUpdate, T>
201impl<T> AppearsInFromClause<ReturningQuerySource<OldIdent, T>>
202    for ReturningQuerySource<InsertStmtWithOnConflictDoUpdate, T>
203{
204    type Count = Once;
205}