SQLite UPSERT validation workflow for matching conflict-target predicates to partial unique indexes and determining release readiness.

SQLite Accepted the UPSERT. Did It Match the Intended Partial Index?

Thu, Nov 12, 2026

A successful SQLite INSERT ... ON CONFLICT ... DO UPDATE is not, by itself, evidence that the statement targeted the partial unique index an engineer intended. SQLite defines the text between ON CONFLICT and DO as the conflict target, and its grammar allows a predicate after the indexed columns specifically so a partial uniqueness constraint can be identified. UPSERT acts only on uniqueness constraints: a UNIQUE or PRIMARY KEY declaration, or a unique index. Partial indexes, meanwhile, cover only rows for which their WHERE expression evaluates true.

The operational trap is therefore semantic, not merely syntactic. If a table has several uniqueness rules, especially multiple partial unique indexes over the same key columns, a syntactically valid conflict target can identify a different uniqueness rule from the one the application contract names. The database may return success while the validation question remains unanswered: which predicate-defined uniqueness domain actually governed the operation? SQLite's own internal description calls the optional conflict-target WHERE expression the field used to identify partial unique indexes.

This playbook treats that question as a release-acceptance problem. It uses a disposable database, synthetic rows, a pinned target SQLite release, an independent expected-case manifest, explicit negative controls, state reconciliation, preserved failure evidence, and a four-way ACCEPT / REPAIR / RERUN / HOLD decision. The current official SQLite release verified during research is 3.54.1, released October 16, 2026; SQLite publishes Linux command-line tools for that version as sqlite-tools-linux-x64-3540100.zip.

No behavioral case below is represented as locally executed. The research environment did not provide an executable sqlite3 CLI, and the official binary could not be fetched into that isolated runtime. Consequently every case is marked EXPECTED / NOT EXECUTED. Documentation claims and expected fixture outcomes are deliberately kept separate.

Define the acceptance contract and baseline

The acceptance contract should not be “the SQL returned without error.” That signal is too weak. For this investigation, acceptance means that the conflict target identifies the declared uniqueness domain, the affected row belongs to that domain, the resulting state agrees with an independently written oracle, and the evidence is tied to an exact SQLite build.

SQLite documents four facts that define the technical boundary. First, the conflict target specifies the uniqueness constraint that triggers the UPSERT. Second, only one matching ON CONFLICT clause runs for an input row, and clauses are considered in order. Third, UPSERT processing applies only to uniqueness constraints, including unique indexes. Fourth, a partial index contains only rows for which its WHERE expression is true.

Do not conflate this UPSERT syntax with SQLite's older conflict-resolution mechanism such as INSERT OR IGNORE, OR REPLACE, ROLLBACK, ABORT, or FAIL. SQLite explicitly documents them as two different uses of the phrase “ON CONFLICT.” The older clause selects a resolution algorithm; the UPSERT conflict target selects the uniqueness constraint relevant to the UPSERT arm.

The acceptance artifacts are:

Artifact

Purpose

Acceptance assertion

version.txt

Pins runtime

sqlite3 -version equals approved version

schema.sql

Declares competing partial unique indexes

Stored schema matches reviewed DDL

manifest.tsv

Independent oracle

Expected target and final state predate execution

case-*.sql

One synthetic case each

No case mutates another case's database

stdout.txt / stderr.txt

Raw engine evidence

Preserved verbatim

before.tsv / after.tsv

State evidence

Identity and values reconcile

schema.tsv

Index evidence

Unique/partial flags and predicates captured

integrity.txt

Structural check

PRAGMA integrity_check returns ok

ledger.tsv

Human review

Every case receives status and disposition

SQLite exposes enough metadata to make the schema evidence independent of application assumptions. PRAGMA index_list(table) reports whether each index is unique and whether it is partial, while sqlite_schema.sql records the CREATE INDEX text for programmer-created indexes.

The target baseline for this playbook is SQLite 3.54.1. That release is current as of November 12, 2026 according to SQLite's official release and download pages.

