1use std::marker::PhantomData;
11
12use crate::dialect::{Dialect, SupportsOnConflict};
13use crate::expr::{Column, ColumnKey, Value};
14use crate::render::{QuerySink, Sink, render_ident};
15use crate::scope::{BaseTable, Table};
16use crate::statement::Statement;
17use crate::update::Assignments;
18
19#[diagnostic::on_unimplemented(
28 message = "`{Self}` isn't a value this column accepts",
29 label = "expected the column's own Rust type, or an `Option` of it"
30)]
31pub trait IntoColumnValue<V> {
32 fn into_column_value(self) -> V;
33}
34
35mod insertable {
36 pub trait Sealed {}
41}
42
43#[doc(hidden)]
44pub use insertable::Sealed as InsertableSealed;
45
46#[diagnostic::on_unimplemented(
51 message = "every column of `{Self}`'s table is generated, so only one row at a time can be inserted",
52 label = "`DEFAULT VALUES` is what SQL calls a row with nothing in it, and it names no columns to repeat",
53 note = "insert them one statement at a time"
54)]
55pub trait Insertable: InsertableSealed {}
56
57#[diagnostic::on_unimplemented(
68 message = "column `{C}` hasn't been given a value yet",
69 label = "every column that is neither nullable nor defaulted needs one before `.build()`"
70)]
71pub trait Filled<C> {
72 #[doc(hidden)]
73 type Value;
74 #[doc(hidden)]
75 fn filled(self) -> Self::Value;
76}
77
78pub struct Missing<C>(std::marker::PhantomData<fn() -> C>);
82
83impl<C> Missing<C> {
84 #[doc(hidden)]
85 pub const fn new() -> Self {
86 Missing(std::marker::PhantomData)
87 }
88}
89
90impl<C> Default for Missing<C> {
91 fn default() -> Self {
92 Missing::new()
93 }
94}
95
96#[derive(Debug, Clone, PartialEq, Default)]
97pub enum Defaultable<T> {
98 #[default]
99 Default,
100 Value(T),
101}
102
103#[derive(Debug, Clone)]
104pub enum InsertValue {
105 Value(Value),
106 Default,
108}
109
110impl<T: Into<Value>> From<Defaultable<T>> for InsertValue {
111 fn from(d: Defaultable<T>) -> Self {
112 match d {
113 Defaultable::Default => InsertValue::Default,
114 Defaultable::Value(v) => InsertValue::Value(v.into()),
115 }
116 }
117}
118
119pub trait InsertRow: private::Sealed {
128 type Table: Table;
129
130 type Values: InsertValues;
139
140 fn into_values(self) -> Self::Values;
141}
142
143mod insert_values {
144 pub trait Sealed {}
147}
148
149fn collect_values<R: InsertRow>(row: R) -> Vec<InsertValue> {
151 let mut out = Vec::new();
152 row.into_values().push_values(&mut out);
153 out
154}
155
156pub trait InsertValues: insert_values::Sealed {
160 #[doc(hidden)]
161 fn push_names(out: &mut Vec<&'static str>);
162 #[doc(hidden)]
163 fn push_values(self, out: &mut Vec<InsertValue>);
164}
165
166impl insert_values::Sealed for crate::row::RowNil {}
167
168impl InsertValues for crate::row::RowNil {
169 fn push_names(_out: &mut Vec<&'static str>) {}
170 fn push_values(self, _out: &mut Vec<InsertValue>) {}
171}
172
173impl<C: crate::row::Named, Tail: InsertValues> insert_values::Sealed
174 for crate::row::RowCons<C, InsertValue, Tail>
175{
176}
177
178impl<C: crate::row::Named, Tail: InsertValues> InsertValues
179 for crate::row::RowCons<C, InsertValue, Tail>
180{
181 fn push_names(out: &mut Vec<&'static str>) {
182 out.push(<C as crate::row::Named>::NAME);
183 Tail::push_names(out);
184 }
185
186 fn push_values(self, out: &mut Vec<InsertValue>) {
187 let (value, tail) = self.into_cell();
188 out.push(value);
189 tail.push_values(out);
190 }
191}
192
193#[diagnostic::on_unimplemented(
198 message = "`{Self}` isn't an `ON CONFLICT` target for `{T}`",
199 label = "a column of that table, or a tuple of up to three of them"
200)]
201pub trait ConflictTarget<T: Table>: conflict_target::Sealed {
202 #[doc(hidden)]
203 fn column_names(&self) -> Vec<&'static str>;
204}
205
206mod conflict_target {
207 pub trait Sealed {}
211 impl<C: crate::expr::ColumnKey> Sealed for crate::expr::Column<C> {}
212 impl<A: crate::expr::ColumnKey> Sealed for (crate::expr::Column<A>,) {}
216 impl<A: crate::expr::ColumnKey, B: crate::expr::ColumnKey> Sealed
217 for (crate::expr::Column<A>, crate::expr::Column<B>)
218 {
219 }
220 impl<A: crate::expr::ColumnKey, B: crate::expr::ColumnKey, C: crate::expr::ColumnKey> Sealed
221 for (
222 crate::expr::Column<A>,
223 crate::expr::Column<B>,
224 crate::expr::Column<C>,
225 )
226 {
227 }
228}
229
230impl<C: ColumnKey> ConflictTarget<C::Table> for Column<C> {
231 fn column_names(&self) -> Vec<&'static str> {
232 vec![C::NAME]
233 }
234}
235
236macro_rules! conflict_target_tuple {
237 ($($name:ident),+) => {
238 #[allow(non_snake_case)]
239 impl<T: Table, $($name: ColumnKey<Table = T>,)+> ConflictTarget<T> for ($(Column<$name>,)+) {
240 fn column_names(&self) -> Vec<&'static str> {
241 vec![$(<$name as crate::row::Named>::NAME),+]
242 }
243 }
244 };
245}
246conflict_target_tuple!(A);
249conflict_target_tuple!(A, B);
250conflict_target_tuple!(A, B, C);
251
252enum ConflictAction<T> {
253 DoNothing,
254 DoUpdate(Assignments<T>),
263}
264
265struct ConflictClause<T> {
266 target: Vec<&'static str>,
267 action: ConflictAction<T>,
268}
269
270fn render_conflict_clause<D: Dialect, T>(clause: &ConflictClause<T>, sink: &mut dyn Sink) {
271 sink.text(" ON CONFLICT (");
272 for (i, c) in clause.target.iter().enumerate() {
273 if i > 0 {
274 sink.text(", ");
275 }
276 render_ident::<D>(sink, c);
277 }
278 sink.ch(')');
279 match &clause.action {
280 ConflictAction::DoNothing => sink.text(" DO NOTHING"),
281 ConflictAction::DoUpdate(sets) => {
282 sink.text(" DO UPDATE SET ");
283 sets.render_into::<D>(sink);
284 }
285 }
286}
287
288mod private {
289 pub trait Sealed {}
293}
294
295#[doc(hidden)]
296pub use private::Sealed as InsertRowSealed;
297
298pub struct InsertSeed<D, T> {
299 _marker: PhantomData<fn() -> (D, T)>,
300}
301
302pub fn insert<D, T: BaseTable>(_table: T) -> InsertSeed<D, T> {
303 InsertSeed {
304 _marker: PhantomData,
305 }
306}
307
308impl<D, T: Table> InsertSeed<D, T> {
309 pub fn values<R: InsertRow<Table = T>>(self, row: R) -> Insert<D, R> {
310 Insert {
311 rows: vec![collect_values(row)],
312 on_conflict: None,
313 _marker: PhantomData,
314 }
315 }
316
317 pub fn values_all<R: InsertRow<Table = T> + Insertable>(
322 self,
323 rows: impl IntoIterator<Item = R>,
324 ) -> Result<Insert<D, R>, NothingToInsert> {
325 let rows: Vec<_> = rows.into_iter().map(collect_values).collect();
326 if rows.is_empty() {
327 return Err(NothingToInsert);
328 }
329 Ok(Insert {
330 rows,
331 on_conflict: None,
332 _marker: PhantomData,
333 })
334 }
335}
336
337#[derive(Debug, Clone, Copy, PartialEq, Eq)]
342pub struct NothingToInsert;
343
344impl std::fmt::Display for NothingToInsert {
345 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
346 f.write_str("an INSERT must have at least one row, but no rows were given")
347 }
348}
349impl std::error::Error for NothingToInsert {}
350
351fn render_values_clause<D: Dialect, R: InsertRow>(
352 rows: &[Vec<InsertValue>],
353 on_conflict: &Option<ConflictClause<R::Table>>,
354) -> QuerySink<D> {
355 let mut sink = QuerySink::<D>::new();
356 sink.text("INSERT INTO ");
357 render_ident::<D>(&mut sink, <R::Table as Table>::NAME);
358
359 let mut header = Vec::new();
362 <R::Values as InsertValues>::push_names(&mut header);
363
364 if header.is_empty() {
369 sink.text(D::INSERT_NO_COLUMNS);
370 if let Some(clause) = on_conflict {
371 render_conflict_clause::<D, _>(clause, &mut sink);
372 }
373 return sink;
374 }
375
376 sink.text(" (");
377 for (i, name) in header.iter().enumerate() {
378 if i > 0 {
379 sink.text(", ");
380 }
381 render_ident::<D>(&mut sink, name);
382 }
383 sink.text(") VALUES ");
384
385 for (row_i, row) in rows.iter().enumerate() {
386 if row_i > 0 {
387 sink.text(", ");
388 }
389 sink.ch('(');
390 for (i, v) in row.iter().enumerate() {
391 if i > 0 {
392 sink.text(", ");
393 }
394 match v {
395 InsertValue::Default => sink.text("DEFAULT"),
396 InsertValue::Value(v) => sink.bind(v),
397 }
398 }
399 sink.ch(')');
400 }
401
402 if let Some(clause) = on_conflict {
403 render_conflict_clause::<D, _>(clause, &mut sink);
404 }
405
406 sink
407}
408
409pub struct Insert<D, R: InsertRow> {
410 rows: Vec<Vec<InsertValue>>,
411 on_conflict: Option<ConflictClause<R::Table>>,
412 _marker: PhantomData<fn() -> (D, R)>,
413}
414
415impl<D, R: InsertRow + Insertable> Insert<D, R> {
416 pub fn values(mut self, row: R) -> Self {
418 self.rows.push(collect_values(row));
419 self
420 }
421
422 pub fn values_all(mut self, rows: impl IntoIterator<Item = R>) -> Self {
426 self.rows.extend(rows.into_iter().map(collect_values));
427 self
428 }
429}
430
431impl<D: Dialect, R: InsertRow> Insert<D, R> {
432 pub fn on_conflict_do_nothing(mut self, target: impl ConflictTarget<R::Table>) -> Self
434 where
435 D: SupportsOnConflict,
436 {
437 self.on_conflict = Some(ConflictClause {
438 target: target.column_names(),
439 action: ConflictAction::DoNothing,
440 });
441 self
442 }
443
444 pub fn on_conflict_do_update(
447 mut self,
448 target: impl ConflictTarget<R::Table>,
449 set: Assignments<R::Table>,
450 ) -> Self
451 where
452 D: SupportsOnConflict,
453 {
454 self.on_conflict = Some(ConflictClause {
455 target: target.column_names(),
456 action: ConflictAction::DoUpdate(set),
457 });
458 self
459 }
460}
461
462impl<D: Dialect, R: InsertRow> crate::statement::private::Sealed for Insert<D, R> {}
463
464impl<D: Dialect, R: InsertRow> Statement for Insert<D, R> {
465 type Dialect = D;
466 type Table = R::Table;
467 fn render(&self) -> QuerySink<D> {
468 render_values_clause::<D, R>(&self.rows, &self.on_conflict)
469 }
470}