Description
GraphStore::insert_or_supersede_with_metrics() calls insert_new_edge before invalidate_prior_head, which violates the partial unique index uq_graph_edges_active_head when a second edge replaces an existing active head.
Reproduction Steps
- Insert edge A→B with relation R
- Insert a different edge A→B with relation R (should supersede the first)
- Observe: SQLite error 2067 (UNIQUE constraint failed) because new edge is inserted while old head is still
active = true
Expected Behavior
Supersede path should:
invalidate_prior_head (set old head active = false)
insert_new_edge (insert new head with active = true)
Actual Behavior
Order is reversed: insert_new_edge runs first, hitting the unique index while the old head is still active.
Suggested Fix
Swap operation order in insert_or_supersede_with_metrics, or mark the index as DEFERRABLE INITIALLY DEFERRED if the transaction semantics require it.
Environment
- Version: 0.20.1
- Features: full
Notes
Found during unit test development for PR #3631/#3629. The APEX-MEM write path itself is correct — this bug is in the pre-existing store implementation. Does not affect this PR (APEX-MEM path is off by default).
Description
GraphStore::insert_or_supersede_with_metrics()callsinsert_new_edgebeforeinvalidate_prior_head, which violates the partial unique indexuq_graph_edges_active_headwhen a second edge replaces an existing active head.Reproduction Steps
active = trueExpected Behavior
Supersede path should:
invalidate_prior_head(set old headactive = false)insert_new_edge(insert new head withactive = true)Actual Behavior
Order is reversed:
insert_new_edgeruns first, hitting the unique index while the old head is still active.Suggested Fix
Swap operation order in
insert_or_supersede_with_metrics, or mark the index asDEFERRABLE INITIALLY DEFERREDif the transaction semantics require it.Environment
Notes
Found during unit test development for PR #3631/#3629. The APEX-MEM write path itself is correct — this bug is in the pre-existing store implementation. Does not affect this PR (APEX-MEM path is off by default).