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