# Required precondition for an executed acceptance run.
# This command has NOT been executed for the report below.
# EXPECTED / NOT EXECUTED

sqlite3 -version | tee evidence/version.txt

test "$(sqlite3 -version | awk '{print $1}')" = "3.54.1"

Measurable pass condition: the first token printed by the candidate sqlite3 binary is exactly 3.54.1, and version.txt is retained with the evidence bundle.

Measurable fail condition: the command is unavailable, reports another version, or the version cannot be attributed to the binary that actually executed the cases.

That last condition matters. “Our dependency manifest says SQLite 3.54.1” is not runtime evidence. Capture the binary's report from the process used for the fixture.

The Machine learning evaluation article focuses on model metrics, baselines, protected test data, thresholding, calibration, and reproducible ML performance claims. Its reusable principle is independent evaluation; its workflow, datasets, metrics, and failure modes are unrelated to SQLite uniqueness arbitration.

Create the isolated fixture and expected-case manifest

The fixture needs two competing partial uniqueness domains over the same key columns. That is the smallest useful design for exposing the difference between “SQLite accepted my UPSERT” and “SQLite selected the uniqueness rule I meant.”

Use a synthetic contact table:

-- schema.sql
-- EXPECTED / NOT EXECUTED
PRAGMA foreign_keys = ON;
CREATE TABLE contact (
    id          INTEGER PRIMARY KEY,
    tenant_id   INTEGER NOT NULL,
    email       TEXT NOT NULL,
    deleted_at  TEXT,
    verified    INTEGER NOT NULL CHECK (verified IN (0,1)),
    payload     TEXT NOT NULL
);
CREATE UNIQUE INDEX ux_contact_live_email
ON contact(tenant_id, email)
WHERE deleted_at IS NULL;
CREATE UNIQUE INDEX ux_contact_verified_email
ON contact(tenant_id, email)
WHERE verified = 1;

Both indexes are legal SQLite partial unique indexes: adding WHERE makes an index partial, and adding UNIQUE requires entries that actually belong to that index to be unique. Rows whose predicate is false or NULL are omitted from that partial index.

The two domains are intentionally different:

Index

Key

Predicate

Business-style interpretation

ux_contact_live_email

(tenant_id,email)

deleted_at IS NULL

One live row per email

ux_contact_verified_email

(tenant_id,email)

verified = 1

One verified row per email

The fixture is disposable:

#!/bin/sh
# run-fixture.sh
# EXPECTED / NOT EXECUTED
set -eu
ROOT="${ROOT:-$(pwd)/sqlite-upsert-partial-fixture}"
DB="$ROOT/fixture.db"
EVIDENCE="$ROOT/evidence"
rm -rf "$ROOT"
mkdir -p "$EVIDENCE"
sqlite3 -version > "$EVIDENCE/version.txt"
sqlite3 "$DB" < schema.sql
sqlite3 -tabs "$DB" "
  SELECT name, \"unique\", origin, partial
  FROM pragma_index_list('contact')
  ORDER BY name;
" > "$EVIDENCE/index-list.tsv"
sqlite3 -tabs "$DB" "
  SELECT name, sql
  FROM sqlite_schema
  WHERE type='index'
    AND tbl_name='contact'
  ORDER BY name;
" > "$EVIDENCE/schema.tsv"
sqlite3 "$DB" "PRAGMA integrity_check;" \
  > "$EVIDENCE/integrity-initial.txt"

sqlite_schema is appropriate here because SQLite documents its sql column as the SQL text that recreates application-defined schema objects, subject to limited normalization.

The expected-case manifest must be written before case output is inspected. It is not generated from the database under test.

# manifest.tsv
# EXPECTED / NOT EXECUTED
case    target_domain        expected_engine_result expected_row_effect decision_if_match
C01     live                 success                update live row      ACCEPT
C02     verified             success                update verified row  HOLD
C03     live                 success                insert tombstone     ACCEPT
C04     no_matching_target   prepare/error          none                 ACCEPT
C05     update_abort         constraint error        statement rollback  ACCEPT
C06     live-negative        no live-row update      insert              ACCEPT

