cratestack_sql/values/conflict.rs
1/// Conflict target for an upsert. Defaults to the model's primary key
2/// (matching the previous PK-only behavior). `Columns` lets callers
3/// upsert on an arbitrary unique tuple — most commonly a natural key
4/// that's distinct from the PK (e.g. `(owner_id, provider)` on a
5/// per-owner-and-provider settings row, or `(pairing_id, slot)` on a
6/// per-slot envelope).
7///
8/// The named columns MUST correspond to a `UNIQUE` constraint or
9/// `UNIQUE` index on the target table — the database engine enforces
10/// this and will surface a clear error if not. The upsert builder
11/// additionally requires the input to carry a value for every column
12/// in the target tuple, so the conflict probe (`SELECT … FOR UPDATE`)
13/// has something to filter on.
14///
15/// Composite-constraint-by-name (`ON CONFLICT ON CONSTRAINT
16/// my_unique_idx_v2`) is not yet exposed; pass the matching column
17/// tuple via [`Self::Columns`] instead.
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum ConflictTarget {
20 /// The model's `@id` primary key. Default.
21 PrimaryKey,
22 /// A caller-supplied tuple of columns forming a unique key on the
23 /// target table.
24 Columns(&'static [&'static str]),
25}
26
27impl ConflictTarget {
28 /// Sugar for `ConflictTarget::Columns(&[...])`.
29 pub const fn columns(cols: &'static [&'static str]) -> Self {
30 Self::Columns(cols)
31 }
32}
33
34impl Default for ConflictTarget {
35 fn default() -> Self {
36 Self::PrimaryKey
37 }
38}