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
78
79
//! [`try_incoming_row_satisfies_predicate`] — the DO NOTHING path's
//! savepoint-wrapped, narrowly-falling-back variant of
//! [`super::upsert_predicate_probe::incoming_row_satisfies_predicate`]
//! (cratestack#741 finding 2). Split out of `upsert_predicate_probe.rs`
//! purely to stay under this codebase's ~200-LoC-per-file convention,
//! not a behavioral boundary.
use CratestackError;
use crateAcquire;
use crate::;
use incoming_row_satisfies_predicate_inner;
use ProbeOutcome;
/// [`super::upsert_predicate_probe::incoming_row_satisfies_predicate`],
/// but wrapped in its own `SAVEPOINT` so a probe-evaluation failure
/// doesn't poison the rest of `tx`.
///
/// Postgres aborts an entire transaction the instant any statement in
/// it errors: every subsequent statement on that same transaction then
/// fails with `25P02 current transaction is aborted, commands ignored
/// until end of transaction block`, even an unrelated one, until a
/// `ROLLBACK` (or `ROLLBACK TO SAVEPOINT`) runs. `run_upsert_do_nothing_in_tx`
/// needs to keep issuing statements against `tx` after a probe failure
/// (the real `ON CONFLICT ... DO NOTHING RETURNING`, which is
/// authoritative regardless — see that function's doc comment), so the
/// probe has to run inside its own savepoint that gets rolled back on
/// failure, leaving the outer transaction clean. Confirmed live: without
/// this savepoint, the very first upsert against such a schema fails
/// with `25P02` instead of the intended fallback behavior, because the
/// probe's own `42703` had already aborted `tx`.
///
/// Returns `Ok(None)` only for [`ProbeOutcome::UndefinedColumn`]
/// (savepoint rolled back) — callers treat this the same as "unknown,
/// fall back to the authoritative statement". Every other failure —
/// [`ProbeOutcome::Other`], or a failure of the savepoint machinery
/// itself (`BEGIN`/`COMMIT`/`ROLLBACK`, not the probe query) —
/// propagates as `Err` rather than being absorbed: a masked connection
/// loss, statement timeout, or permission error would otherwise
/// resurface later as a different, more confusing failure from a
/// different statement (or, worse, silently succeed if the later
/// statement happens not to need whatever failed). This is narrow BY
/// CONSTRUCTION — matching on [`ProbeOutcome`]'s variant, not
/// inspecting the mapped error's shape — see
/// `upsert_predicate_probe_error`'s module doc comment.
pub async