Skip to main content

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}