The manifest is an independent test oracle because it declares semantics in domain language (live, verified, no_matching_target) instead of copying whatever SQLite reports. The test runner later translates actual rows and error classes back into those domain assertions.

The fixture should also capture index columns and collations:

-- EXPECTED / NOT EXECUTED

SELECT FROM pragma_index_xinfo('ux_contact_live_email');
SELECT FROM pragma_index_xinfo('ux_contact_verified_email');

SQLite documents PRAGMA index_xinfo as returning the key and auxiliary columns of an index, including sort direction and collating sequence.

The asyncio context capture article studies when asyncio.to_thread() captures contextvars, distinguishing coroutine construction, task scheduling, context capture, and worker execution. Its useful shared discipline is event-boundary isolation. Its subject is Python task/context timing, not database uniqueness.

A proper negative control verifies that the harness can distinguish a row that belongs to the intended live uniqueness domain from one that does not.

-- negative-control.sql
-- EXPECTED / NOT EXECUTED
DELETE FROM contact;
INSERT INTO contact
  (id, tenant_id, email, deleted_at, verified, payload)
VALUES
  (1, 10, '[email protected]', '2026-01-01T00:00:00Z', 0, 'tombstone');
INSERT INTO contact
  (tenant_id, email, deleted_at, verified, payload)
VALUES
  (10, '[email protected]', '2026-02-01T00:00:00Z', 0, 'second tombstone')
ON CONFLICT(tenant_id, email)
WHERE deleted_at IS NULL
DO UPDATE SET payload = excluded.payload;
SELECT id, tenant_id, email, deleted_at, verified, payload
FROM contact
ORDER BY id;

Because neither row satisfies deleted_at IS NULL, neither belongs to ux_contact_live_email; the expected result is two rows, not an update of row 1. That expectation follows from the documented definition of partial-index membership.

Negative-control pass condition: two tombstoned rows exist after the statement, row 1 retains payload='tombstone', and the new row has payload='second tombstone'.

Negative-control fail condition: row 1 is updated, only one row remains, or the case cannot distinguish the intended predicate domain.

Status: EXPECTED / NOT EXECUTED.

Reproduce the misleading success and comparison case

The misleading-success case deliberately targets the verified uniqueness domain while the hypothetical release requirement names the live domain. Nothing here assumes SQLite behaves incorrectly. The point is that a valid statement can be wrong relative to the caller's intended contract.

Seed a row that is verified but deleted:

-- case-C02-wrong-domain.sql
-- EXPECTED / NOT EXECUTED
DELETE FROM contact;
INSERT INTO contact
  (id, tenant_id, email, deleted_at, verified, payload)
VALUES
  (1, 10, '[email protected]',
   '2026-01-01T00:00:00Z', 1, 'before');
INSERT INTO contact
  (tenant_id, email, deleted_at, verified, payload)
VALUES
  (10, '[email protected]',
   '2026-02-01T00:00:00Z', 1, 'after')
ON CONFLICT(tenant_id, email)
WHERE verified = 1
DO UPDATE SET payload = excluded.payload;
SELECT changes();
SELECT id, tenant_id, email, deleted_at, verified, payload
FROM contact
ORDER BY id;

The statement explicitly names (tenant_id,email) WHERE verified = 1. The fixture contains a unique partial index with exactly that declared domain. If the statement succeeds by updating row 1, it demonstrates that the SQL is operational for the verified rule; it does not show that the statement validated ux_contact_live_email. SQLite's UPSERT documentation says the conflict target specifies which uniqueness constraint triggers that arm.

The expected ledger entry is therefore deliberately uncomfortable:

Case

API/CLI signal

Semantic target

Intended release target

Expected disposition

C02

success

verified

live

