1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
//! Return type for `.upsert(..).do_nothing()` (cratestack#487).
//!
//! A genuine `ON CONFLICT ... DO NOTHING` returns nothing at all for
//! the conflicting row — Postgres only RETURNs rows a statement
//! actually touched, and DO NOTHING touches none. Callers therefore
//! need "inserted" and "already existed" to be distinguishable in the
//! type, not collapsed into a single `M` the way the DO UPDATE path's
//! `.upsert(..).run(..)` returns it.
/// Outcome of a `.upsert(..).do_nothing().run(..)` call.
///
/// # Race semantics
///
/// The runtime always resolves the conflict under a `SELECT ... FOR
/// UPDATE` row lock held for the lifetime of the surrounding
/// transaction (see `upsert_do_nothing_exec::run_upsert_do_nothing_in_tx`
/// for the exact sequencing):
///
/// * If the probe finds an existing row, that row is locked before this
/// call returns — no concurrent transaction can delete or modify it
/// until the caller commits — so [`Existing`](Self::Existing) is a
/// guarantee about the row's state *at the moment this call
/// returns*, not merely "at some point during the call".
/// * If the probe finds nothing, the actual `INSERT ... ON CONFLICT
/// DO NOTHING` is still the statement that runs (not a plain
/// `INSERT`), because the probe's "no row" answer does not itself
/// lock anything — a concurrent transaction can commit a conflicting
/// row in the gap between the probe and the INSERT. When that race
/// is lost, the runtime performs one more locked read to hand back
/// the row the other transaction actually committed, so callers never
/// see a phantom "existing" row invented from stale data — see
/// [`Existing`](Self::Existing) below for what happens if *that* row
/// is deleted before the fallback read completes.