expense_metadata: every reader resolves the row a write lands on
getTransactions' provenance LATERAL, merchantForTransaction and the Slack details modal all select on transaction_id = $1 OR matched_transaction_id = $1 with a bare LIMIT 1, so they could read a different row than replaceLineItems writes. Same ORDER BY as the match, the write and the order-detail GET. Defensive, not a live bug: measured 2026-08-21, expense_metadata holds 667 rows, 147 of them pointing-only, and ZERO transactions resolve to more than one row by either link. This changes nothing today. It is here so the readers still agree on the day multiplicity appears, which is the only condition under which any of them was ever wrong.
This commit is contained in:
@@ -119,6 +119,16 @@ export async function merchantForTransaction(
|
||||
const row = await queryRow<{ merchant_normalized: string | null }>(
|
||||
`SELECT merchant_normalized FROM expense_metadata
|
||||
WHERE transaction_id = $1 OR matched_transaction_id = $1
|
||||
-- Ordered the same way as replaceLineItems (line-items.ts) and
|
||||
-- matchTransaction (intake-router.ts), so every reader of this row
|
||||
-- resolves the same one a write lands on. NULLS LAST because DESC is
|
||||
-- NULLS FIRST and the row that merely POINTS at the transaction has a
|
||||
-- NULL transaction_id.
|
||||
-- Measured 2026-08-21: 667 expense_metadata rows, 147 of them
|
||||
-- pointing-only, and ZERO transactions resolving to more than one row by
|
||||
-- either link — so this changes nothing today. It is here so the readers
|
||||
-- still agree on the day multiplicity appears.
|
||||
ORDER BY (transaction_id = $1) DESC NULLS LAST, id
|
||||
LIMIT 1`,
|
||||
[transactionId]
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user