HOLD

Status: EXPECTED / NOT EXECUTED.

Now run the comparison with the predicate that defines the intended live index:

-- case-C01-live.sql
-- EXPECTED / NOT EXECUTED
DELETE FROM contact;
INSERT INTO contact
  (id, tenant_id, email, deleted_at, verified, payload)
VALUES
  (1, 10, '[email protected]',
   NULL, 0, 'before');
INSERT INTO contact
  (tenant_id, email, deleted_at, verified, payload)
VALUES
  (10, '[email protected]',
   NULL, 0, 'after')
ON CONFLICT(tenant_id, email)
WHERE deleted_at IS NULL
DO UPDATE SET payload = excluded.payload;
SELECT changes();
SELECT id, tenant_id, email, deleted_at, verified, payload
FROM contact
ORDER BY id;

Here the target predicate corresponds to ux_contact_live_email, and both the existing and proposed rows are members of that partial uniqueness domain. A successful update plus the expected final row is evidence for this bounded case.

This distinction matters because query-planner partial-index logic should not be substituted for conflict-target reasoning. SQLite's partial-index documentation discusses when a query predicate implies an index predicate (W⇒X) and explains that the planner uses deliberately limited matching rules rather than a general theorem prover. That documentation concerns query usability, not a promise that arbitrary logically equivalent expressions will identify an UPSERT target.

For release validation, avoid clever logical rewrites of the target predicate. Preserve the reviewed partial-index predicate in the UPSERT unless a separately executed case proves the intended version accepts the alternative.

A comparison invariant is stronger than “both commands return success”:

EXPECTED / NOT EXECUTED

C01:
  target predicate = deleted_at IS NULL
  seeded conflicting row satisfies deleted_at IS NULL
  final state = same row identity, payload changed to "after"

C02:
  target predicate = verified = 1
  seeded conflicting row satisfies verified = 1
  final state = same row identity, payload changed to "after"

Required differential:
  C01 and C02 exercise different predicate-defined uniqueness domains.

Pass: each case's seed satisfies only the domain it is intended to isolate, and final-state evidence agrees with the independent manifest.

Fail: the rows accidentally satisfy both predicates, fixture state leaks between cases, or reviewers infer index identity solely from a zero exit status.

The Kubernetes preStop article treats graceful termination as a lifecycle-budget and evidence problem, including pinned tool versions and preserved state. Its reusable idea is that one successful signal does not prove a different lifecycle boundary.

Exercise failure boundaries and preserve per-case evidence

A validation suite that contains only success paths cannot show that it detects incorrect conflict targets. Failure evidence is part of the acceptance contract.

The first boundary is a target that should not correspond to either declared partial unique index:

-- case-C04-no-match.sql
-- EXPECTED / NOT EXECUTED

INSERT INTO contact
  (tenant_id, email, deleted_at, verified, payload)
VALUES
  (10, '[email protected]', NULL, 0, 'x')
ON CONFLICT(tenant_id, email)
WHERE verified = 0
DO UPDATE SET payload = excluded.payload;

There is no declared unique index on (tenant_id,email) WHERE verified = 0. The expected outcome is failure to resolve the named target rather than a silent fallback to an unrelated uniqueness rule.

Status: EXPECTED / NOT EXECUTED.

The second boundary should test a predicate rewrite rather than assume semantic equivalence is accepted:

-- case-predicate-rewrite.sql
-- EXPECTED / NOT EXECUTED

INSERT INTO contact
  (tenant_id, email, deleted_at, verified, payload)
VALUES
  (10, '[email protected]', NULL, 0, 'x')
ON CONFLICT(tenant_id, email)
WHERE NOT (deleted_at IS NOT NULL)
DO UPDATE SET payload = excluded.payload;

The Boolean expression is logically intended to describe the same rows as deleted_at IS NULL, but this playbook does not claim SQLite 3.54.1 will treat the target as interchangeable without execution evidence. SQLite's internal representation explicitly stores a conflict-target predicate for identifying partial unique indexes, while its public partial-index documentation separately warns that SQLite does not generally perform algebraic theorem proving when reasoning about predicates.

