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