diesel/type_impls/
tuples.rs

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);