diesel/query_source/aliasing/
alias.rs

1use super::field_alias_mapper::FieldAliasMapper;
2use super::{AliasSource, AliasedField};
3
4use crate::backend::{sql_dialect, Backend};
5use crate::expression::{Expression, SelectableExpression, ValidGrouping};
6use crate::helper_types::AliasedFields;
7use crate::query_builder::{AsQuery, AstPass, FromClause, QueryFragment, QueryId, SelectStatement};
8use crate::query_source::{AppearsInFromClause, Column, Never, QuerySource, Table, TableNotEqual};
9use crate::result::QueryResult;
10
11use std::marker::PhantomData;
12
13#[derive(Debug, Clone, Copy, Default)]
14/// Represents an alias within diesel's query builder
15///
16/// See [`alias!`](crate::alias) for more details.
17#[diesel_derives::__diesel_public_if(
18    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
19    public_fields(source)
20)]
21pub struct Alias<S> {
22    /// The inner alias definition
23    pub(crate) source: S,
24}
25
26impl<S: AliasSource> Alias<S> {
27    /// Maps a single field of the source table in this alias
28    pub fn field<F>(&self, field: F) -> AliasedField<S, F>
29    where
30        F: Column<Table = S::Target>,
31    {
32        AliasedField {
33            _alias_source: PhantomData,
34            _field: field,
35        }
36    }
37    /// Maps multiple fields of the source table in this alias
38    /// (takes in tuples and some expressions)
39    pub fn fields<Fields>(&self, fields: Fields) -> AliasedFields<S, Fields>
40    where
41        Fields: FieldAliasMapper<S>,
42    {
43        fields.map(self)
44    }
45}
46
47impl<S> Alias<S> {
48    #[doc(hidden)]
49    /// May be used to create an alias. Used by the [`alias!`] macro.
50    pub const fn new(source: S) -> Self {
51        Self { source }
52    }
53}
54
55impl<S> QueryId for Alias<S>
56where
57    Self: 'static,
58    S: AliasSource,
59    S::Target: QueryId,
60{
61    type QueryId = Self;
62    const HAS_STATIC_QUERY_ID: bool = <S::Target as QueryId>::HAS_STATIC_QUERY_ID;
63}
64
65impl<S> QuerySource for Alias<S>
66where
67    Self: Clone,
68    S: AliasSource,
69    S::Target: QuerySource,
70    <S::Target as QuerySource>::DefaultSelection: FieldAliasMapper<S>,
71    <<S::Target as QuerySource>::DefaultSelection as FieldAliasMapper<S>>::Out:
72        SelectableExpression<Self>,
73{
74    type FromClause = Self;
75    type DefaultSelection =
76        <<S::Target as QuerySource>::DefaultSelection as FieldAliasMapper<S>>::Out;
77
78    fn from_clause(&self) -> Self::FromClause {
79        self.clone()
80    }
81
82    fn default_selection(&self) -> Self::DefaultSelection {
83        self.fields(self.source.target().default_selection())
84    }
85}
86
87impl<S, DB> QueryFragment<DB> for Alias<S>
88where
89    S: AliasSource,
90    DB: Backend,
91    Self: QueryFragment<DB, DB::AliasSyntax>,
92{
93    fn walk_ast<'b>(&'b self, pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
94        <Self as QueryFragment<DB, DB::AliasSyntax>>::walk_ast(self, pass)
95    }
96}
97
98impl<S, DB> QueryFragment<DB, sql_dialect::alias_syntax::AsAliasSyntax> for Alias<S>
99where
100    S: AliasSource,
101    DB: Backend,
102    S::Target: QueryFragment<DB>,
103{
104    fn walk_ast<'b>(&'b self, mut pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
105        self.source.target().walk_ast(pass.reborrow())?;
106        pass.push_sql(" AS ");
107        pass.push_identifier(S::NAME)?;
108        Ok(())
109    }
110}
111
112impl<S> AsQuery for Alias<S>
113where
114    S: AliasSource,
115    S::Target: AsQuery,
116    Self: QuerySource,
117    <Self as QuerySource>::DefaultSelection: ValidGrouping<()>,
118{
119    type SqlType = <<Self as QuerySource>::DefaultSelection as Expression>::SqlType;
120    type Query = SelectStatement<FromClause<Self>>;
121
122    fn as_query(self) -> Self::Query {
123        SelectStatement::simple(self)
124    }
125}
126
127/// This trait is used to allow external crates to implement
128/// `AppearsInFromClause<QS> for Alias<S>`
129///
130/// at the table level without running in conflicting impl issues
131///
132/// Implementing this at the table level (in the crate that defines the tables)
133/// does not result in conflicting impl issues because the table is the struct
134/// we're implementing on.
135pub trait AliasAppearsInFromClause<S, QS> {
136    /// Will be passed on to the `impl AppearsInFromClause<QS>`
137    type Count;
138}
139impl<S, QS> AppearsInFromClause<QS> for Alias<S>
140where
141    S: AliasSource,
142    S::Target: AliasAppearsInFromClause<S, QS>,
143{
144    type Count = <S::Target as AliasAppearsInFromClause<S, QS>>::Count;
145}
146
147/// This trait is used to allow external crates to implement
148/// `AppearsInFromClause<Alias<S2>> for Alias<S1>`
149///
150/// at the table level without running in conflicting impl issues
151///
152/// Implementing this at the table level (in the crate that defines the tables)
153/// does not result in conflicting impl issues because the tables are specified as both first
154/// argument of the trait and struct we're implementing on.
155pub trait AliasAliasAppearsInFromClause<T2, S1, S2> {
156    /// Will be passed on to the `impl AppearsInFromClause<QS>`
157    type Count;
158}
159impl<T1, S1, S2> AliasAppearsInFromClause<S1, Alias<S2>> for T1
160where
161    S2: AliasSource,
162    T1: AliasAliasAppearsInFromClause<S2::Target, S1, S2>,
163{
164    type Count = <T1 as AliasAliasAppearsInFromClause<S2::Target, S1, S2>>::Count;
165}
166
167/// This trait is used to allow external crates to implement
168/// `AppearsInFromClause<Alias<S2>> for Alias<S1>`
169///
170/// at the alias level without running in conflicting impl issues
171///
172/// Implementing this at the alias level (in the crate that defines the aliases)
173/// does not result in conflicting impl issues because the aliases are specified as both first
174/// argument of the trait and struct we're implementing on.
175///
176/// The corresponding implementation of `AliasAliasAppearsInFromClause` for implementors of this
177/// trait is done at the table level, to avoid conflict with the implementation for distinct tables
178/// below.
179pub trait AliasAliasAppearsInFromClauseSameTable<S2, T> {
180    /// Will be passed on to the `impl AppearsInFromClause<QS>`
181    type Count;
182}
183
184// impl<S: AliasSource<Table=T1>> AppearsInFromClause<T2> for Alias<S>
185// where T1 != T2
186impl<T1, T2, S> AliasAppearsInFromClause<S, T2> for T1
187where
188    T1: TableNotEqual<T2> + Table,
189    T2: Table,
190    S: AliasSource<Target = T1>,
191{
192    type Count = Never;
193}
194
195// impl<S1, S2> AppearsInFromClause<Alias<S1>> for Alias<S2>
196// where S1: AliasSource, S2: AliasSource, S1::Table != S2::Table
197impl<T1, T2, S1, S2> AliasAliasAppearsInFromClause<T1, S2, S1> for T2
198where
199    T1: TableNotEqual<T2> + Table,
200    T2: Table,
201    S1: AliasSource<Target = T1>,
202    S2: AliasSource<Target = T2>,
203{
204    type Count = Never;
205}
206
207/// To be able to define `helper_types::Fields` with the usual conventions
208///
209/// This type is intentionally not publicly exported
210#[allow(unreachable_pub)]
211pub trait GetAliasSourceFromAlias {
212    type Source;
213}
214
215impl<S> GetAliasSourceFromAlias for Alias<S> {
216    type Source = S;
217}