Skip to content

fix: keep card updates inside the deck and stop PUT from inserting - #97

Merged
lesnik512 merged 2 commits into
mainfrom
fix/upsert-cards-deck-scope
Oct 17, 2026
Merged

lesnik512 merged 2 commits into
mainfrom
fix/upsert-cards-deck-scope

Conversation

@lesnik512

Copy link
Copy Markdown
Member

PUT /api/decks/{deck_id}/cards/ sent INSERT ... ON CONFLICT (id) DO UPDATE, which had two bugs (advanced-alchemy's upsert_many had the same ones before #95):

  1. A card id from another deck was moved into this deck and overwritten.
  2. An id that did not exist was inserted with the client's id. That skips cards_id_seq, so the next POST /api/decks/{id}/cards/ took the same id from nextval and failed on the primary key (422).

Restricting the conflict update to the same deck would fix only the first one, since an unknown id never conflicts and still gets inserted. So CardsRepository.upsert_cards is now update_cards and sends one statement:

UPDATE cards SET front = updates.front, back = updates.back, hint = updates.hint, updated_at = now()
FROM (VALUES ...) AS updates (id, front, back, hint)
WHERE cards.id = updates.id AND cards.deck_id = :deck_id
RETURNING cards.*

If fewer rows come back than ids were sent, it raises NotFoundError (404). The use case never reaches commit(), so the rows that did match are rolled back. A missing deck also gives 404.

A schemas.CardUpdates validator rejects duplicate ids in one request with a 422. Before this, Postgres raised ON CONFLICT DO UPDATE command cannot affect row a second time and the request failed with an unhandled error.

This changes behavior: PUT no longer creates cards, so clients use POST for new ones.

Tests: the two bug tests failed on main and pass now. New tests cover a mixed request with one unknown id (404, nothing updated) and duplicate ids (rejected with no SQL sent). The existing one-statement test still passes. just test passes at 100% coverage, and ruff and ty are clean. AGENTS.md describes the new statement.

@lesnik512
lesnik512 merged commit feb742a into main Oct 17, 2026
3 checks passed
@lesnik512
lesnik512 deleted the fix/upsert-cards-deck-scope branch October 17, 2026 11:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant