Repository navigation
fix: split temporal periods without FOR PORTION OF, on PostgreSQL 18 - #879
Closed
zachdaniel wants to merge 1 commit into
Closed
zachdaniel wants to merge 1 commit into
zachdaniel wants to merge 1 commit into
Conversation
PostgreSQL reverted UPDATE/DELETE FOR PORTION OF from 19 (a4b26b8f7cd), because concurrent writes under READ COMMITTED could lose updates. Temporal writes now split versions themselves in one statement, using PG18's RETURNING old, and lock the versions they split first: if a concurrent write changed one, the statement writes nothing and reruns. Upserts that race to insert the same record skip on the WITHOUT OVERLAPS primary key and retry that key. After 25 conflicts, AshPostgres.Temporal.WriteConflict. - migrations emit temporal DDL unconditionally; VerifyTemporal requires the repo's min_pg_version/0 to be at least 18 - temporal upsert errors go through handle_raised_error - test suite: temporal resources on AshPostgres.TemporalTestRepo, only migrated on PG18+; test repo port is PG_PORT (CI broke on 5433) - docs: temporal resources topic
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PostgreSQL reverted
UPDATE/DELETE ... FOR PORTION OFfrom 19 before release (a4b26b8f7cd, discussion): concurrent writes under READ COMMITTED could silently lose part of an update. Temporal writes relied on it.Splitting. Each temporal write is one statement that writes the slice it covers and puts back the rest of the version as new rows, using PG18's
RETURNING old. Temporal resources now need PostgreSQL 18, not 19. Once PostgreSQL ships nativeFOR PORTION OF, we'll use it.Concurrency. Each statement locks the versions it's about to split and compares them with what its snapshot matched. If a concurrent write changed one, the statement writes nothing and reruns, inside a transaction so the locks it took are kept. Upserts that race to insert the same record skip on the
WITHOUT OVERLAPSprimary key (ON CONFLICT ON CONSTRAINT <pkey> DO NOTHING) and retry just that key. Identity violations still raise. After 25 conflicts,AshPostgres.Temporal.WriteConflict. No savepoints.Migrations. Temporal DDL is emitted unconditionally instead of behind
server_version_num >= 190000guards with plain-key fallbacks.VerifyTemporalrequires the repo'smin_pg_version/0to be at least 18.Also:
handle_raised_error(identity violations wereAsh.Error.Unknown)PG_PORTnow, default 5432. Plus format fixes.AshPostgres.TemporalTestRepo(min_pg_version 18), only migrated and started on PG18+, so the PG14-17 jobs still compileTests: new
test/temporal_concurrency_test.exsruns real concurrent transactions (split, end, bulk, upsert race, partial bulk-upsert race). All fail without the conflict gate. Locally: PG18 full suite and a PG17 run pass, except 3 unrelated sort tests that also fail on main. Not re-run on PG19 beta since the test-repo restructure.Upgrade note: migrations generated before this created plain keys on PostgreSQL 18. The new docs page explains how to check and fix.