That is exactly the sort of boundary that belongs in a versioned fixture rather than in prose presented as a guarantee.

A third failure boundary tests the DO UPDATE path itself:

-- case-C05-update-abort.sql
-- EXPECTED / NOT EXECUTED
CREATE UNIQUE INDEX ux_payload
ON contact(payload);
DELETE FROM contact;
INSERT INTO contact
  (id, tenant_id, email, deleted_at, verified, payload)
VALUES
  (1, 10, '[email protected]', NULL, 0, 'one'),
  (2, 20, '[email protected]', NULL, 0, 'two');
INSERT INTO contact
  (tenant_id, email, deleted_at, verified, payload)
VALUES
  (10, '[email protected]', NULL, 0, 'two')
ON CONFLICT(tenant_id, email)
WHERE deleted_at IS NULL
DO UPDATE SET payload = excluded.payload;

SQLite explicitly documents that constraint handling inside the DO UPDATE portion is always ABORT: if the update violates another constraint, the entire INSERT statement is rolled back.

The expected final state is therefore row 1 still carrying payload='one' and row 2 carrying payload='two'.

Status: EXPECTED / NOT EXECUTED.

Preserve raw evidence per case instead of piping everything through a summarizer:

#!/bin/sh
# run-case.sh
# EXPECTED / NOT EXECUTED
set -u
CASE="$1"
DB="runs/$CASE/fixture.db"
mkdir -p "runs/$CASE"
cp pristine.db "$DB"
sqlite3 -tabs "$DB" "
  SELECT id, tenant_id, email, deleted_at, verified, payload
  FROM contact ORDER BY id;
" > "runs/$CASE/before.tsv"
set +e
sqlite3 -bail "$DB" < "cases/$CASE.sql" \
  > "runs/$CASE/stdout.txt" \
  2> "runs/$CASE/stderr.txt"
RC=$?
set -e
printf '%s\n' "$RC" > "runs/$CASE/exit-code.txt"
sqlite3 -tabs "$DB" "
  SELECT id, tenant_id, email, deleted_at, verified, payload
  FROM contact ORDER BY id;
" > "runs/$CASE/after.tsv"
sqlite3 "$DB" "PRAGMA integrity_check;" \
  > "runs/$CASE/integrity.txt"

PRAGMA integrity_check verifies low-level database consistency including missing or surplus index entries and uniqueness errors; when no such problems are found it returns the single value ok. It does not prove that the application chose the right conflict-target predicate, so it is a guardrail rather than the oracle.

A per-case evidence ledger should look like this before execution:

Case

Version

Target

Expected result

Expected state

Observed result

Observed state

Status

C01

3.54.1 target

live

success/update

row 1 → after

Not observed

Not observed

EXPECTED / NOT EXECUTED

C02

3.54.1 target

verified

success/update

row 1 → after

Not observed

Not observed

EXPECTED / NOT EXECUTED

C03

3.54.1 target

live

success/insert

two tombstones

Not observed

Not observed

EXPECTED / NOT EXECUTED

C04

3.54.1 target

none

target error

unchanged

Not observed

Not observed

EXPECTED / NOT EXECUTED

C05

3.54.1 target

live + ux_payload

constraint error

statement rolled back

Not observed

Not observed

EXPECTED / NOT EXECUTED

C06

3.54.1 target

negative control

insert

original unchanged

Not observed

Not observed

EXPECTED / NOT EXECUTED

The test passes only when the original stdout, stderr, exit code, pre-state, post-state, schema capture, integrity output, and runtime identity remain available. A human-written “PASS” file without those artifacts is not adequate failure evidence.

Reconcile state, identity, documentation, and observation

A release reviewer should reconcile three things after each UPSERT: row identity, row membership in the relevant partial-index predicate, and the changed values.

