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