diesel/query_source/aliasing/
aliased_field.rs

1use diesel_derives::DieselNumericOps;
2
3use super::{Alias, AliasSource};
4
5use crate::backend::Backend;
6use crate::dsl;
7use crate::expression::{
8    is_aggregate, AppearsOnTable, AsExpression, Expression, SelectableExpression, ValidGrouping,
9};
10use crate::expression_methods::{EqAll, ExpressionMethods};
11use crate::query_builder::{AstPass, FromClause, QueryFragment, QueryId, SelectStatement};
12use crate::query_source::{AppearsInFromClause, Column, Once, QuerySource};
13use crate::result::QueryResult;
14use crate::sql_types;
15
16use std::marker::PhantomData;
17
18#[derive(Debug, Clone, Copy, DieselNumericOps)]
19/// Represents an aliased field (column) within diesel's query builder
20///
21/// See [`alias!`](crate::alias) for more details.
22pub struct AliasedField<S, F> {
23    pub(super) _alias_source: PhantomData<S>,
24    pub(super) _field: F,
25}
26
27impl<S, C> QueryId for AliasedField<S, C>
28where
29    S: AliasSource + 'static,
30    S::Target: 'static,
31    C: Column<Table = S::Target> + 'static + QueryId,
32{
33    type QueryId = Self;
34    const HAS_STATIC_QUERY_ID: bool = <C as QueryId>::HAS_STATIC_QUERY_ID;
35}
36
37impl<QS, S, C> AppearsOnTable<QS> for AliasedField<S, C>
38where
39    S: AliasSource,
40    QS: AppearsInFromClause<Alias<S>, Count = Once>,
41    C: Column<Table = S::Target>,
42{
43}
44
45impl<S, C, DB> QueryFragment<DB> for AliasedField<S, C>
46where
47    S: AliasSource,
48    DB: Backend,
49    C: Column<Table = S::Target>,
50{
51    fn walk_ast<'b>(&'b self, mut pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
52        pass.push_identifier(S::NAME)?;
53        pass.push_sql(".");
54        pass.push_identifier(C::NAME)?;
55        Ok(())
56    }
57}
58
59impl<S, C> Expression for AliasedField<S, C>
60where
61    S: AliasSource,
62    C: Column<Table = S::Target> + Expression,
63{
64    type SqlType = C::SqlType;
65}
66
67impl<S, C> SelectableExpression<Alias<S>> for AliasedField<S, C>
68where
69    S: AliasSource,
70    C: Column<Table = S::Target>,
71    Self: AppearsOnTable<Alias<S>>,
72{
73}
74
75impl<S, C> ValidGrouping<()> for AliasedField<S, C>
76where
77    S: AliasSource,
78    C: Column<Table = S::Target>,
79{
80    type IsAggregate = is_aggregate::No;
81}
82
83impl<S, C1, C2> ValidGrouping<AliasedField<S, C1>> for AliasedField<S, C2>
84where
85    S: AliasSource,
86    C1: Column<Table = S::Target>,
87    C2: Column<Table = S::Target>,
88    C2: ValidGrouping<C1, IsAggregate = is_aggregate::Yes>,
89{
90    type IsAggregate = is_aggregate::Yes;
91}
92
93// FIXME: Remove this when overlapping marker traits are stable
94impl<From, S, C> SelectableExpression<SelectStatement<FromClause<From>>> for AliasedField<S, C>
95where
96    Self: SelectableExpression<From> + AppearsOnTable<SelectStatement<FromClause<From>>>,
97    From: QuerySource,
98{
99}
100
101impl<S, C, T> EqAll<T> for AliasedField<S, C>
102where
103    S: AliasSource,
104    C: Column<Table = S::Target>,
105    Self: ExpressionMethods,
106    <Self as Expression>::SqlType: sql_types::SqlType,
107    T: AsExpression<<Self as Expression>::SqlType>,
108    dsl::Eq<Self, T>: Expression<SqlType = sql_types::Bool>,
109{
110    type Output = dsl::Eq<Self, T>;
111
112    fn eq_all(self, rhs: T) -> Self::Output {
113        self.eq(rhs)
114    }
115}