diesel/type_impls/
tuples.rs

1use std::error::Error;
2
3use associations::BelongsTo;
4use backend::Backend;
5use deserialize::{self, FromSqlRow, Queryable, QueryableByName};
6use expression::{
7    AppearsOnTable, AsExpression, AsExpressionList, Expression, NonAggregate, SelectableExpression,
8};
9use insertable::{CanInsertInSingleQuery, InsertValues, Insertable};
10use query_builder::*;
11use query_source::*;
12use result::QueryResult;
13use row::*;
14use sql_types::{HasSqlType, NotNull};
15use util::TupleAppend;
16
17#[cfg(feature = "mysql")]
18use sql_types::IsSigned;
19
20macro_rules! tuple_impls {
21    ($(
22        $Tuple:tt {
23            $(($idx:tt) -> $T:ident, $ST:ident, $TT:ident,)+
24        }
25    )+) => {
26        $(
27            impl<$($T),+, __DB> HasSqlType<($($T,)+)> for __DB where
28                $(__DB: HasSqlType<$T>),+,
29                __DB: Backend,
30            {
31                fn metadata(_: &__DB::MetadataLookup) -> __DB::TypeMetadata {
32                    unreachable!("Tuples should never implement `ToSql` directly");
33                }
34
35                #[cfg(feature = "with-deprecated")]
36                #[allow(deprecated)]
37                fn row_metadata(out: &mut Vec<__DB::TypeMetadata>, lookup: &__DB::MetadataLookup) {
38                    $(<__DB as HasSqlType<$T>>::row_metadata(out, lookup);)+
39                }
40
41                #[cfg(feature = "mysql")]
42                fn mysql_row_metadata(out: &mut Vec<(__DB::TypeMetadata, IsSigned)>, lookup: &__DB::MetadataLookup) {
43                    $(<__DB as HasSqlType<$T>>::mysql_row_metadata(out, lookup);)+
44                }
45            }
46
47            impl<$($T),+> NotNull for ($($T,)+) {
48            }
49
50            impl<$($T),+, $($ST),+, __DB> FromSqlRow<($($ST,)+), __DB> for ($($T,)+) where
51                __DB: Backend,
52                $($T: FromSqlRow<$ST, __DB>),+,
53            {
54                const FIELDS_NEEDED: usize = $($T::FIELDS_NEEDED +)+ 0;
55
56                fn build_from_row<RowT: Row<__DB>>(row: &mut RowT) -> Result<Self, Box<dyn Error + Send + Sync>> {
57                    Ok(($($T::build_from_row(row)?,)+))
58                }
59            }
60
61            impl<$($T),+, $($ST),+, __DB> Queryable<($($ST,)+), __DB> for ($($T,)+) where
62                __DB: Backend,
63                $($T: Queryable<$ST, __DB>),+,
64            {
65                type Row = ($($T::Row,)+);
66
67                fn build(row: Self::Row) -> Self {
68                    ($($T::build(row.$idx),)+)
69                }
70            }
71
72            impl<$($T,)+ __DB> QueryableByName<__DB> for ($($T,)+)
73            where
74                __DB: Backend,
75                $($T: QueryableByName<__DB>,)+
76            {
77                fn build<RowT: NamedRow<__DB>>(row: &RowT) -> deserialize::Result<Self> {
78                    Ok(($($T::build(row)?,)+))
79                }
80            }
81
82            impl<$($T: Expression + NonAggregate),+> Expression for ($($T,)+) {
83                type SqlType = ($(<$T as Expression>::SqlType,)+);
84            }
85
86            impl<$($T: QueryFragment<__DB>),+, __DB: Backend> QueryFragment<__DB> for ($($T,)+) {
87                #[allow(unused_assignments)]
88                fn walk_ast(&self, mut out: AstPass<__DB>) -> QueryResult<()> {
89                    let mut needs_comma = false;
90                    $(
91                        if !self.$idx.is_noop()? {
92                            if needs_comma {
93                                out.push_sql(", ");
94                            }
95                            self.$idx.walk_ast(out.reborrow())?;
96                            needs_comma = true;
97                        }
98                    )+
99                    Ok(())
100                }
101            }
102
103            impl<$($T,)+ Tab> ColumnList for ($($T,)+)
104            where
105                $($T: ColumnList<Table = Tab>,)+
106            {
107                type Table = Tab;
108
109                fn walk_ast<__DB: Backend>(&self, mut out: AstPass<__DB>) -> QueryResult<()> {
110                    $(
111                        if $idx != 0 {
112                            out.push_sql(", ");
113                        }
114                        self.$idx.walk_ast(out.reborrow())?;
115                    )+
116                    Ok(())
117                }
118            }
119
120            impl<$($T: QueryId),+> QueryId for ($($T,)+) {
121                type QueryId = ($($T::QueryId,)+);
122
123                const HAS_STATIC_QUERY_ID: bool = $($T::HAS_STATIC_QUERY_ID &&)+ true;
124            }
125
126            impl<$($T: Expression + NonAggregate),+> NonAggregate for ($($T,)+) {
127            }
128
129            impl<$($T,)+ Tab> UndecoratedInsertRecord<Tab> for ($($T,)+)
130            where
131                $($T: UndecoratedInsertRecord<Tab>,)+
132            {
133            }
134
135            impl<$($T,)+ __DB> CanInsertInSingleQuery<__DB> for ($($T,)+)
136            where
137                __DB: Backend,
138                $($T: CanInsertInSingleQuery<__DB>,)+
139            {
140                fn rows_to_insert(&self) -> Option<usize> {
141                    $(debug_assert_eq!(self.$idx.rows_to_insert(), Some(1));)+
142                    Some(1)
143                }
144            }
145
146            impl<$($T,)+ $($ST,)+ Tab> Insertable<Tab> for ($($T,)+)
147            where
148                $($T: Insertable<Tab, Values = ValuesClause<$ST, Tab>>,)+
149            {
150                type Values = ValuesClause<($($ST,)+), Tab>;
151
152                fn values(self) -> Self::Values {
153                    ValuesClause::new(($(self.$idx.values().values,)+))
154                }
155            }
156
157            impl<'a, $($T,)+ Tab> Insertable<Tab> for &'a ($($T,)+)
158            where
159                ($(&'a $T,)+): Insertable<Tab>,
160            {
161                type Values = <($(&'a $T,)+) as Insertable<Tab>>::Values;
162
163                fn values(self) -> Self::Values {
164                    ($(&self.$idx,)+).values()
165                }
166            }
167
168            #[allow(unused_assignments)]
169            impl<$($T,)+ Tab, __DB> InsertValues<Tab, __DB> for ($($T,)+)
170            where
171                Tab: Table,
172                __DB: Backend,
173                $($T: InsertValues<Tab, __DB>,)+
174            {
175                fn column_names(&self, mut out: AstPass<__DB>) -> QueryResult<()> {
176                    let mut needs_comma = false;
177                    $(
178                        let noop_element = self.$idx.is_noop()?;
179                        if !noop_element {
180                            if needs_comma {
181                                out.push_sql(", ");
182                            }
183                            self.$idx.column_names(out.reborrow())?;
184                            needs_comma = true;
185                        }
186                    )+
187                    Ok(())
188                }
189            }
190
191            impl<$($T,)+ QS> SelectableExpression<QS> for ($($T,)+) where
192                $($T: SelectableExpression<QS>,)+
193                ($($T,)+): AppearsOnTable<QS>,
194            {
195            }
196
197            impl<$($T,)+ QS> AppearsOnTable<QS> for ($($T,)+) where
198                $($T: AppearsOnTable<QS>,)+
199                ($($T,)+): Expression,
200            {
201            }
202
203            impl<Target, $($T,)+> AsChangeset for ($($T,)+) where
204                $($T: AsChangeset<Target=Target>,)+
205                Target: QuerySource,
206            {
207                type Target = Target;
208                type Changeset = ($($T::Changeset,)+);
209
210                fn as_changeset(self) -> Self::Changeset {
211                    ($(self.$idx.as_changeset(),)+)
212                }
213            }
214
215            impl<$($T,)+ Parent> BelongsTo<Parent> for ($($T,)+) where
216                A: BelongsTo<Parent>,
217            {
218                type ForeignKey = A::ForeignKey;
219                type ForeignKeyColumn = A::ForeignKeyColumn;
220
221                fn foreign_key(&self) -> Option<&Self::ForeignKey> {
222                    self.0.foreign_key()
223                }
224
225                fn foreign_key_column() -> Self::ForeignKeyColumn {
226                    A::foreign_key_column()
227                }
228            }
229
230            impl<$($T,)+ Next> TupleAppend<Next> for ($($T,)+) {
231                type Output = ($($T,)+ Next);
232
233                #[allow(non_snake_case)]
234                fn tuple_append(self, next: Next) -> Self::Output {
235                    let ($($T,)+) = self;
236                    ($($T,)+ next)
237                }
238            }
239
240            impl<$($T,)+ ST> AsExpressionList<ST> for ($($T,)+) where
241                $($T: AsExpression<ST>,)+
242            {
243                type Expression = ($($T::Expression,)+);
244
245                fn as_expression_list(self) -> Self::Expression {
246                    ($(self.$idx.as_expression(),)+)
247                }
248            }
249        )+
250    }
251}
252
253__diesel_for_each_tuple!(tuple_impls);