1use std::marker::PhantomData;
2
3use backend::{Backend, SupportsDefaultKeyword};
4use expression::{AppearsOnTable, Expression};
5use query_builder::{
6 AstPass, InsertStatement, QueryFragment, UndecoratedInsertRecord, ValuesClause,
7};
8use query_source::{Column, Table};
9use result::QueryResult;
10#[cfg(feature = "sqlite")]
11use sqlite::Sqlite;
12
13pub trait Insertable<T> {
30 type Values;
37
38 fn values(self) -> Self::Values;
43
44 fn insert_into(self, table: T) -> InsertStatement<T, Self::Values>
82 where
83 Self: Sized,
84 {
85 ::insert_into(table).values(self)
86 }
87}
88
89pub trait CanInsertInSingleQuery<DB: Backend> {
90 fn rows_to_insert(&self) -> Option<usize>;
95}
96
97impl<'a, T, DB> CanInsertInSingleQuery<DB> for &'a T
98where
99 T: ?Sized + CanInsertInSingleQuery<DB>,
100 DB: Backend,
101{
102 fn rows_to_insert(&self) -> Option<usize> {
103 (*self).rows_to_insert()
104 }
105}
106
107impl<'a, T, Tab, DB> CanInsertInSingleQuery<DB> for BatchInsert<'a, T, Tab>
108where
109 DB: Backend + SupportsDefaultKeyword,
110{
111 fn rows_to_insert(&self) -> Option<usize> {
112 Some(self.records.len())
113 }
114}
115
116impl<T, Table, DB> CanInsertInSingleQuery<DB> for OwnedBatchInsert<T, Table>
117where
118 DB: Backend + SupportsDefaultKeyword,
119{
120 fn rows_to_insert(&self) -> Option<usize> {
121 Some(self.values.len())
122 }
123}
124
125impl<T, U, DB> CanInsertInSingleQuery<DB> for ColumnInsertValue<T, U>
126where
127 DB: Backend,
128{
129 fn rows_to_insert(&self) -> Option<usize> {
130 Some(1)
131 }
132}
133
134pub trait InsertValues<T: Table, DB: Backend>: QueryFragment<DB> {
135 fn column_names(&self, out: AstPass<DB>) -> QueryResult<()>;
136}
137
138#[derive(Debug, Copy, Clone)]
139#[doc(hidden)]
140pub enum ColumnInsertValue<Col, Expr> {
141 Expression(Col, Expr),
142 Default,
143}
144
145impl<Col, Expr> Default for ColumnInsertValue<Col, Expr> {
146 fn default() -> Self {
147 ColumnInsertValue::Default
148 }
149}
150
151impl<Col, Expr, DB> InsertValues<Col::Table, DB> for ColumnInsertValue<Col, Expr>
152where
153 DB: Backend + SupportsDefaultKeyword,
154 Col: Column,
155 Expr: Expression<SqlType = Col::SqlType> + AppearsOnTable<()>,
156 Self: QueryFragment<DB>,
157{
158 fn column_names(&self, mut out: AstPass<DB>) -> QueryResult<()> {
159 out.push_identifier(Col::NAME)?;
160 Ok(())
161 }
162}
163
164impl<Col, Expr, DB> QueryFragment<DB> for ColumnInsertValue<Col, Expr>
165where
166 DB: Backend + SupportsDefaultKeyword,
167 Expr: QueryFragment<DB>,
168{
169 fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
170 if let ColumnInsertValue::Expression(_, ref value) = *self {
171 value.walk_ast(out.reborrow())?;
172 } else {
173 out.push_sql("DEFAULT");
174 }
175 Ok(())
176 }
177}
178
179#[cfg(feature = "sqlite")]
180impl<Col, Expr> InsertValues<Col::Table, Sqlite> for ColumnInsertValue<Col, Expr>
181where
182 Col: Column,
183 Expr: Expression<SqlType = Col::SqlType> + AppearsOnTable<()>,
184 Self: QueryFragment<Sqlite>,
185{
186 fn column_names(&self, mut out: AstPass<Sqlite>) -> QueryResult<()> {
187 if let ColumnInsertValue::Expression(..) = *self {
188 out.push_identifier(Col::NAME)?;
189 }
190 Ok(())
191 }
192}
193
194#[cfg(feature = "sqlite")]
195impl<Col, Expr> QueryFragment<Sqlite> for ColumnInsertValue<Col, Expr>
196where
197 Expr: QueryFragment<Sqlite>,
198{
199 fn walk_ast(&self, mut out: AstPass<Sqlite>) -> QueryResult<()> {
200 if let ColumnInsertValue::Expression(_, ref value) = *self {
201 value.walk_ast(out.reborrow())?;
202 }
203 Ok(())
204 }
205}
206
207impl<'a, T, Tab> Insertable<Tab> for &'a [T]
208where
209 &'a T: UndecoratedInsertRecord<Tab>,
210{
211 type Values = BatchInsert<'a, T, Tab>;
212
213 fn values(self) -> Self::Values {
214 BatchInsert {
215 records: self,
216 _marker: PhantomData,
217 }
218 }
219}
220
221impl<'a, T, Tab> Insertable<Tab> for &'a Vec<T>
222where
223 &'a [T]: Insertable<Tab>,
224{
225 type Values = <&'a [T] as Insertable<Tab>>::Values;
226
227 fn values(self) -> Self::Values {
228 (&**self).values()
229 }
230}
231
232impl<T, Tab> Insertable<Tab> for Vec<T>
233where
234 T: Insertable<Tab> + UndecoratedInsertRecord<Tab>,
235{
236 type Values = OwnedBatchInsert<T::Values, Tab>;
237
238 fn values(self) -> Self::Values {
239 OwnedBatchInsert {
240 values: self.into_iter().map(Insertable::values).collect(),
241 _marker: PhantomData,
242 }
243 }
244}
245
246impl<T, Tab> Insertable<Tab> for Option<T>
247where
248 T: Insertable<Tab>,
249 T::Values: Default,
250{
251 type Values = T::Values;
252
253 fn values(self) -> Self::Values {
254 self.map(Insertable::values).unwrap_or_default()
255 }
256}
257
258impl<'a, T, Tab> Insertable<Tab> for &'a Option<T>
259where
260 Option<&'a T>: Insertable<Tab>,
261{
262 type Values = <Option<&'a T> as Insertable<Tab>>::Values;
263
264 fn values(self) -> Self::Values {
265 self.as_ref().values()
266 }
267}
268
269#[derive(Debug, Clone, Copy)]
270pub struct BatchInsert<'a, T: 'a, Tab> {
271 pub(crate) records: &'a [T],
272 _marker: PhantomData<Tab>,
273}
274
275impl<'a, T, Tab, Inner, DB> QueryFragment<DB> for BatchInsert<'a, T, Tab>
276where
277 DB: Backend + SupportsDefaultKeyword,
278 &'a T: Insertable<Tab, Values = ValuesClause<Inner, Tab>>,
279 ValuesClause<Inner, Tab>: QueryFragment<DB>,
280 Inner: QueryFragment<DB>,
281{
282 fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
283 let mut records = self.records.iter().map(Insertable::values);
284 if let Some(record) = records.next() {
285 record.walk_ast(out.reborrow())?;
286 }
287 for record in records {
288 out.push_sql(", (");
289 record.values.walk_ast(out.reborrow())?;
290 out.push_sql(")");
291 }
292 Ok(())
293 }
294}
295
296#[derive(Debug)]
297pub struct OwnedBatchInsert<V, Tab> {
298 pub(crate) values: Vec<V>,
299 _marker: PhantomData<Tab>,
300}
301
302impl<Tab, DB, Inner> QueryFragment<DB> for OwnedBatchInsert<ValuesClause<Inner, Tab>, Tab>
303where
304 DB: Backend + SupportsDefaultKeyword,
305 ValuesClause<Inner, Tab>: QueryFragment<DB>,
306 Inner: QueryFragment<DB>,
307{
308 fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
309 let mut values = self.values.iter();
310 if let Some(value) = values.next() {
311 value.walk_ast(out.reborrow())?;
312 }
313 for value in values {
314 out.push_sql(", (");
315 value.values.walk_ast(out.reborrow())?;
316 out.push_sql(")");
317 }
318 Ok(())
319 }
320}