qbrs_core/insert.rs
1//! `INSERT INTO ..`, from values or from a query.
2//!
3//! A column with a schema default gets a `Defaultable<T>` field, so "omit"
4//! and "explicit value" stay distinguishable. One that is nullable as well
5//! gets `Defaultable<Option<T>>`, making that three distinct states.
6//! Omission renders as the `DEFAULT` keyword in that row's `VALUES (..)`
7//! tuple rather than changing the column list, so rows that omit different
8//! fields still share one statement.
9//!
10//! An `ON CONFLICT` target names columns, and the database infers an index
11//! from them: one over exactly those columns whose own predicate the
12//! target's implies. A *partial* unique index therefore needs its predicate
13//! repeated, which is what `partial_index(..)` is for.
14
15use std::marker::PhantomData;
16
17use crate::dialect::{Dialect, SupportsOnConflict};
18use crate::expr::{AssignsTo, Column, ColumnKey, Expr, ExprKind, IntoExpr, Value, Writable};
19use crate::render::{Sink, render_ident};
20use crate::scope::{BaseTable, Cons, Nil, NotNull, Superset, Table, TableSlot};
21use crate::select::{Condition, Predicate};
22use crate::statement::{Statement, WrittenTable};
23use crate::update::Assignments;
24
25/// What a column's setter accepts, keyed by what that column's field
26/// holds: the column's own Rust type (`&str` for text), plus the `Option`
27/// a request struct already carries, wherever leaving the column out means
28/// something. What `None` means is the position's own: on an insert it is
29/// NULL for a nullable column and the schema's default for a defaulted one
30/// (`.<column>_null()` says the other, where a column is both); on an
31/// update it is *untouched*, since an `UPDATE` that says nothing about a
32/// column leaves it alone.
33#[diagnostic::on_unimplemented(
34 message = "`{Self}` isn't a value this column accepts",
35 label = "expected the column's own Rust type, or an `Option` of it"
36)]
37pub trait IntoColumnValue<V> {
38 fn into_column_value(self) -> V;
39}
40
41mod insertable {
42 /// Sealed like the other markers a derive emits. Unlike `Filled`, whose
43 /// doc explains why forging it buys nothing, forging this one turns a
44 /// bulk insert into a single `DEFAULT VALUES`, losing rows quietly, so
45 /// it gets the door even though a determined caller can still write it.
46 pub trait Sealed {}
47}
48
49#[doc(hidden)]
50pub use insertable::Sealed as InsertableSealed;
51
52/// A table with at least one column a statement may insert into. Emitted by
53/// `#[derive(Table)]` unless every column is generated, which leaves an
54/// `INSERT` with nothing to name: SQL spells that `DEFAULT VALUES`, and
55/// spells it for exactly one row.
56#[diagnostic::on_unimplemented(
57 message = "every column of `{Self}`'s table is generated, so only one row at a time can be inserted",
58 label = "`DEFAULT VALUES` is what SQL calls a row with nothing in it, and it names no columns to repeat",
59 note = "insert them one statement at a time"
60)]
61pub trait Insertable: InsertableSealed {}
62
63/// Proof that a builder's slot for column `C` holds that column's value.
64/// Deliberately unsealed, unlike `scope::Find`: forging it buys nothing,
65/// because `*Insert`'s fields are public and a complete row with a value of
66/// the caller's choosing is directly constructible. What the type-state
67/// builder prevents is *forgetting* a column, not choosing its value. A
68/// seal here can't hold anyway, since the derive must implement this in
69/// the schema's own crate, where any nameable proof is nameable twice.
70/// `Missing<C>` doesn't implement it, which is what `build()` is bounded
71/// by. That bound sits on the method rather than on the impl block, so an
72/// incomplete row is a sentence naming the column rather than a missing
73/// `build`.
74#[diagnostic::on_unimplemented(
75 message = "column `{C}` hasn't been given a value yet",
76 label = "every column that is neither nullable nor defaulted needs one before `.build()`"
77)]
78pub trait Filled<C> {
79 #[doc(hidden)]
80 type Value;
81 #[doc(hidden)]
82 fn filled(self) -> Self::Value;
83}
84
85/// A column an `*Insert` builder hasn't been given a value for yet. Named
86/// after the column so the builder's type says which one is missing, rather
87/// than leaving a bare `()` to be counted by position.
88pub struct Missing<C>(std::marker::PhantomData<fn() -> C>);
89
90impl<C> Missing<C> {
91 #[doc(hidden)]
92 pub const fn new() -> Self {
93 Missing(std::marker::PhantomData)
94 }
95}
96
97impl<C> Default for Missing<C> {
98 fn default() -> Self {
99 Missing::new()
100 }
101}
102
103#[derive(Debug, Clone, PartialEq, Default)]
104pub enum Defaultable<T> {
105 #[default]
106 Default,
107 Value(T),
108}
109
110#[derive(Debug, Clone)]
111pub enum InsertValue {
112 Value(Value),
113 /// Renders as the bare `DEFAULT` keyword in the `VALUES` list.
114 Default,
115}
116
117impl<T: Into<Value>> From<Defaultable<T>> for InsertValue {
118 fn from(d: Defaultable<T>) -> Self {
119 match d {
120 Defaultable::Default => InsertValue::Default,
121 Defaultable::Value(v) => InsertValue::Value(v.into()),
122 }
123 }
124}
125
126/// Implemented by the `#[derive(Table)]`-generated `*Insert` struct for each
127/// table. One list of `(column, value)` pairs rather than a name list beside
128/// a value list, for the reason `select::AllColumns` carries one list: the
129/// seal is `#[doc(hidden)] pub`, since the derive has to write it in the
130/// schema's own crate. Two lists that have to line up position for position
131/// could therefore be made not to, and `INSERT INTO t (a, b, c) VALUES ($1)`
132/// is malformed whatever the table looks like. `update::UpdateRow::sets` has
133/// always had this shape.
134pub trait InsertRow: private::Sealed {
135 type Table: Table;
136
137 /// This row's columns *and* values as one chain: the keys spell the
138 /// statement's header, the cells carry what goes under them. One type,
139 /// because two lists reconciled at render time is the shape that made
140 /// every earlier version of this trait able to produce SQL malformed
141 /// for any table, or to drop a value silently: a `COLUMNS` const
142 /// beside positional values, then pairs matched against the first row's
143 /// names, then pairs matched against a declared header. A chain can
144 /// carry neither a surplus cell nor a missing one.
145 type Values: InsertValues;
146
147 fn into_values(self) -> Self::Values;
148}
149
150mod insert_values {
151 /// Sealed to the two shapes a chain has, so `Values` is always a real
152 /// one. `row::ColumnNames` is sealed for the same reason.
153 pub trait Sealed {}
154}
155
156/// One row's cells, in the order its chain declares them.
157fn collect_values<R: InsertRow>(row: R) -> Vec<InsertValue> {
158 let mut out = Vec::new();
159 row.into_values().push_values(&mut out);
160 out
161}
162
163/// A chain of `(column, value)` cells: `RowCons<C, InsertValue, Tail>` down
164/// to `RowNil`. Walked once for the header and once for each row's values,
165/// so the two cannot disagree.
166pub trait InsertValues: insert_values::Sealed {
167 #[doc(hidden)]
168 fn push_names(out: &mut Vec<&'static str>);
169 #[doc(hidden)]
170 fn push_values(self, out: &mut Vec<InsertValue>);
171}
172
173impl insert_values::Sealed for crate::row::RowNil {}
174
175impl InsertValues for crate::row::RowNil {
176 fn push_names(_out: &mut Vec<&'static str>) {}
177 fn push_values(self, _out: &mut Vec<InsertValue>) {}
178}
179
180impl<C: crate::row::Named, Tail: InsertValues> insert_values::Sealed
181 for crate::row::RowCons<C, InsertValue, Tail>
182{
183}
184
185impl<C: crate::row::Named, Tail: InsertValues> InsertValues
186 for crate::row::RowCons<C, InsertValue, Tail>
187{
188 fn push_names(out: &mut Vec<&'static str>) {
189 out.push(<C as crate::row::Named>::NAME);
190 Tail::push_names(out);
191 }
192
193 fn push_values(self, out: &mut Vec<InsertValue>) {
194 let (value, tail) = self.into_cell();
195 out.push(value);
196 tail.push_values(out);
197 }
198}
199
200/// The columns an `ON CONFLICT` target infers an index from: one or more,
201/// proven by `T` to belong to the table being inserted into, where a raw
202/// `&[&str]` would let a typo through to the database. Implemented for a
203/// bare `Column<C>` and for tuples of up to three; add arities as real
204/// schemas need them.
205#[diagnostic::on_unimplemented(
206 message = "`{Self}` isn't a column list for `{T}`",
207 label = "a column of that table, or a tuple of up to three of them"
208)]
209pub trait ConflictColumns<T: Table>: conflict_target::ColumnsSealed<T> {
210 #[doc(hidden)]
211 fn column_names(&self) -> Vec<&'static str>;
212}
213
214/// An `ON CONFLICT` target: the columns, and for a partial unique index the
215/// predicate that picks it. Implemented for everything `ConflictColumns`
216/// is, plus the [`partial_index`] those columns pass through.
217#[diagnostic::on_unimplemented(
218 message = "`{Self}` isn't an `ON CONFLICT` target for `{T}`",
219 label = "a column of that table, a tuple of up to three of them, or `partial_index(..)` of either"
220)]
221pub trait ConflictTarget<T: Table>: conflict_target::Sealed<T> {
222 #[doc(hidden)]
223 fn into_target(self) -> Target;
224}
225
226/// The rendered half of a conflict target: the columns a dialect infers an
227/// index from, and the `index_predicate` that picks a *partial* one.
228#[doc(hidden)]
229pub struct Target {
230 columns: Vec<&'static str>,
231 index_predicate: Option<ExprKind>,
232}
233
234mod conflict_target {
235 /// Sealed for the reason `InsertRow` is: a hand-written impl could name
236 /// a column that isn't there, and the point of taking `Column<C>`s is
237 /// that it can't. Both seals carry the trait's own table parameter. A
238 /// seal on `Self` alone leaves that table a free slot the caller fills
239 /// with their own type, which is all the orphan rule asks for, and
240 /// `ON CONFLICT ("nickname")` against a table without one is exactly
241 /// the typo the seal is here to stop.
242 pub trait ColumnsSealed<T> {}
243 pub trait Sealed<T> {}
244}
245
246impl<C: ColumnKey> conflict_target::ColumnsSealed<C::Table> for Column<C> {}
247impl<C: ColumnKey> conflict_target::Sealed<C::Table> for Column<C> {}
248
249impl<C: ColumnKey> ConflictColumns<C::Table> for Column<C> {
250 fn column_names(&self) -> Vec<&'static str> {
251 vec![C::NAME]
252 }
253}
254
255impl<C: ColumnKey> ConflictTarget<C::Table> for Column<C> {
256 fn into_target(self) -> Target {
257 Target {
258 columns: self.column_names(),
259 index_predicate: None,
260 }
261 }
262}
263
264macro_rules! conflict_target_tuple {
265 ($($name:ident),+) => {
266 // Elements constrained, or the seal admits a tuple of anything.
267 impl<T: Table, $($name: ColumnKey<Table = T>,)+> conflict_target::ColumnsSealed<T>
268 for ($(Column<$name>,)+) {}
269 impl<T: Table, $($name: ColumnKey<Table = T>,)+> conflict_target::Sealed<T>
270 for ($(Column<$name>,)+) {}
271
272 #[allow(non_snake_case)]
273 impl<T: Table, $($name: ColumnKey<Table = T>,)+> ConflictColumns<T> for ($(Column<$name>,)+) {
274 fn column_names(&self) -> Vec<&'static str> {
275 vec![$(<$name as crate::row::Named>::NAME),+]
276 }
277 }
278
279 impl<T: Table, $($name: ColumnKey<Table = T>,)+> ConflictTarget<T> for ($(Column<$name>,)+) {
280 fn into_target(self) -> Target {
281 Target {
282 columns: self.column_names(),
283 index_predicate: None,
284 }
285 }
286 }
287 };
288}
289// Columns, not nested targets: a conflict target is a list of columns, and
290// letting it nest is what made the documented limit of three not one.
291conflict_target_tuple!(A);
292conflict_target_tuple!(A, B);
293conflict_target_tuple!(A, B, C);
294
295/// `ON CONFLICT (a, b) WHERE deleted_at IS NULL`: the conflict target of a
296/// **partial** unique index.
297///
298/// A target of bare columns is matched against an index over exactly those
299/// columns whose own predicate the target's implies. A target with no
300/// predicate implies only an index with none, so a partial index is
301/// unreachable without one. Implication, not equality: a predicate saying
302/// more than the index's still picks it. This is Postgres's
303/// `index_predicate`, and SQLite spells it the same way. It is only ever
304/// that: it does not filter which rows the conflict applies to, and where
305/// the columns also carry an unfiltered unique index that one still wins.
306///
307/// A predicate that implies no index at all is refused by the database
308/// rather than silently matching a different one.
309///
310/// ```ignore
311/// insert(members::Table)
312/// .values(row)
313/// .on_conflict_do_update(
314/// partial_index((members::team, members::handle), members::left_at.is_null()),
315/// assignments,
316/// )
317/// ```
318pub fn partial_index<T, Cols, E, Req, Idxs>(columns: Cols, index_predicate: E) -> PartialIndex<T>
319where
320 T: Table,
321 Cols: ConflictColumns<T>,
322 E: crate::expr::IntoExpr<Req = Req>,
323 E::Sql: crate::expr::BoolLike,
324 WrittenTable<T>: crate::scope::Superset<Req, Idxs>,
325{
326 PartialIndex {
327 target: Target {
328 columns: columns.column_names(),
329 index_predicate: Some(index_predicate.into_expr().kind),
330 },
331 _marker: PhantomData,
332 }
333}
334
335/// A conflict target narrowed to a partial unique index, from
336/// [`partial_index`]. It takes the columns rather than another target, so
337/// the predicate it carries is the only one there is.
338pub struct PartialIndex<T> {
339 target: Target,
340 _marker: PhantomData<fn() -> T>,
341}
342
343impl<T> conflict_target::Sealed<T> for PartialIndex<T> {}
344
345impl<T: Table> ConflictTarget<T> for PartialIndex<T> {
346 fn into_target(self) -> Target {
347 self.target
348 }
349}
350
351/// How the pseudo-table is spelled, in the one place a statement renders it
352/// and the one place the scope names it.
353pub(crate) const EXCLUDED: &str = "excluded";
354
355/// The row an `INSERT` proposed, as `ON CONFLICT DO UPDATE` sees it: a
356/// pseudo-table holding the target's own columns. Deliberately not a
357/// [`BaseTable`], so it is not a table a query can select from.
358/// [`excluded`] is the only way to name a column of it.
359///
360/// **Known limitation**: a schema table actually called `excluded` shadows
361/// nothing and is shadowed by this one, so an assignment naming that table
362/// in a `DO UPDATE` reads the proposed row. This is the general case of the
363/// one [`scope`](crate::scope) documents: two tables sharing a name are
364/// one table to the renderer.
365pub struct Excluded<T>(PhantomData<fn() -> T>);
366
367impl<T: Table> Table for Excluded<T> {
368 const NAME: &'static str = EXCLUDED;
369}
370
371/// What a `DO UPDATE` assignment may name: the conflicting row and the
372/// proposed one. An `UPDATE`'s own `SET` list is discharged against
373/// [`WrittenTable`] alone, which is what keeps [`excluded`] out of a
374/// statement that has no proposed row.
375pub type ConflictScope<T> = Cons<TableSlot<Excluded<T>, NotNull>, WrittenTable<T>>;
376
377/// `excluded.column`: the value the column would have taken had the row
378/// inserted, which is what `SET total = total + EXCLUDED.total` and the
379/// plain `SET v = EXCLUDED.v` of every upsert are written with. Reads as an
380/// ordinary expression over the target's columns, so it composes with them
381/// through everything that takes one; what confines it is the scope it is
382/// discharged against, and [`ConflictUpdate`] is the only list with it.
383pub fn excluded<C: ColumnKey>(_column: Column<C>) -> Expr<Cons<Excluded<C::Table>, Nil>, C::Sql> {
384 Expr::from_kind(ExprKind::Excluded {
385 name: <C as crate::row::Named>::NAME,
386 })
387}
388
389/// The `DO UPDATE` half of an upsert: everything an `UPDATE` assigns, plus
390/// [`excluded`], plus the `WHERE` that decides whether the update fires at
391/// all. An [`Assignments`] converts into one, so a request-shaped patch
392/// reaches an upsert as it always did; the reverse doesn't exist, which is
393/// what keeps a list naming the proposed row out of a statement that has
394/// none.
395///
396/// It carries `D` for the reason [`Predicate`] does: its `WHERE` is a
397/// condition like any other, and a condition pinned to one dialect must not
398/// reach a statement of another. The statement it is passed to says which
399/// dialect that is, so a value built inline needs no annotation. One bound
400/// to a `let` and never used does.
401pub struct ConflictUpdate<D, T> {
402 sets: Vec<(&'static str, ExprKind)>,
403 wheres: Vec<ExprKind>,
404 _marker: PhantomData<fn() -> (D, T)>,
405}
406
407impl<D, T> From<Assignments<T>> for ConflictUpdate<D, T> {
408 fn from(sets: Assignments<T>) -> Self {
409 ConflictUpdate {
410 sets: sets.into_sets(),
411 wheres: Vec::new(),
412 _marker: PhantomData,
413 }
414 }
415}
416
417impl<D, T: Table> ConflictUpdate<D, T> {
418 /// `column = <expression>`, over the conflicting row and the proposed
419 /// one. This is [`Assignments::set_to`] with the wider scope.
420 pub fn set_to<C, V, Idxs>(_column: Column<C>, value: V) -> Self
421 where
422 C: ColumnKey<Table = T> + Writable,
423 V: IntoExpr,
424 V::Sql: AssignsTo<C::Sql>,
425 ConflictScope<T>: Superset<V::Req, Idxs>,
426 {
427 ConflictUpdate {
428 sets: vec![(<C as crate::row::Named>::NAME, value.into_expr().kind)],
429 wheres: Vec::new(),
430 _marker: PhantomData,
431 }
432 }
433
434 /// One more of them.
435 pub fn and_set_to<C, V, Idxs>(mut self, _column: Column<C>, value: V) -> Self
436 where
437 C: ColumnKey<Table = T> + Writable,
438 V: IntoExpr,
439 V::Sql: AssignsTo<C::Sql>,
440 ConflictScope<T>: Superset<V::Req, Idxs>,
441 {
442 crate::update::push_set(
443 &mut self.sets,
444 <C as crate::row::Named>::NAME,
445 value.into_expr().kind,
446 );
447 self
448 }
449
450 /// `DO UPDATE SET .. WHERE <condition>`: which conflicting rows the
451 /// update actually touches, over the conflicting row and the proposed
452 /// one. A row the condition rejects is left as it is *and is not
453 /// counted*, so a one-row upsert's `rows_affected()` answers "did this
454 /// write anything" rather than always being 1. It counts the rows a
455 /// statement wrote, not the branch each took: a multi-row upsert's
456 /// count still folds inserts together with updates, and only zero says
457 /// nothing happened.
458 ///
459 /// A different clause from the one [`partial_index`] carries: that one
460 /// only picks which index the conflict is inferred against.
461 pub fn filter<C: Condition<D, ConflictScope<T>, Idxs>, Idxs>(mut self, cond: C) -> Self {
462 self.wheres.push(cond.into_predicate().into_kind());
463 self
464 }
465
466 /// AND-folds a runtime-length collection of discharged conditions, the
467 /// same way [`Update::filter_all`](crate::update::Update::filter_all)
468 /// does.
469 pub fn filter_all(
470 mut self,
471 conds: impl IntoIterator<Item = Predicate<D, ConflictScope<T>>>,
472 ) -> Self {
473 self.wheres
474 .extend(conds.into_iter().map(Predicate::into_kind));
475 self
476 }
477
478 /// A correlated subquery over the rows this action sees. It is the
479 /// same `EXISTS` [`Update::correlated`](crate::update::Update::correlated)
480 /// builds, against the conflicting row and the proposed one.
481 pub fn correlated<S, InnerSel>(
482 &self,
483 source: S,
484 selection: InnerSel,
485 ) -> crate::select::Select<
486 D,
487 Cons<TableSlot<S::Table, NotNull>, ConflictScope<T>>,
488 InnerSel,
489 ConflictScope<T>,
490 >
491 where
492 S: crate::select::JoinSource<D>,
493 {
494 crate::select::correlated_with(source, selection)
495 }
496}
497
498impl<D: Dialect, T> ConflictUpdate<D, T> {
499 fn render_into(&self, sink: &mut dyn Sink) {
500 for (i, (col, value)) in self.sets.iter().enumerate() {
501 if i > 0 {
502 sink.text(", ");
503 }
504 render_ident::<D>(sink, col);
505 sink.text(" = ");
506 crate::render::render_expr::<D>(value, sink);
507 }
508 crate::render::render_and_list::<D>(sink, " WHERE ", &self.wheres);
509 }
510}
511
512enum ConflictAction<D, T> {
513 DoNothing,
514 DoUpdate(ConflictUpdate<D, T>),
515}
516
517struct ConflictClause<D, T> {
518 target: Target,
519 action: ConflictAction<D, T>,
520}
521
522fn render_conflict_clause<D: Dialect, T>(clause: &ConflictClause<D, T>, sink: &mut dyn Sink) {
523 sink.text(" ON CONFLICT (");
524 for (i, c) in clause.target.columns.iter().enumerate() {
525 if i > 0 {
526 sink.text(", ");
527 }
528 render_ident::<D>(sink, c);
529 }
530 sink.ch(')');
531 if let Some(predicate) = &clause.target.index_predicate {
532 sink.text(" WHERE ");
533 crate::render::render_expr::<D>(predicate, sink);
534 }
535 match &clause.action {
536 ConflictAction::DoNothing => sink.text(" DO NOTHING"),
537 ConflictAction::DoUpdate(sets) => {
538 sink.text(" DO UPDATE SET ");
539 sets.render_into(sink);
540 }
541 }
542}
543
544mod private {
545 /// The row's `(column, value)` pairs are what a statement writes;
546 /// `#[derive(Table)]` is what guarantees that, so it is the only thing
547 /// that can produce an `InsertRow`.
548 pub trait Sealed {}
549}
550
551#[doc(hidden)]
552pub use private::Sealed as InsertRowSealed;
553
554pub struct InsertSeed<D, T> {
555 _marker: PhantomData<fn() -> (D, T)>,
556}
557
558pub fn insert<D, T: BaseTable>(_table: T) -> InsertSeed<D, T> {
559 InsertSeed {
560 _marker: PhantomData,
561 }
562}
563
564impl<D, T: Table> InsertSeed<D, T> {
565 pub fn values<R: InsertRow<Table = T>>(self, row: R) -> Insert<D, R> {
566 Insert {
567 rows: vec![collect_values(row)],
568 on_conflict: None,
569 _marker: PhantomData,
570 }
571 }
572
573 /// `INSERT INTO t (..) SELECT ..`: the rows a query produces, checked
574 /// against the target's own row by `row::SameShape`, the same one
575 /// comparison a `UNION` branch and a CTE body go through.
576 ///
577 /// The query fills every column the target lets a statement write: all
578 /// of them but the generated ones, which the database writes itself and
579 /// refuses a value for. That is the target's order too, which is its
580 /// `#[derive(Table)]` field order with the generated fields left out.
581 ///
582 /// `SameShape` walks the two lists together, so the source's columns
583 /// must be spelled and typed as the target's and come in that order.
584 /// Order because SQL fills an `INSERT`'s column list by position, and
585 /// the rendered header is read off the same list this is checked
586 /// against. SQL would widen an `INTEGER` into a `BIGINT` and take a NOT
587 /// NULL value for a nullable column, and neither is accepted here. A
588 /// source column under another name takes a `label!{}` one.
589 ///
590 /// **Known limitations**: the source is a `Select`, so a `SetOp`
591 /// (`UNION`) or a `DynSelect` cannot be one; a one-column target still
592 /// needs a one-tuple (`select((t::only,))`), since a bare selection is
593 /// a value rather than a row.
594 pub fn select<Scope, Sel, SelIdx, TgtIdx>(
595 self,
596 query: &crate::select::Select<D, Scope, Sel>,
597 ) -> InsertSelect<D, T>
598 where
599 D: Dialect,
600 T: WrittenColumns,
601 T::Columns: crate::select::ColumnList<WrittenTable<T>, TgtIdx>,
602 TargetRow<T, TgtIdx>: crate::row::ColumnNames,
603 Sel: crate::select::Selection<Scope, SelIdx>,
604 Sel::Output: crate::row::SameShape<crate::row::Row<TargetRow<T, TgtIdx>>>,
605 {
606 InsertSelect {
607 // Read off the very row the query was checked against, the way
608 // a `WITH` header is: one fact rather than two that could name
609 // different columns.
610 header: <TargetRow<T, TgtIdx> as crate::row::ColumnNames>::names(),
611 body: query.fragment::<SelIdx>(),
612 _marker: PhantomData,
613 }
614 }
615
616 /// Every row of a collection at once: the shape a bulk import has,
617 /// where the rows are already in a `Vec` and the first one isn't
618 /// special. `INSERT` with no rows has no SQL form, so an empty
619 /// collection is refused here rather than rendered.
620 pub fn values_all<R: InsertRow<Table = T> + Insertable>(
621 self,
622 rows: impl IntoIterator<Item = R>,
623 ) -> Result<Insert<D, R>, NothingToInsert> {
624 let rows: Vec<_> = rows.into_iter().map(collect_values).collect();
625 if rows.is_empty() {
626 return Err(NothingToInsert);
627 }
628 Ok(Insert {
629 rows,
630 on_conflict: None,
631 _marker: PhantomData,
632 })
633 }
634}
635
636/// The columns of a table an `INSERT` may name: all of them but the
637/// generated ones, which the database writes itself and refuses a value
638/// for. Emitted by `#[derive(Table)]` beside `select::AllColumns`, which is
639/// the other list: what a `SELECT` of the whole table reads.
640#[doc(hidden)]
641pub trait WrittenColumns {
642 /// `Cons<Column<C>, ..>`, in the schema's own order.
643 type Columns;
644}
645
646/// The row an `INSERT INTO t (..) SELECT ..` has to be handed: the target's
647/// writable columns, read in the one-table scope a write statement has.
648type TargetRow<T, Idx> = <<T as WrittenColumns>::Columns as crate::select::ColumnList<
649 WrittenTable<T>,
650 Idx,
651>>::Fields<crate::row::RowNil>;
652
653/// `INSERT INTO t (..) SELECT ..`: rows a query produces rather than rows
654/// a caller holds. From [`InsertSeed::select`].
655///
656/// The header is the target's own writable columns, so the two sides line
657/// up by the target's order rather than by whatever order its
658/// `CREATE TABLE` happened to use. The body is a `render::Fragment`,
659/// rendered before the statement knows how many parameters precede it, for
660/// the reason a CTE body is one.
661///
662/// **Known limitation**: no `ON CONFLICT` on this shape, and no column
663/// subset. The query fills every column the target lets one write.
664pub struct InsertSelect<D, T> {
665 header: Vec<&'static str>,
666 body: crate::render::Fragment,
667 _marker: PhantomData<fn() -> (D, T)>,
668}
669
670impl<D: Dialect, T: Table> crate::statement::private::Sealed for InsertSelect<D, T> {}
671
672impl<D: Dialect, T: Table> Statement for InsertSelect<D, T> {
673 type Dialect = D;
674 type Table = T;
675 fn render_into(&self, sink: &mut dyn Sink) {
676 sink.text("INSERT INTO ");
677 render_ident::<D>(sink, T::NAME);
678 sink.text(" (");
679 for (i, name) in self.header.iter().enumerate() {
680 if i > 0 {
681 sink.text(", ");
682 }
683 render_ident::<D>(sink, name);
684 }
685 sink.text(") ");
686 self.body.splice_into(sink);
687 }
688}
689
690/// An `INSERT` was given no rows at all. Returned rather than panicked for
691/// the reason `update::NothingToSet` gives: an empty collection is ordinary
692/// request-shaped data, and the caller decides whether it is a no-op or an
693/// error.
694#[derive(Debug, Clone, Copy, PartialEq, Eq)]
695pub struct NothingToInsert;
696
697impl std::fmt::Display for NothingToInsert {
698 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
699 f.write_str("an INSERT must have at least one row, but no rows were given")
700 }
701}
702impl std::error::Error for NothingToInsert {}
703
704fn render_values_clause<D: Dialect, R: InsertRow>(
705 sink: &mut dyn Sink,
706 rows: &[Vec<InsertValue>],
707 on_conflict: &Option<ConflictClause<D, R::Table>>,
708) {
709 sink.text("INSERT INTO ");
710 render_ident::<D>(sink, <R::Table as Table>::NAME);
711
712 // Header and values come from one chain, so a row has exactly one cell
713 // per column named: no reconciliation, nothing to drop.
714 let mut header = Vec::new();
715 <R::Values as InsertValues>::push_names(&mut header);
716
717 // A table whose every column is generated leaves nothing to name, and
718 // an empty column list is a syntax error in two of the three dialects.
719 // One such row is all SQL can express, which is why `values`/`values_all`
720 // take `Insertable`.
721 if header.is_empty() {
722 sink.text(D::INSERT_NO_COLUMNS);
723 if let Some(clause) = on_conflict {
724 render_conflict_clause::<D, _>(clause, sink);
725 }
726 return;
727 }
728
729 sink.text(" (");
730 for (i, name) in header.iter().enumerate() {
731 if i > 0 {
732 sink.text(", ");
733 }
734 render_ident::<D>(sink, name);
735 }
736 sink.text(") VALUES ");
737
738 for (row_i, row) in rows.iter().enumerate() {
739 if row_i > 0 {
740 sink.text(", ");
741 }
742 sink.ch('(');
743 for (i, v) in row.iter().enumerate() {
744 if i > 0 {
745 sink.text(", ");
746 }
747 match v {
748 InsertValue::Default => sink.text("DEFAULT"),
749 InsertValue::Value(v) => sink.bind(v),
750 }
751 }
752 sink.ch(')');
753 }
754
755 if let Some(clause) = on_conflict {
756 render_conflict_clause::<D, _>(clause, sink);
757 }
758}
759
760pub struct Insert<D, R: InsertRow> {
761 rows: Vec<Vec<InsertValue>>,
762 on_conflict: Option<ConflictClause<D, R::Table>>,
763 _marker: PhantomData<fn() -> (D, R)>,
764}
765
766impl<D, R: InsertRow + Insertable> Insert<D, R> {
767 /// Bulk insert: add another row to the same statement.
768 pub fn values(mut self, row: R) -> Self {
769 self.rows.push(collect_values(row));
770 self
771 }
772
773 /// The same for a collection. Infallible, unlike the seed's: this
774 /// statement already has a row, so an empty collection adds nothing
775 /// rather than describing an `INSERT` with nothing in it.
776 pub fn values_all(mut self, rows: impl IntoIterator<Item = R>) -> Self {
777 self.rows.extend(rows.into_iter().map(collect_values));
778 self
779 }
780}
781
782impl<D: Dialect, R: InsertRow> Insert<D, R> {
783 /// `ON CONFLICT (..) DO NOTHING`. Pass [`partial_index`] where the
784 /// index to infer is a partial one.
785 pub fn on_conflict_do_nothing(mut self, target: impl ConflictTarget<R::Table>) -> Self
786 where
787 D: SupportsOnConflict,
788 {
789 self.on_conflict = Some(ConflictClause {
790 target: target.into_target(),
791 action: ConflictAction::DoNothing,
792 });
793 self
794 }
795
796 /// `ON CONFLICT (..) DO UPDATE SET ..`. Takes the [`Assignments`] an
797 /// `UPDATE` sets, or a [`ConflictUpdate`] where an assignment names the
798 /// row the `INSERT` proposed. Pass [`partial_index`] where the index to
799 /// infer is a partial one. A [`ConflictUpdate`] is also where the
800 /// `WHERE` that decides whether the update fires at all lives.
801 pub fn on_conflict_do_update(
802 mut self,
803 target: impl ConflictTarget<R::Table>,
804 set: impl Into<ConflictUpdate<D, R::Table>>,
805 ) -> Self
806 where
807 D: SupportsOnConflict,
808 {
809 self.on_conflict = Some(ConflictClause {
810 target: target.into_target(),
811 action: ConflictAction::DoUpdate(set.into()),
812 });
813 self
814 }
815}
816
817impl<D: Dialect, R: InsertRow> crate::statement::private::Sealed for Insert<D, R> {}
818
819impl<D: Dialect, R: InsertRow> Statement for Insert<D, R> {
820 type Dialect = D;
821 type Table = R::Table;
822 fn render_into(&self, sink: &mut dyn Sink) {
823 render_values_clause::<D, R>(sink, &self.rows, &self.on_conflict);
824 }
825}