1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
use super::field_alias_mapper::FieldAliasMapper;
use super::{AliasSource, AliasedField};

use crate::backend::Backend;
use crate::expression::{Expression, SelectableExpression, ValidGrouping};
use crate::helper_types::AliasedFields;
use crate::query_builder::{AsQuery, AstPass, FromClause, QueryFragment, QueryId, SelectStatement};
use crate::query_source::{AppearsInFromClause, Column, Never, QuerySource, Table, TableNotEqual};
use crate::result::QueryResult;

use std::marker::PhantomData;

#[derive(Debug, Clone, Copy, Default)]
/// Represents an alias within diesel's query builder
///
/// See [`alias!`](crate::alias) for more details.
pub struct Alias<S> {
    pub(crate) source: S,
}

impl<S: AliasSource> Alias<S> {
    /// Maps a single field of the source table in this alias
    pub fn field<F>(&self, field: F) -> AliasedField<S, F>
    where
        F: Column<Table = S::Target>,
    {
        AliasedField {
            _alias_source: PhantomData,
            _field: field,
        }
    }
    /// Maps multiple fields of the source table in this alias
    /// (takes in tuples and some expressions)
    pub fn fields<Fields>(&self, fields: Fields) -> AliasedFields<S, Fields>
    where
        Fields: FieldAliasMapper<S>,
    {
        fields.map(self)
    }
}

impl<S> Alias<S> {
    #[doc(hidden)]
    /// May be used to create an alias. Used by the [`alias!`] macro.
    pub const fn new(source: S) -> Self {
        Self { source }
    }
}

impl<S> QueryId for Alias<S>
where
    Self: 'static,
    S: AliasSource,
    S::Target: QueryId,
{
    type QueryId = Self;
    const HAS_STATIC_QUERY_ID: bool = <S::Target as QueryId>::HAS_STATIC_QUERY_ID;
}

impl<S> QuerySource for Alias<S>
where
    Self: Clone,
    S: AliasSource,
    S::Target: QuerySource,
    <S::Target as QuerySource>::DefaultSelection: FieldAliasMapper<S>,
    <<S::Target as QuerySource>::DefaultSelection as FieldAliasMapper<S>>::Out:
        SelectableExpression<Self>,
{
    type FromClause = Self;
    type DefaultSelection =
        <<S::Target as QuerySource>::DefaultSelection as FieldAliasMapper<S>>::Out;

    fn from_clause(&self) -> Self::FromClause {
        self.clone()
    }

    fn default_selection(&self) -> Self::DefaultSelection {
        self.fields(self.source.target().default_selection())
    }
}

impl<S, DB> QueryFragment<DB> for Alias<S>
where
    S: AliasSource,
    DB: Backend,
    S::Target: QueryFragment<DB>,
{
    fn walk_ast<'b>(&'b self, mut pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
        self.source.target().walk_ast(pass.reborrow())?;
        pass.push_sql(" AS ");
        pass.push_identifier(S::NAME)?;
        Ok(())
    }
}

impl<S> AsQuery for Alias<S>
where
    S: AliasSource,
    S::Target: AsQuery,
    Self: QuerySource,
    <Self as QuerySource>::DefaultSelection: ValidGrouping<()>,
{
    type SqlType = <<Self as QuerySource>::DefaultSelection as Expression>::SqlType;
    type Query = SelectStatement<FromClause<Self>>;

    fn as_query(self) -> Self::Query {
        SelectStatement::simple(self)
    }
}

/// This trait is used to allow external crates to implement
/// `AppearsInFromClause<QS> for Alias<S>`
///
/// at the table level without running in conflicting impl issues
///
/// Implementing this at the table level (in the crate that defines the tables)
/// does not result in conflicting impl issues because the table is the struct
/// we're implementing on.
pub trait AliasAppearsInFromClause<S, QS> {
    /// Will be passed on to the `impl AppearsInFromClause<QS>`
    type Count;
}
impl<S, QS> AppearsInFromClause<QS> for Alias<S>
where
    S: AliasSource,
    S::Target: AliasAppearsInFromClause<S, QS>,
{
    type Count = <S::Target as AliasAppearsInFromClause<S, QS>>::Count;
}

/// This trait is used to allow external crates to implement
/// `AppearsInFromClause<Alias<S2>> for Alias<S1>`
///
/// at the table level without running in conflicting impl issues
///
/// Implementing this at the table level (in the crate that defines the tables)
/// does not result in conflicting impl issues because the tables are specified as both first
/// argument of the trait and struct we're implementing on.
pub trait AliasAliasAppearsInFromClause<T2, S1, S2> {
    /// Will be passed on to the `impl AppearsInFromClause<QS>`
    type Count;
}
impl<T1, S1, S2> AliasAppearsInFromClause<S1, Alias<S2>> for T1
where
    S2: AliasSource,
    T1: AliasAliasAppearsInFromClause<S2::Target, S1, S2>,
{
    type Count = <T1 as AliasAliasAppearsInFromClause<S2::Target, S1, S2>>::Count;
}

/// This trait is used to allow external crates to implement
/// `AppearsInFromClause<Alias<S2>> for Alias<S1>`
///
/// at the alias level without running in conflicting impl issues
///
/// Implementing this at the alias level (in the crate that defines the aliases)
/// does not result in conflicting impl issues because the aliases are specified as both first
/// argument of the trait and struct we're implementing on.
///
/// The corresponding implementation of `AliasAliasAppearsInFromClause` for implementors of this
/// trait is done at the table level, to avoid conflict with the implementation for distinct tables
/// below.
pub trait AliasAliasAppearsInFromClauseSameTable<S2, T> {
    /// Will be passed on to the `impl AppearsInFromClause<QS>`
    type Count;
}

// impl<S: AliasSource<Table=T1>> AppearsInFromClause<T2> for Alias<S>
// where T1 != T2
impl<T1, T2, S> AliasAppearsInFromClause<S, T2> for T1
where
    T1: TableNotEqual<T2> + Table,
    T2: Table,
    S: AliasSource<Target = T1>,
{
    type Count = Never;
}

// impl<S1, S2> AppearsInFromClause<Alias<S1>> for Alias<S2>
// where S1: AliasSource, S2: AliasSource, S1::Table != S2::Table
impl<T1, T2, S1, S2> AliasAliasAppearsInFromClause<T1, S2, S1> for T2
where
    T1: TableNotEqual<T2> + Table,
    T2: Table,
    S1: AliasSource<Target = T1>,
    S2: AliasSource<Target = T2>,
{
    type Count = Never;
}