1use crate::associations::BelongsTo;
2use crate::backend::Backend;
3use crate::deserialize::{
4 self, FromSqlRow, FromStaticSqlRow, Queryable, SqlTypeOrSelectable, StaticallySizedRow,
5};
6use crate::expression::{
7 is_contained_in_group_by, AppearsOnTable, Expression, IsContainedInGroupBy, MixedAggregates,
8 QueryMetadata, Selectable, SelectableExpression, TypedExpressionType, ValidGrouping,
9};
10use crate::insertable::{CanInsertInSingleQuery, InsertValues, Insertable, InsertableOptionHelper};
11use crate::query_builder::*;
12use crate::query_dsl::load_dsl::CompatibleType;
13use crate::query_source::*;
14use crate::result::QueryResult;
15use crate::row::*;
16use crate::sql_types::{HasSqlType, IntoNullable, Nullable, OneIsNullable, SqlType};
17use crate::util::{TupleAppend, TupleSize};
18
19impl<T> TupleSize for T
20where
21 T: crate::sql_types::SingleValue,
22{
23 const SIZE: usize = 1;
24}
25
26macro_rules! tuple_impls {
27 ($(
28 $Tuple:tt {
29 $(($idx:tt) -> $T:ident, $ST:ident, $TT:ident,)+
30 }
31 )+) => {
32 $(
33 impl<$($T),+, __DB> HasSqlType<($($T,)+)> for __DB where
34 $(__DB: HasSqlType<$T>),+,
35 __DB: Backend,
36 {
37 fn metadata(_: &mut __DB::MetadataLookup) -> __DB::TypeMetadata {
38 unreachable!("Tuples should never implement `ToSql` directly");
39 }
40 }
41
42 impl_from_sql_row!(($($T,)+), ($($ST,)+));
43
44
45 impl<$($T: Expression),+> Expression for ($($T,)+)
46 where ($($T::SqlType, )*): TypedExpressionType
47 {
48 type SqlType = ($(<$T as Expression>::SqlType,)+);
49 }
50
51 impl<$($T: TypedExpressionType,)*> TypedExpressionType for ($($T,)*) {}
52 impl<$($T: SqlType + TypedExpressionType,)*> TypedExpressionType for Nullable<($($T,)*)>
53 where ($($T,)*): SqlType
54 {
55 }
56
57 impl<$($T: SqlType,)*> IntoNullable for ($($T,)*)
58 where Self: SqlType,
59 {
60 type Nullable = Nullable<($($T,)*)>;
61 }
62
63 impl<$($T,)+ __DB> Selectable<__DB> for ($($T,)+)
64 where
65 __DB: Backend,
66 $($T: Selectable<__DB>),+,
67 {
68 type SelectExpression = ($($T::SelectExpression,)+);
69
70 fn construct_selection() -> Self::SelectExpression {
71 ($($T::construct_selection(),)+)
72 }
73 }
74
75 impl<$($T: QueryFragment<__DB>),+, __DB: Backend> QueryFragment<__DB> for ($($T,)+) {
76 #[allow(unused_assignments)]
77 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, __DB>) -> QueryResult<()>
78 {
79 let mut needs_comma = false;
80 $(
81 if !self.$idx.is_noop(out.backend())? {
82 if needs_comma {
83 out.push_sql(", ");
84 }
85 self.$idx.walk_ast(out.reborrow())?;
86 needs_comma = true;
87 }
88 )+
89 Ok(())
90 }
91 }
92
93 impl<$($T,)+ Tab> ColumnList for ($($T,)+)
94 where
95 $($T: ColumnList<Table = Tab>,)+
96 {
97 type Table = Tab;
98
99 fn walk_ast<__DB: Backend>(&self, mut out: AstPass<'_, '_, __DB>) -> QueryResult<()> {
100 $(
101 if $idx != 0 {
102 out.push_sql(", ");
103 }
104 self.$idx.walk_ast(out.reborrow())?;
105 )+
106 Ok(())
107 }
108 }
109
110 impl<$($T: QueryId),+> QueryId for ($($T,)+) {
111 type QueryId = ($($T::QueryId,)+);
112
113 const HAS_STATIC_QUERY_ID: bool = $($T::HAS_STATIC_QUERY_ID &&)+ true;
114 }
115
116 impl_valid_grouping_for_tuple_of_columns!($($T,)*);
117
118 impl<$($T,)+ Tab> UndecoratedInsertRecord<Tab> for ($($T,)+)
119 where
120 $($T: UndecoratedInsertRecord<Tab>,)+
121 {
122 }
123
124 impl<$($T,)+ __DB> CanInsertInSingleQuery<__DB> for ($($T,)+)
125 where
126 __DB: Backend,
127 $($T: CanInsertInSingleQuery<__DB>,)+
128 {
129 fn rows_to_insert(&self) -> Option<usize> {
130 $(debug_assert_eq!(self.$idx.rows_to_insert(), Some(1));)+
131 Some(1)
132 }
133 }
134
135 impl<$($T,)+ $($ST,)+ Tab> Insertable<Tab> for ($($T,)+)
136 where
137 $($T: Insertable<Tab, Values = ValuesClause<$ST, Tab>>,)+
138 {
139 type Values = ValuesClause<($($ST,)+), Tab>;
140
141 fn values(self) -> Self::Values {
142 ValuesClause::new(($(self.$idx.values().values,)+))
143 }
144 }
145
146 impl<'a, $($T,)+ Tab> Insertable<Tab> for &'a ($($T,)+)
147 where
148 ($(&'a $T,)+): Insertable<Tab>,
149 {
150 type Values = <($(&'a $T,)+) as Insertable<Tab>>::Values;
151
152 fn values(self) -> Self::Values {
153 ($(&self.$idx,)+).values()
154 }
155 }
156
157 #[allow(unused_assignments)]
158 impl<$($T,)+ Tab, __DB> InsertValues<__DB, Tab> for ($($T,)+)
159 where
160 Tab: Table,
161 __DB: Backend,
162 $($T: InsertValues<__DB, Tab>,)+
163 {
164 fn column_names(&self, mut out: AstPass<'_, '_, __DB>) -> QueryResult<()> {
165 let mut needs_comma = false;
166 $(
167 let noop_element = self.$idx.is_noop(out.backend())?;
168 if !noop_element {
169 if needs_comma {
170 out.push_sql(", ");
171 }
172 self.$idx.column_names(out.reborrow())?;
173 needs_comma = true;
174 }
175 )+
176 Ok(())
177 }
178 }
179
180 impl<__T, $($ST,)* Tab> Insertable<Tab> for InsertableOptionHelper<__T, ($($ST,)*)>
181 where
182 __T: Insertable<Tab>,
183 __T::Values: Default,
184 {
185 type Values = __T::Values;
186
187 fn values(self) -> Self::Values {
188 self.0.map(|v| v.values()).unwrap_or_default()
189 }
190 }
191
192 impl<$($T,)+ QS> SelectableExpression<QS> for ($($T,)+) where
193 $($T: SelectableExpression<QS>,)+
194 ($($T,)+): AppearsOnTable<QS>,
195 {
196 }
197
198 impl<$($T,)+ QS> AppearsOnTable<QS> for ($($T,)+) where
199 $($T: AppearsOnTable<QS>,)+
200 ($($T,)+): Expression,
201 {
202 }
203
204 impl<Target, $($T,)+> AsChangeset for ($($T,)+) where
205 $($T: AsChangeset<Target=Target>,)+
206 Target: QuerySource,
207 {
208 type Target = Target;
209 type Changeset = ($($T::Changeset,)+);
210
211 fn as_changeset(self) -> Self::Changeset {
212 ($(self.$idx.as_changeset(),)+)
213 }
214 }
215
216 impl<$($T,)+ Parent> BelongsTo<Parent> for ($($T,)+) where
217 T0: BelongsTo<Parent>,
218 {
219 type ForeignKey = T0::ForeignKey;
220 type ForeignKeyColumn = T0::ForeignKeyColumn;
221
222 fn foreign_key(&self) -> Option<&Self::ForeignKey> {
223 self.0.foreign_key()
224 }
225
226 fn foreign_key_column() -> Self::ForeignKeyColumn {
227 T0::foreign_key_column()
228 }
229 }
230
231 impl<$($T,)+ Next> TupleAppend<Next> for ($($T,)+) {
232 type Output = ($($T,)+ Next);
233
234 #[allow(non_snake_case)]
235 fn tuple_append(self, next: Next) -> Self::Output {
236 let ($($T,)+) = self;
237 ($($T,)+ next)
238 }
239 }
240
241 impl_sql_type!($($T,)*);
242
243 impl<$($T,)* __DB, $($ST,)*> Queryable<($($ST,)*), __DB> for ($($T,)*)
244 where __DB: Backend,
245 Self: FromStaticSqlRow<($($ST,)*), __DB>,
246 {
247 type Row = Self;
248
249 fn build(row: Self::Row) -> deserialize::Result<Self> {
250 Ok(row)
251 }
252 }
253
254 impl<__T, $($ST,)* __DB> FromStaticSqlRow<Nullable<($($ST,)*)>, __DB> for Option<__T> where
255 __DB: Backend,
256 ($($ST,)*): SqlType,
257 __T: FromSqlRow<($($ST,)*), __DB>,
258 {
259
260 #[allow(non_snake_case, unused_variables, unused_mut)]
261 fn build_from_row<'a>(row: &impl Row<'a, __DB>)
262 -> deserialize::Result<Self>
263 {
264 match <__T as FromSqlRow<($($ST,)*), __DB>>::build_from_row(row) {
265 Ok(v) => Ok(Some(v)),
266 Err(e) if e.is::<crate::result::UnexpectedNullError>() => Ok(None),
267 Err(e) => Err(e)
268 }
269 }
270 }
271
272 impl<__T, __DB, $($ST,)*> Queryable<Nullable<($($ST,)*)>, __DB> for Option<__T>
273 where __DB: Backend,
274 Self: FromStaticSqlRow<Nullable<($($ST,)*)>, __DB>,
275 ($($ST,)*): SqlType,
276 {
277 type Row = Self;
278
279 fn build(row: Self::Row) -> deserialize::Result<Self> {
280 Ok(row)
281 }
282 }
283
284 impl<$($T,)*> TupleSize for ($($T,)*)
285 where $($T: TupleSize,)*
286 {
287 const SIZE: usize = $($T::SIZE +)* 0;
288 }
289
290 impl<$($T,)*> TupleSize for Nullable<($($T,)*)>
291 where $($T: TupleSize,)*
292 ($($T,)*): SqlType,
293 {
294 const SIZE: usize = $($T::SIZE +)* 0;
295 }
296
297 impl<$($T,)* __DB> QueryMetadata<($($T,)*)> for __DB
298 where __DB: Backend,
299 $(__DB: QueryMetadata<$T>,)*
300 {
301 fn row_metadata(lookup: &mut Self::MetadataLookup, row: &mut Vec<Option<__DB::TypeMetadata>>) {
302 $(
303 <__DB as QueryMetadata<$T>>::row_metadata(lookup, row);
304 )*
305 }
306 }
307
308 impl<$($T,)* __DB> QueryMetadata<Nullable<($($T,)*)>> for __DB
309 where __DB: Backend,
310 $(__DB: QueryMetadata<$T>,)*
311 {
312 fn row_metadata(lookup: &mut Self::MetadataLookup, row: &mut Vec<Option<__DB::TypeMetadata>>) {
313 $(
314 <__DB as QueryMetadata<$T>>::row_metadata(lookup, row);
315 )*
316 }
317 }
318
319 impl<$($T,)* __DB> deserialize::QueryableByName< __DB> for ($($T,)*)
320 where __DB: Backend,
321 $($T: deserialize::QueryableByName<__DB>,)*
322 {
323 fn build<'a>(row: &impl NamedRow<'a, __DB>) -> deserialize::Result<Self> {
324 Ok(($(
325 <$T as deserialize::QueryableByName<__DB>>::build(row)?,
326 )*))
327 }
328 }
329
330 impl<__T, $($ST,)* __DB> CompatibleType<__T, __DB> for ($($ST,)*)
331 where
332 __DB: Backend,
333 __T: FromSqlRow<($($ST,)*), __DB>,
334 {
335 type SqlType = Self;
336 }
337
338 impl<__T, $($ST,)* __DB> CompatibleType<Option<__T>, __DB> for Nullable<($($ST,)*)>
339 where
340 __DB: Backend,
341 ($($ST,)*): CompatibleType<__T, __DB>
342 {
343 type SqlType = Nullable<<($($ST,)*) as CompatibleType<__T, __DB>>::SqlType>;
344 }
345
346 impl<$($ST,)*> SqlTypeOrSelectable for ($($ST,)*)
347 where $($ST: SqlTypeOrSelectable,)*
348 {}
349
350 impl<$($ST,)*> SqlTypeOrSelectable for Nullable<($($ST,)*)>
351 where ($($ST,)*): SqlTypeOrSelectable
352 {}
353 )+
354 }
355}
356
357macro_rules! impl_from_sql_row {
358 (($T1: ident,), ($ST1: ident,)) => {
359 impl<$T1, $ST1, __DB> crate::deserialize::FromStaticSqlRow<($ST1,), __DB> for ($T1,) where
360 __DB: Backend,
361 $ST1: CompatibleType<$T1, __DB>,
362 $T1: FromSqlRow<<$ST1 as CompatibleType<$T1, __DB>>::SqlType, __DB>,
363 {
364
365 #[allow(non_snake_case, unused_variables, unused_mut)]
366 fn build_from_row<'a>(row: &impl Row<'a, __DB>)
367 -> deserialize::Result<Self>
368 {
369 Ok(($T1::build_from_row(row)?,))
370 }
371 }
372 };
373 (($T1: ident, $($T: ident,)*), ($ST1: ident, $($ST: ident,)*)) => {
374 impl<$T1, $($T,)* $($ST,)* __DB> FromSqlRow<($($ST,)* crate::sql_types::Untyped), __DB> for ($($T,)* $T1)
375 where __DB: Backend,
376 $T1: FromSqlRow<crate::sql_types::Untyped, __DB>,
377 $(
378 $T: FromSqlRow<$ST, __DB> + StaticallySizedRow<$ST, __DB>,
379 )*
380 {
381 #[allow(non_snake_case, unused_variables, unused_mut)]
382 fn build_from_row<'a>(full_row: &impl Row<'a, __DB>)
383 -> deserialize::Result<Self>
384 {
385 let field_count = full_row.field_count();
386
387 let mut static_field_count = 0;
388 $(
389 let row = full_row.partial_row(static_field_count..static_field_count + $T::FIELD_COUNT);
390 static_field_count += $T::FIELD_COUNT;
391 let $T = $T::build_from_row(&row)?;
392 )*
393
394 let row = full_row.partial_row(static_field_count..field_count);
395
396 Ok(($($T,)* $T1::build_from_row(&row)?,))
397 }
398 }
399
400 impl<$T1, $ST1, $($T,)* $($ST,)* __DB> FromStaticSqlRow<($($ST,)* $ST1,), __DB> for ($($T,)* $T1,) where
401 __DB: Backend,
402 $ST1: CompatibleType<$T1, __DB>,
403 $T1: FromSqlRow<<$ST1 as CompatibleType<$T1, __DB>>::SqlType, __DB>,
404 $(
405 $ST: CompatibleType<$T, __DB>,
406 $T: FromSqlRow<<$ST as CompatibleType<$T, __DB>>::SqlType, __DB> + StaticallySizedRow<<$ST as CompatibleType<$T, __DB>>::SqlType, __DB>,
407 )*
408
409 {
410
411 #[allow(non_snake_case, unused_variables, unused_mut)]
412 fn build_from_row<'a>(full_row: &impl Row<'a, __DB>)
413 -> deserialize::Result<Self>
414 {
415 let field_count = full_row.field_count();
416
417 let mut static_field_count = 0;
418 $(
419 let row = full_row.partial_row(static_field_count..static_field_count + $T::FIELD_COUNT);
420 static_field_count += $T::FIELD_COUNT;
421 let $T = <$T as FromSqlRow<<$ST as CompatibleType<$T, __DB>>::SqlType, __DB>>::build_from_row(&row)?;
422 )*
423
424 let row = full_row.partial_row(static_field_count..field_count);
425
426 Ok(($($T,)* $T1::build_from_row(&row)?,))
427 }
428 }
429 }
430}
431
432macro_rules! impl_valid_grouping_for_tuple_of_columns {
433 ($T1: ident, $($T: ident,)+) => {
434 impl<$T1, $($T,)* __GroupByClause> ValidGrouping<__GroupByClause> for ($T1, $($T,)*)
435 where
436 $T1: ValidGrouping<__GroupByClause>,
437 ($($T,)*): ValidGrouping<__GroupByClause>,
438 $T1::IsAggregate: MixedAggregates<<($($T,)*) as ValidGrouping<__GroupByClause>>::IsAggregate>,
439 {
440 type IsAggregate = <$T1::IsAggregate as MixedAggregates<<($($T,)*) as ValidGrouping<__GroupByClause>>::IsAggregate>>::Output;
441 }
442
443 impl<$T1, $($T,)* Col> IsContainedInGroupBy<Col> for ($T1, $($T,)*)
444 where Col: Column,
445 ($($T,)*): IsContainedInGroupBy<Col>,
446 $T1: IsContainedInGroupBy<Col>,
447 $T1::Output: is_contained_in_group_by::IsAny<<($($T,)*) as IsContainedInGroupBy<Col>>::Output>
448 {
449 type Output = <$T1::Output as is_contained_in_group_by::IsAny<<($($T,)*) as IsContainedInGroupBy<Col>>::Output>>::Output;
450 }
451 };
452 ($T1: ident,) => {
453 impl<$T1, Col> IsContainedInGroupBy<Col> for ($T1,)
454 where Col: Column,
455 $T1: IsContainedInGroupBy<Col>
456 {
457 type Output = <$T1 as IsContainedInGroupBy<Col>>::Output;
458 }
459
460 impl<$T1, __GroupByClause> ValidGrouping<__GroupByClause> for ($T1,)
461 where $T1: ValidGrouping<__GroupByClause>
462 {
463 type IsAggregate = $T1::IsAggregate;
464 }
465 };
466}
467
468macro_rules! impl_sql_type {
469 (
470 @build
471 start_ts = [$($ST: ident,)*],
472 ts = [$T1: ident,],
473 bounds = [$($bounds: tt)*],
474 is_null = [$($is_null: tt)*],
475 )=> {
476 impl<$($ST,)*> SqlType for ($($ST,)*)
477 where
478 $($ST: SqlType,)*
479 $($bounds)*
480 $T1::IsNull: OneIsNullable<$($is_null)*>,
481 {
482 type IsNull = <$T1::IsNull as OneIsNullable<$($is_null)*>>::Out;
483 }
484
485 };
486 (
487 @build
488 start_ts = [$($ST: ident,)*],
489 ts = [$T1: ident, $($T: ident,)+],
490 bounds = [$($bounds: tt)*],
491 is_null = [$($is_null: tt)*],
492 )=> {
493 impl_sql_type!{
494 @build
495 start_ts = [$($ST,)*],
496 ts = [$($T,)*],
497 bounds = [$($bounds)* $T1::IsNull: OneIsNullable<$($is_null)*>,],
498 is_null = [<$T1::IsNull as OneIsNullable<$($is_null)*>>::Out],
499 }
500 };
501 ($T1: ident, $($T: ident,)+) => {
502 impl_sql_type!{
503 @build
504 start_ts = [$T1, $($T,)*],
505 ts = [$($T,)*],
506 bounds = [],
507 is_null = [$T1::IsNull],
508 }
509 };
510 ($T1: ident,) => {
511 impl<$T1> SqlType for ($T1,)
512 where $T1: SqlType,
513 {
514 type IsNull = $T1::IsNull;
515 }
516 }
517}
518
519diesel_derives::__diesel_for_each_tuple!(tuple_impls);