Skip to main content

diesel/expression/
subselect.rs

1use core::marker::PhantomData;
2
3use crate::expression::array_comparison::InExpression;
4use crate::expression::*;
5use crate::query_builder::*;
6use crate::query_source::{Never, Once};
7use crate::result::QueryResult;
8
9/// This struct tells our type system that the whatever we put in `values`
10/// will be handled by SQL as an expression of type `ST`.
11/// It also implements the usual `SelectableExpression` and `AppearsOnTable` traits
12/// (which is useful when using this as an expression). To enforce correctness here, it checks
13/// the dedicated [`ValidSubselect`]. This however does not check that the `SqlType` of
14/// [`SelectQuery`], matches `ST`, so appropriate constraints should be checked in places that
15/// construct Subselect. (It's not always equal, notably .single_value() makes `ST` nullable, and
16/// `exists` checks bounds on `SubSelect<T, Bool>` although there is actually no such subquery in
17/// the final SQL.)
18#[derive(#[automatically_derived]
impl<T: ::core::fmt::Debug, ST: ::core::fmt::Debug> ::core::fmt::Debug for
    Subselect<T, ST> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "Subselect",
            "values", &self.values, "_sql_type", &&self._sql_type)
    }
}Debug, #[automatically_derived]
impl<T: ::core::marker::Copy, ST: ::core::marker::Copy> ::core::marker::Copy
    for Subselect<T, ST> {
}Copy, #[automatically_derived]
impl<T: ::core::clone::Clone, ST: ::core::clone::Clone> ::core::clone::Clone
    for Subselect<T, ST> {
    #[inline]
    fn clone(&self) -> Self {
        Self {
            values: ::core::clone::Clone::clone(&self.values),
            _sql_type: ::core::clone::Clone::clone(&self._sql_type),
        }
    }
}Clone, const _: () =
    {
        use diesel;
        #[allow(non_camel_case_types)]
        impl<T: diesel::query_builder::QueryId,
            ST: diesel::query_builder::QueryId> diesel::query_builder::QueryId
            for Subselect<T, ST> {
            type QueryId =
                Subselect<<T as diesel::query_builder::QueryId>::QueryId,
                <ST as diesel::query_builder::QueryId>::QueryId>;
            const HAS_STATIC_QUERY_ID: bool =
                <T as diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID &&
                        <ST as diesel::query_builder::QueryId>::HAS_STATIC_QUERY_ID
                    && true;
            const IS_WINDOW_FUNCTION: bool =
                <T as diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION ||
                        <ST as diesel::query_builder::QueryId>::IS_WINDOW_FUNCTION
                    || false;
        }
    };QueryId)]
19pub struct Subselect<T, ST> {
20    values: T,
21    _sql_type: PhantomData<ST>,
22}
23
24impl<T, ST> Subselect<T, ST> {
25    pub(crate) fn new(values: T) -> Self {
26        Self {
27            values,
28            _sql_type: PhantomData,
29        }
30    }
31}
32
33impl<T: SelectQuery, ST> Expression for Subselect<T, ST>
34where
35    ST: SqlType + TypedExpressionType,
36{
37    // This is useful for `.single_value()`
38    type SqlType = ST;
39}
40
41impl<T, ST: SqlType> InExpression for Subselect<T, ST> {
42    type SqlType = ST;
43    fn is_empty(&self) -> bool {
44        false
45    }
46    fn is_array(&self) -> bool {
47        false
48    }
49}
50
51impl<T, ST, QS> SelectableExpression<QS> for Subselect<T, ST>
52where
53    Subselect<T, ST>: AppearsOnTable<QS>,
54    T: ValidSubselect<QS>,
55{
56}
57
58impl<T, ST, QS> AppearsOnTable<QS> for Subselect<T, ST>
59where
60    Subselect<T, ST>: Expression,
61    T: ValidSubselect<QS>,
62{
63}
64
65impl<T, ST, GB> ValidGrouping<GB> for Subselect<T, ST>
66where
67    T: ValidSubselectGrouping<GB>,
68{
69    type IsAggregate = T::IsAggregate;
70}
71
72impl<T, ST, DB> QueryFragment<DB> for Subselect<T, ST>
73where
74    DB: Backend,
75    T: QueryFragment<DB>,
76{
77    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
78        self.values.walk_ast(out.reborrow())?;
79        Ok(())
80    }
81}
82
83pub trait ValidSubselect<QS> {}
84
85#[diagnostic::on_unimplemented(
86    message = "`{Self}` cannot be used as a subselect",
87    note = "only select statements and their combinations can be used as subselects"
88)]
89pub trait ValidSubselectGrouping<GB> {
90    type IsAggregate;
91}
92
93/// Grouping context of a subselect `WHERE` clause, from the outer `GB` and the subselect `From`.
94#[derive(#[automatically_derived]
impl<GB: ::core::fmt::Debug, From: ::core::fmt::Debug> ::core::fmt::Debug for
    SubselectGroupBy<GB, From> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_tuple_field1_finish(f,
            "SubselectGroupBy", &&self.0)
    }
}Debug, #[automatically_derived]
impl<GB: ::core::clone::Clone, From: ::core::clone::Clone>
    ::core::clone::Clone for SubselectGroupBy<GB, From> {
    #[inline]
    fn clone(&self) -> Self { Self(::core::clone::Clone::clone(&self.0)) }
}Clone, #[automatically_derived]
impl<GB: ::core::marker::Copy, From: ::core::marker::Copy>
    ::core::marker::Copy for SubselectGroupBy<GB, From> {
}Copy)]
95pub struct SubselectGroupBy<GB, From>(PhantomData<(GB, From)>);
96
97/// Grouping of `Field` in a subselect, keyed by how often its relation appears in the subselect `FROM`.
98pub trait SubselectFieldGrouping<Field, GB> {
99    /// See [`ValidGrouping::IsAggregate`]
100    type IsAggregate;
101}
102
103impl<Field, GB> SubselectFieldGrouping<Field, GB> for Once {
104    type IsAggregate = is_aggregate::Never;
105}
106
107impl<Field, GB> SubselectFieldGrouping<Field, GB> for Never
108where
109    Field: ValidGrouping<GB>,
110{
111    type IsAggregate = Field::IsAggregate;
112}