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