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::query_source::joins::ToInnerJoin;
9use crate::query_source::{AppearsInFromClause, Once};
10use core::marker::PhantomData;
11
12/// Statement-kind marker
13#[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]
impl ::core::clone::Clone for InsertStmtWithoutOnConflictDoUpdate {
    #[inline]
    fn clone(&self) -> InsertStmtWithoutOnConflictDoUpdate { *self }
}Clone)]
14pub struct InsertStmtWithoutOnConflictDoUpdate;
15
16/// Statement-kind marker
17#[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]
impl ::core::clone::Clone for UpdateStmt {
    #[inline]
    fn clone(&self) -> UpdateStmt { *self }
}Clone)]
18pub struct UpdateStmt;
19
20/// Statement-kind marker
21#[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]
impl ::core::clone::Clone for DeleteStmt {
    #[inline]
    fn clone(&self) -> DeleteStmt { *self }
}Clone)]
22pub struct DeleteStmt;
23
24/// Statement-kind marker
25#[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]
impl ::core::clone::Clone for InsertStmtWithOnConflictDoUpdate {
    #[inline]
    fn clone(&self) -> InsertStmtWithOnConflictDoUpdate { *self }
}Clone)]
26pub struct InsertStmtWithOnConflictDoUpdate;
27
28/// Synthetic query source used as the `QS` parameter of
29/// [`SelectableExpression`](crate::expression::SelectableExpression) /
30/// [`AppearsOnTable`](crate::expression::AppearsOnTable) when type-checking
31/// `RETURNING` clauses.
32///
33/// `StmtKind` is one of the marker structs above; `T` is the table that the
34/// `INSERT`/`UPDATE`/`DELETE` is acting on.
35#[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) -> ReturningQuerySource<StmtKind, T> {
        ReturningQuerySource(::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)]
36pub struct ReturningQuerySource<StmtKind, T>(PhantomData<(StmtKind, T)>);
37
38impl<StmtKind, T> AppearsInFromClause<T> for ReturningQuerySource<StmtKind, T> {
39    type Count = Once;
40}
41
42// For typechecking of `old(column).nullable()`
43
44impl<T> ToInnerJoin for ReturningQuerySource<UpdateStmt, T> {
45    type InnerJoin = Self;
46}
47
48impl<T> ToInnerJoin for ReturningQuerySource<DeleteStmt, T> {
49    type InnerJoin = Self;
50}
51
52impl<T> ToInnerJoin for ReturningQuerySource<InsertStmtWithoutOnConflictDoUpdate, T> {
53    type InnerJoin = Self;
54}
55
56// `InsertStmtWithOnConflictDoUpdate` maps to `UpdateStmt`. This is what makes
57// `Nullable<Old<C>>: SelectableExpression<ReturningQuerySource<InsertStmtWithOnConflictDoUpdate, _>>`
58// resolve through the existing
59// `impl<T, QS> SelectableExpression<QS> for Nullable<T>
60//     where QS: ToInnerJoin, T: SelectableExpression<QS::InnerJoin>` impl
61// (see `crate::expression::nullable::Nullable`): that bound reduces to
62// `Old<C>: SelectableExpression<ReturningQuerySource<UpdateStmt, _>>`, which
63// holds, while the bare `Old<C>: SelectableExpression<ReturningQuerySource<InsertStmtWithOnConflictDoUpdate, _>>`
64// is intentionally *not* implemented — forcing users to write
65// `old(col).nullable()` in `ON CONFLICT ... DO UPDATE` for type safety.
66impl<T> ToInnerJoin for ReturningQuerySource<InsertStmtWithOnConflictDoUpdate, T> {
67    type InnerJoin = ReturningQuerySource<UpdateStmt, T>;
68}
69
70/// Maps an `InsertStatement` `Values` shape to the statement-kind marker that
71/// should be used when type-checking that statement's `RETURNING` clause.
72///
73/// This is what makes `RETURNING old(col)` accept `INSERT ... ON CONFLICT
74/// ... DO UPDATE` (where the marker is [`InsertStmtWithOnConflictDoUpdate`], for
75/// which `Nullable<Old<C>>` is a valid `RETURNING` element) but reject plain
76/// `INSERT` (where the marker is [`InsertStmtWithoutOnConflictDoUpdate`], for which `Old<C>` does not
77/// implement `SelectableExpression`).
78///
79/// The trait is sealed in spirit — it only has impls for the values shapes
80/// `diesel` itself produces — but it is exposed publicly under the
81/// `i-implement-a-third-party-backend-and-opt-into-breaking-changes` feature
82/// so third-party backends that introduce new values shapes can add their own
83/// impls.
84pub trait InsertStmtKind {
85    /// The statement-kind marker (see e.g. [`InsertStmtWithoutOnConflictDoUpdate`],
86    /// [`InsertStmtWithOnConflictDoUpdate`]) used as the `StmtKind` parameter of
87    /// [`ReturningQuerySource`] for `INSERT` statements with this `Values`
88    /// shape.
89    type StmtKind;
90}
91
92impl<T, Tab> InsertStmtKind for crate::query_builder::ValuesClause<T, Tab> {
93    type StmtKind = InsertStmtWithoutOnConflictDoUpdate;
94}
95
96impl<V, Tab, QId, const STABLE_QUERY_ID: bool> InsertStmtKind
97    for crate::query_builder::BatchInsert<V, Tab, QId, STABLE_QUERY_ID>
98{
99    type StmtKind = InsertStmtWithoutOnConflictDoUpdate;
100}
101
102impl InsertStmtKind for crate::query_builder::insert_statement::DefaultValues {
103    type StmtKind = InsertStmtWithoutOnConflictDoUpdate;
104}
105
106impl<S, C> InsertStmtKind for crate::query_builder::insert_statement::InsertFromSelect<S, C> {
107    type StmtKind = InsertStmtWithoutOnConflictDoUpdate;
108}
109
110impl<V, Target, T, WhereClause> InsertStmtKind
111    for crate::query_builder::upsert::on_conflict_clause::OnConflictValues<
112        V,
113        Target,
114        crate::query_builder::upsert::on_conflict_actions::DoNothing<T>,
115        WhereClause,
116    >
117{
118    // ON CONFLICT DO NOTHING does not return the lines that conflicted if using RETURNING
119    // so it's unnecessary (and would even be misleading) to allow RETURNING old.xxx
120    // in this case.
121    type StmtKind = InsertStmtWithoutOnConflictDoUpdate;
122}
123
124impl<V, Target, Changeset, Tab, WhereClause> InsertStmtKind
125    for crate::query_builder::upsert::on_conflict_clause::OnConflictValues<
126        V,
127        Target,
128        crate::query_builder::upsert::on_conflict_actions::DoUpdate<Changeset, Tab>,
129        WhereClause,
130    >
131{
132    type StmtKind = InsertStmtWithOnConflictDoUpdate;
133}