Identity matters because DO UPDATE modifies the conflicting row; the result should not be accepted merely because a row with the requested values exists somewhere after the statement. SQLite documents that the DO UPDATE action applies to the single row that experienced the uniqueness conflict.

For the live-domain case:

-- reconciliation-C01.sql
-- EXPECTED / NOT EXECUTED

SELECT
    id,
    tenant_id,
    email,
    deleted_at,
    deleted_at IS NULL AS in_live_domain,
    verified,
    verified = 1 AS in_verified_domain,
    payload
FROM contact
ORDER BY id;

The test oracle requires id=1, in_live_domain=1, and payload='after'. The verified domain should be controlled so the case does not accidentally prove both partial indexes at once.

The same principle appears in optimistic concurrency systems, but it is not the same mechanism. The HTTP If-Match article focuses on strong validators and atomically rejecting stale HTTP resource versions so concurrent edits do not overwrite each other. This SQLite experiment has no ETag, HTTP precondition, or concurrent-editor workflow; its narrower concern is mapping an UPSERT conflict target to a predicate-scoped uniqueness rule.

Documentation and observation must be recorded in separate columns.

Claim

Classification

Evidence

A partial index includes only rows where its predicate is true

DOCUMENTED

SQLite partial-index documentation

UNIQUE partial indexes enforce uniqueness among index entries

DOCUMENTED

SQLite partial-index / CREATE INDEX docs

UPSERT conflict targets identify uniqueness constraints

DOCUMENTED

SQLite UPSERT documentation

Target WHERE is represented internally for identifying partial unique indexes

DOCUMENTED IMPLEMENTATION DETAIL

SQLite source commentary

SQLite 3.54.1 is the current release on Nov. 12, 2026

VERIFIED PUBLIC BASELINE

Official release/download pages

C01 updates row 1 on a particular workstation

OBSERVED

No observation available

Predicate rewrite is rejected on 3.54.1

OBSERVED/TEST REQUIRED

EXPECTED / NOT EXECUTED

SQLite's release history says UPSERT entered SQLite in 3.24.0 in 2018; generalized UPSERT with multiple clauses and a final clause lacking a target arrived in 3.35.0 in 2021. Partial indexes have existed since 3.8.0. Those facts support the fixture's version requirements but do not prove that every historical build should be treated identically.

There is another subtle documentation boundary: if the final ON CONFLICT clause omits its conflict target, SQLite documents that it can catch a uniqueness failure not handled by prior target-specific clauses.

That is useful application syntax, but it is inappropriate as the primary probe in this acceptance test. A catch-all arm destroys evidence about which named partial uniqueness domain the developer intended to validate.

For example:

-- Do not use this as the primary acceptance probe.
-- EXPECTED / NOT EXECUTED

INSERT INTO contact(...)
VALUES(...)
ON CONFLICT DO UPDATE
SET payload = excluded.payload;

A successful catch-all UPSERT may establish that some uniqueness rule fired; it does not, by itself, establish that ux_contact_live_email was the intended one.

A bounded repair therefore changes only the target definition or schema element demonstrated to be inconsistent with the contract. It does not rewrite unrelated conflict handling, replace UPSERT with INSERT OR REPLACE, or drop uniqueness rules merely to turn a failing acceptance test green.

Implement bounded repair and verify rollback and rerun safety

Suppose review finds application SQL using:

ON CONFLICT(tenant_id, email)
WHERE verified = 1
DO UPDATE ...

while the written contract says “one live contact per tenant/email,” defined by deleted_at IS NULL.

The smallest repair is not “make the statement stop erroring.” It is to align conflict-target semantics with the declared live uniqueness rule:

-- bounded repair candidate
-- EXPECTED / NOT EXECUTED

INSERT INTO contact
  (tenant_id, email, deleted_at, verified, payload)
VALUES
  (:tenant_id, :email, :deleted_at, :verified, :payload)
