diesel/query_builder/
from_clause.rs

1use super::{AstPass, QueryFragment, QueryId};
2use crate::backend::Backend;
3use crate::query_source::AppearsInFromClause;
4use crate::{QueryResult, QuerySource};
5
6/// This type represents a not existing from clause
7///
8/// Custom backends can provide a custom [`QueryFragment`]
9/// impl by specializing the implementation via
10/// [`SqlDialect::EmptyFromClauseSyntax`](crate::backend::SqlDialect::EmptyFromClauseSyntax)
11#[cfg_attr(
12    feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes",
13    cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")
14)]
15#[derive(Debug, Clone, Copy, QueryId)]
16pub struct NoFromClause;
17
18impl<DB> QueryFragment<DB> for NoFromClause
19where
20    Self: QueryFragment<DB, DB::EmptyFromClauseSyntax>,
21    DB: Backend,
22{
23    fn walk_ast<'b>(&'b self, pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
24        <Self as QueryFragment<DB, DB::EmptyFromClauseSyntax>>::walk_ast(self, pass)
25    }
26}
27
28impl<DB> QueryFragment<DB, crate::backend::sql_dialect::from_clause_syntax::AnsiSqlFromClauseSyntax>
29    for NoFromClause
30where
31    DB: Backend<EmptyFromClauseSyntax = crate::backend::sql_dialect::from_clause_syntax::AnsiSqlFromClauseSyntax>,
32{
33    fn walk_ast<'b>(&'b self, _pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
34        Ok(())
35    }
36}
37
38pub trait AsQuerySource {
39    type QuerySource: QuerySource;
40
41    fn as_query_source(&self) -> &Self::QuerySource;
42}
43
44impl<QS> AsQuerySource for QS
45where
46    QS: QuerySource,
47{
48    type QuerySource = Self;
49
50    fn as_query_source(&self) -> &Self::QuerySource {
51        self
52    }
53}
54
55#[doc(hidden)]
56pub struct FromClause<F: QuerySource> {
57    pub(crate) source: F,
58    pub(crate) from_clause: F::FromClause,
59}
60
61impl<F> AsQuerySource for FromClause<F>
62where
63    F: QuerySource,
64{
65    type QuerySource = F;
66
67    fn as_query_source(&self) -> &Self::QuerySource {
68        &self.source
69    }
70}
71
72impl<F> QueryId for FromClause<F>
73where
74    F: QuerySource + QueryId,
75{
76    type QueryId = F::QueryId;
77
78    const HAS_STATIC_QUERY_ID: bool = F::HAS_STATIC_QUERY_ID;
79}
80
81impl<F> Copy for FromClause<F>
82where
83    F: QuerySource + Copy,
84    F::FromClause: Copy,
85{
86}
87
88impl<F> Clone for FromClause<F>
89where
90    F: QuerySource + Clone,
91    F::FromClause: Clone,
92{
93    fn clone(&self) -> Self {
94        Self {
95            source: self.source.clone(),
96            from_clause: self.from_clause.clone(),
97        }
98    }
99}
100
101impl<F> std::fmt::Debug for FromClause<F>
102where
103    F: QuerySource,
104    F::FromClause: std::fmt::Debug,
105{
106    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107        f.debug_struct("FromClause")
108            .field("from_clause", &self.from_clause)
109            .finish()
110    }
111}
112
113impl<F: QuerySource> FromClause<F> {
114    pub(crate) fn new(qs: F) -> Self {
115        Self {
116            from_clause: qs.from_clause(),
117            source: qs,
118        }
119    }
120}
121
122impl<DB, F> QueryFragment<DB> for FromClause<F>
123where
124    F: QuerySource,
125    DB: Backend,
126    F::FromClause: QueryFragment<DB>,
127{
128    fn walk_ast<'b>(&'b self, mut pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
129        pass.push_sql(" FROM ");
130        self.from_clause.walk_ast(pass)
131    }
132}
133
134impl<QS1, QS2> AppearsInFromClause<QS1> for FromClause<QS2>
135where
136    QS1: QuerySource,
137    QS2: QuerySource,
138    QS2: AppearsInFromClause<QS1>,
139{
140    type Count = <QS2 as AppearsInFromClause<QS1>>::Count;
141}