1use super::{AppearsInFromClause, Plus, QuerySource};
2use backend::Backend;
3use expression::grouped::Grouped;
4use expression::nullable::Nullable;
5use expression::SelectableExpression;
6use prelude::*;
7use query_builder::*;
8use result::QueryResult;
9use sql_types::Bool;
10use util::TupleAppend;
11
12#[derive(Debug, Clone, Copy, QueryId)]
13pub struct Join<Left, Right, Kind> {
15 left: Left,
16 right: Right,
17 kind: Kind,
18}
19
20#[derive(Debug, Clone, Copy, QueryId)]
21#[doc(hidden)]
22pub struct JoinOn<Join, On> {
26 join: Join,
27 on: On,
28}
29
30impl<Left, Right, Kind> Join<Left, Right, Kind> {
31 pub fn new(left: Left, right: Right, kind: Kind) -> Self {
32 Join {
33 left: left,
34 right: right,
35 kind: kind,
36 }
37 }
38
39 #[doc(hidden)]
40 pub fn on<On>(self, on: On) -> JoinOn<Self, On> {
41 JoinOn { join: self, on: on }
42 }
43}
44
45impl<Left, Right> QuerySource for Join<Left, Right, Inner>
46where
47 Left: QuerySource + AppendSelection<Right::DefaultSelection>,
48 Right: QuerySource,
49 Left::Output: SelectableExpression<Self>,
50 Self: Clone,
51{
52 type FromClause = Self;
53 type DefaultSelection = Left::Output;
54
55 fn from_clause(&self) -> Self::FromClause {
56 self.clone()
57 }
58
59 fn default_selection(&self) -> Self::DefaultSelection {
60 self.left.append_selection(self.right.default_selection())
61 }
62}
63
64impl<Left, Right> QuerySource for Join<Left, Right, LeftOuter>
65where
66 Left: QuerySource + AppendSelection<Nullable<Right::DefaultSelection>>,
67 Right: QuerySource,
68 Left::Output: SelectableExpression<Self>,
69 Self: Clone,
70{
71 type FromClause = Self;
72 type DefaultSelection = Left::Output;
73
74 fn from_clause(&self) -> Self::FromClause {
75 self.clone()
76 }
77
78 fn default_selection(&self) -> Self::DefaultSelection {
79 self.left
80 .append_selection(self.right.default_selection().nullable())
81 }
82}
83
84impl<Join, On> QuerySource for JoinOn<Join, On>
85where
86 Join: QuerySource,
87 On: AppearsOnTable<Join::FromClause, SqlType = Bool> + Clone,
88 Join::DefaultSelection: SelectableExpression<Self>,
89{
90 type FromClause = Grouped<nodes::InfixNode<'static, Join::FromClause, On>>;
91 type DefaultSelection = Join::DefaultSelection;
92
93 fn from_clause(&self) -> Self::FromClause {
94 Grouped(nodes::InfixNode::new(
95 self.join.from_clause(),
96 self.on.clone(),
97 " ON ",
98 ))
99 }
100
101 fn default_selection(&self) -> Self::DefaultSelection {
102 self.join.default_selection()
103 }
104}
105
106impl<Left, Right, Kind, DB> QueryFragment<DB> for Join<Left, Right, Kind>
107where
108 DB: Backend,
109 Left: QuerySource,
110 Left::FromClause: QueryFragment<DB>,
111 Right: QuerySource,
112 Right::FromClause: QueryFragment<DB>,
113 Kind: QueryFragment<DB>,
114{
115 fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
116 self.left.from_clause().walk_ast(out.reborrow())?;
117 self.kind.walk_ast(out.reborrow())?;
118 out.push_sql(" JOIN ");
119 self.right.from_clause().walk_ast(out.reborrow())?;
120 Ok(())
121 }
122}
123
124impl<Left, Right, Kind, T> SelectableExpression<Join<Left, Right, Kind>> for Nullable<T>
125where
126 T: SelectableExpression<Join<Left, Right, Inner>>,
127 Nullable<T>: AppearsOnTable<Join<Left, Right, Kind>>,
128{
129}
130
131impl<Join, On, T> SelectableExpression<JoinOn<Join, On>> for Nullable<T>
133where
134 Nullable<T>: SelectableExpression<Join>,
135 Nullable<T>: AppearsOnTable<JoinOn<Join, On>>,
136{
137}
138
139impl<From, T> SelectableExpression<SelectStatement<From>> for Nullable<T>
141where
142 Nullable<T>: SelectableExpression<From>,
143 Nullable<T>: AppearsOnTable<SelectStatement<From>>,
144{
145}
146
147pub trait JoinTo<T> {
167 #[doc(hidden)]
168 type FromClause;
169 #[doc(hidden)]
170 type OnClause;
171 #[doc(hidden)]
172 fn join_target(rhs: T) -> (Self::FromClause, Self::OnClause);
173}
174
175#[doc(hidden)]
176pub trait AppendSelection<Selection> {
181 type Output;
182
183 fn append_selection(&self, selection: Selection) -> Self::Output;
184}
185
186impl<T: Table, Selection> AppendSelection<Selection> for T {
187 type Output = (T::AllColumns, Selection);
188
189 fn append_selection(&self, selection: Selection) -> Self::Output {
190 (T::all_columns(), selection)
191 }
192}
193
194impl<Left, Mid, Selection, Kind> AppendSelection<Selection> for Join<Left, Mid, Kind>
195where
196 Self: QuerySource,
197 <Self as QuerySource>::DefaultSelection: TupleAppend<Selection>,
198{
199 type Output = <<Self as QuerySource>::DefaultSelection as TupleAppend<Selection>>::Output;
200
201 fn append_selection(&self, selection: Selection) -> Self::Output {
202 self.default_selection().tuple_append(selection)
203 }
204}
205
206impl<Join, On, Selection> AppendSelection<Selection> for JoinOn<Join, On>
207where
208 Join: AppendSelection<Selection>,
209{
210 type Output = Join::Output;
211
212 fn append_selection(&self, selection: Selection) -> Self::Output {
213 self.join.append_selection(selection)
214 }
215}
216
217#[doc(hidden)]
218#[derive(Debug, Clone, Copy, Default, QueryId)]
219pub struct Inner;
220
221impl<DB: Backend> QueryFragment<DB> for Inner {
222 fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
223 out.push_sql(" INNER");
224 Ok(())
225 }
226}
227
228#[doc(hidden)]
229#[derive(Debug, Clone, Copy, Default, QueryId)]
230pub struct LeftOuter;
231
232impl<DB: Backend> QueryFragment<DB> for LeftOuter {
233 fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
234 out.push_sql(" LEFT OUTER");
235 Ok(())
236 }
237}
238
239impl<Left, Mid, Right, Kind> JoinTo<Right> for Join<Left, Mid, Kind>
240where
241 Left: JoinTo<Right>,
242{
243 type FromClause = Left::FromClause;
244 type OnClause = Left::OnClause;
245
246 fn join_target(rhs: Right) -> (Self::FromClause, Self::OnClause) {
247 Left::join_target(rhs)
248 }
249}
250
251impl<Join, On, Right> JoinTo<Right> for JoinOn<Join, On>
252where
253 Join: JoinTo<Right>,
254{
255 type FromClause = Join::FromClause;
256 type OnClause = Join::OnClause;
257
258 fn join_target(rhs: Right) -> (Self::FromClause, Self::OnClause) {
259 Join::join_target(rhs)
260 }
261}
262
263impl<T, Left, Right, Kind> AppearsInFromClause<T> for Join<Left, Right, Kind>
264where
265 Left: AppearsInFromClause<T>,
266 Right: AppearsInFromClause<T>,
267 Left::Count: Plus<Right::Count>,
268{
269 type Count = <Left::Count as Plus<Right::Count>>::Output;
270}
271
272impl<T, Join, On> AppearsInFromClause<T> for JoinOn<Join, On>
273where
274 Join: AppearsInFromClause<T>,
275{
276 type Count = Join::Count;
277}
278
279#[doc(hidden)]
280#[derive(Debug, Clone, Copy)]
281pub struct OnClauseWrapper<Source, On> {
282 source: Source,
283 on: On,
284}
285
286impl<Source, On> OnClauseWrapper<Source, On> {
287 pub fn new(source: Source, on: On) -> Self {
288 OnClauseWrapper { source, on }
289 }
290}
291
292impl<Lhs, Rhs, On> JoinTo<OnClauseWrapper<Rhs, On>> for Lhs
293where
294 Lhs: Table,
295{
296 type FromClause = Rhs;
297 type OnClause = On;
298
299 fn join_target(rhs: OnClauseWrapper<Rhs, On>) -> (Self::FromClause, Self::OnClause) {
300 (rhs.source, rhs.on)
301 }
302}