ON CONFLICT(tenant_id, email)
WHERE deleted_at IS NULL
DO UPDATE SET
  payload = excluded.payload,
  verified = excluded.verified;

Before release, compare that SQL with the stored schema:

-- EXPECTED / NOT EXECUTED

SELECT name, sql
FROM sqlite_schema
WHERE type='index'
  AND name='ux_contact_live_email';

The repair boundary is measurable:

PASS: only the target predicate or the explicitly reviewed corresponding index definition changes; all other UPSERT mutation semantics remain unchanged unless separately justified.

FAIL: the repair adds catch-all conflict handling, OR REPLACE, unrelated uniqueness changes, or data cleanup that masks whether the original target was wrong.

SQLite's REPLACE algorithm is particularly unsuitable as an invisible substitute. For uniqueness violations, SQLite documents REPLACE as deleting pre-existing conflicting rows before inserting or updating the new row, which has materially different identity and trigger implications from UPSERT DO UPDATE.

Rollback verification should execute a failing statement inside an explicit transaction and prove both the expected statement rollback and the controlled state of the transaction.

-- rollback-probe.sql
-- EXPECTED / NOT EXECUTED
BEGIN IMMEDIATE;
SELECT 'before', id, payload
FROM contact
ORDER BY id;
-- C05 statement goes here and is expected to fail.
SELECT 'after-failure', id, payload
FROM contact
ORDER BY id;
ROLLBACK;
SELECT 'after-rollback', id, payload
FROM contact
ORDER BY id;

Because SQLite documents the DO UPDATE part as using the ABORT conflict algorithm, a constraint violation inside that update backs out the current INSERT statement.

The rerun contract should make each case start from a pristine seed rather than rely on idempotence accidentally provided by previous output.

# EXPECTED / NOT EXECUTED

rm -f pristine.db
sqlite3 pristine.db < schema.sql
sqlite3 pristine.db < seed.sql

for case in C01 C02 C03 C04 C05 C06
do
  ./run-case.sh "$case"
done

A rerun passes when two independent runs from the same pristine seed produce the same normalized row-state evidence, error class, and decision. Timestamped filenames, SQLite-generated transient identifiers outside the asserted contract, or shell metadata should not be treated as semantic differences.

The CSS transition cancellation article uses a similar evidence discipline for transitionend versus transitioncancel: the final visual style alone is not sufficient proof of the lifecycle event that occurred. Its browser-event workflow remains separate; the shared principle is only that final state and causal mechanism must not be collapsed into one signal.

Operational ownership belongs to whoever can answer four questions with artifacts:

  1. Who approves the target SQLite version?

  2. Who owns the expected-case manifest?

  3. Who investigates a target-resolution contradiction?

  4. Who signs the release decision after state reconciliation?

The ownership gate passes only when all four roles are named in the release record, even if one person holds more than one role. An unexplained failure must not be converted into ACCEPT because the application “worked in manual testing.”

Decide ACCEPT, REPAIR, RERUN, or HOLD

The final decision is not a pass/fail boolean. Different evidence failures require different actions.

Outcome

Required evidence

Decision

Meaning

All target, state, identity, negative-control, rollback and integrity assertions match manifest on approved runtime

Complete

ACCEPT

Evidence supports this bounded release

SQL/schema target is demonstrably inconsistent with declared contract and fix is narrow

Complete enough to identify defect

REPAIR

Change contract implementation, then rerun

Harness failure, incomplete files, wrong seed, transient execution problem, or wrong binary

Invalid/incomplete

RERUN

Result is not interpretable

Contradictory target behavior, unapproved version, unexplained state, missing negative control, or ambiguous uniqueness domain

Insufficient or contradictory

HOLD

Do not approve

For the unexecuted fixture in this report, the release decision is HOLD. The fixture design is reviewable, and the documented contracts are sourced, but no local SQLite 3.54.1 behavioral evidence has been produced. Calling the design ACCEPT would invent an execution result.

The complete pre-execution decision ledger is:

Case

Purpose

