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