1use crate::backend::{Backend, DieselReserveSpecialization};
2use crate::dsl::SqlTypeOf;
3use crate::expression::{
4 AppearsOnTable, Expression, QueryMetadata, Selectable, SelectableExpression,
5 TypedExpressionType, ValidGrouping,
6};
7use crate::query_builder::*;
8use crate::result::QueryResult;
9
10#[derive(Debug)]
11pub struct SelectBy<T: Selectable<DB>, DB: Backend> {
12 selection: T::SelectExpression,
13 p: std::marker::PhantomData<(T, DB)>,
14}
15
16impl<T, DB> Clone for SelectBy<T, DB>
17where
18 DB: Backend,
19 T: Selectable<DB>,
20{
21 fn clone(&self) -> Self {
22 Self {
23 selection: T::construct_selection(),
24 p: std::marker::PhantomData,
25 }
26 }
27}
28
29impl<T, DB> Copy for SelectBy<T, DB>
30where
31 T: Selectable<DB>,
32 DB: Backend,
33 T::SelectExpression: Copy,
34{
35}
36
37impl<T, E, DB> QueryId for SelectBy<T, DB>
38where
39 DB: Backend,
40 T: Selectable<DB, SelectExpression = E>,
41 E: QueryId + Expression,
42{
43 type QueryId = E::QueryId;
44
45 const HAS_STATIC_QUERY_ID: bool = E::HAS_STATIC_QUERY_ID;
46}
47
48impl<T, DB> SelectBy<T, DB>
49where
50 T: Selectable<DB>,
51 DB: Backend,
52{
53 pub(crate) fn new() -> Self {
54 Self {
55 selection: T::construct_selection(),
56 p: std::marker::PhantomData,
57 }
58 }
59}
60
61impl<T, E, DB> Expression for SelectBy<T, DB>
62where
63 DB: Backend,
64 T: Selectable<DB, SelectExpression = E>,
65 E: QueryId + Expression,
66{
67 type SqlType = SelectBy<T, DB>;
68}
69
70impl<T, DB> TypedExpressionType for SelectBy<T, DB>
71where
72 T: Selectable<DB>,
73 DB: Backend,
74{
75}
76
77impl<T, GB, E, DB> ValidGrouping<GB> for SelectBy<T, DB>
78where
79 DB: Backend,
80 T: Selectable<DB, SelectExpression = E>,
81 E: Expression + ValidGrouping<GB>,
82{
83 type IsAggregate = E::IsAggregate;
84}
85
86impl<T, DB> QueryMetadata<SelectBy<T, DB>> for DB
87where
88 DB: Backend,
89 T: Selectable<DB>,
90 DB: QueryMetadata<SqlTypeOf<T::SelectExpression>>,
91{
92 fn row_metadata(lookup: &mut Self::MetadataLookup, out: &mut Vec<Option<Self::TypeMetadata>>) {
93 <DB as QueryMetadata<SqlTypeOf<<T as Selectable<DB>>::SelectExpression>>>::row_metadata(
94 lookup, out,
95 )
96 }
97}
98
99impl<T, DB> QueryFragment<DB> for SelectBy<T, DB>
100where
101 T: Selectable<DB>,
102 T::SelectExpression: QueryFragment<DB>,
103 DB: Backend + DieselReserveSpecialization,
104{
105 fn walk_ast<'b>(&'b self, out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
106 self.selection.walk_ast(out)
107 }
108}
109
110impl<T, QS, DB> SelectableExpression<QS> for SelectBy<T, DB>
111where
112 DB: Backend,
113 T: Selectable<DB>,
114 T::SelectExpression: SelectableExpression<QS>,
115 Self: AppearsOnTable<QS>,
116{
117}
118
119impl<T, QS, DB> AppearsOnTable<QS> for SelectBy<T, DB>
120where
121 DB: Backend,
122 T: Selectable<DB>,
123 T::SelectExpression: AppearsOnTable<QS>,
124 Self: Expression,
125{
126}