Expected outcome

Execution status

Current decision contribution

C01

Correct live target

Live row updated

EXPECTED / NOT EXECUTED

HOLD

C02

Wrong-domain success

Verified row updated, proving wrong semantic domain can still succeed

EXPECTED / NOT EXECUTED

HOLD

C03

Out-of-domain insert

Tombstoned duplicate inserts

EXPECTED / NOT EXECUTED

HOLD

C04

Missing target

Target-resolution failure

EXPECTED / NOT EXECUTED

HOLD

C05

DO UPDATE violation

Statement aborted and rolled back

EXPECTED / NOT EXECUTED

HOLD

C06

Negative control

No accidental live-domain conflict

EXPECTED / NOT EXECUTED

HOLD

Integrity

Structural check

ok

EXPECTED / NOT EXECUTED

HOLD

Version

Runtime pin

3.54.1

EXPECTED / NOT EXECUTED

HOLD

A useful release rule is:

ACCEPT =
  approved_runtime
  AND all_required_cases_executed
  AND manifest_matches_observation
  AND negative_control_passes
  AND state_identity_reconciles
  AND rollback_probe_passes
  AND integrity_check_is_ok
  AND no_unresolved_contradiction

That formula is intentionally stricter than sqlite3_exit_code == 0.

A REPAIR decision is appropriate when evidence has isolated the problem, for example, the application names WHERE verified = 1 while the accepted schema contract names WHERE deleted_at IS NULL.

A RERUN decision is appropriate when the evidence is invalid rather than the software: wrong SQLite binary, contaminated database, missing seed, corrupted output capture, or a case that accidentally satisfies both predicates.

A HOLD decision is appropriate when the contradiction is real but not understood. Examples include version-dependent behavior not represented in the manifest, a target that unexpectedly resolves, or final state that disagrees with both the documented contract and the independent oracle.

The “successful API return” is therefore evidence of execution status, not a release verdict. SQLite's own documentation defines conflict targets and partial-index membership precisely enough to demand a stronger test.

Learning context and limitations

The focus here is the interaction between SQLite UPSERT conflict-target predicates and partial unique indexes, with independent proof that the intended predicate-scoped uniqueness domain, rather than merely some uniqueness failure, governed the statement.

A compact validation workflow is:

sqliteimg

The diagram is explanatory only. Its nodes are not evidence that any fixture case has executed.

The Refonte Learning Database Administrator Essentials program page lists a three-month period, 12 to 14 hours/week, database design and architecture, SQL query optimization, backup and recovery, performance tuning, security, cloud database management, migration, disaster recovery, role-based access control, and monitoring and maintenance. It recommends basic programming knowledge and separately states an admission prerequisite of working toward a bachelor's degree or higher. The page also describes hands-on projects, personalized mentorship, and completion credentials.

The page does not establish that this exact SQLite conflict-target laboratory, SQLite 3.54.1, or SQLite-specific partial-index validation is taught. Engineers seeking structured study of database design, SQL optimization, recovery, security, and administration can review the program page, while treating this SQLite fixture as a separate reproducible exercise.

The limitations are material. No fixture command in this report was executed against SQLite 3.54.1, so every behavioral prediction remains EXPECTED / NOT EXECUTED. The current release number and downloadable artifact were verified from SQLite's official pages, but that verifies availability, not fixture behavior.

The fixture also does not claim to validate every legal indexed expression, collation, generated column, WITHOUT ROWID table, multi-row UPSERT, trigger interaction, virtual table, or historical SQLite release. SQLite explicitly states that UPSERT does not currently work for virtual tables, and its semantics have evolved since the original 3.24.0 implementation.

Finally, neither PRAGMA integrity_check nor a green process exit can answer the central semantic question alone. Integrity checking tests database consistency; successful UPSERT execution tests whether the engine accepted and completed a statement. The release claim requires a third piece: independently reconciled evidence that the conflict target corresponds to the intended partial uniqueness predicate.