Repository navigation
warren.set_owner: ownership transfer; re-check ownership after the lock (M10 step 5) - #55
Merged
Merged
Conversation
set_owner(name, owner regrole) gives a graph a new owner, as ALTER MATERIALIZED VIEW ... OWNER TO does. The caller must be a member of the current owner and able to SET ROLE to the new one (member_can_set_role on PG 16+, membership on PG 15). It takes the graph's row lock, opens the source queries as the new owner under the graph's search_path (42501 or 42804 before anything changes), keeps versions, vectors and readers (minus the new owner), and raises create_graph's search_path notice judged for the new owner. A contraction has no sources to open. writable_schemas now takes the owner it judges for, and the node id type check the build made is source::require_node_id_type, shared with set_owner. Added to the 0.5.0 -> 0.6.0 upgrade script, parallel_labels (UNSAFE) and access::guard's CALLS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
GraphDefinition::lock re-read current_version and node_order but not owner, and refresh, compact, promote, drop_version and contract into an existing quotient checked ownership only before taking the lock. A call queued behind a set_owner therefore ran with an ownership its caller no longer had. lock now re-reads owner and readers and checks ownership again for the action it is given. test/sql/set_owner_race.sql, written first, failed with "refresh after the transfer is refused: OK"; it now covers all five functions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
…done) docs/semantics.md's Access section describes ownership transfer, with its example mirrored in test/sql/docs_examples.sql. DESIGN.md §5.7 records the implementation (member_can_set_role on PG 16+, is_member_of_role on PG 15, lock re-checking ownership itself) and marks step 5 done; §7 and §9.3 list set_owner. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
They checked ownership before the lock and never after: under READ
COMMITTED a call queued behind an uncommitted set_owner waited on the row
and EvalPlanQual then applied it to the new owner's graph. They now take
GraphDefinition::lock(action), which re-checks; drop_graph keeps letting a
superuser drop a graph whose owner was dropped, after the lock too.
set_owner_race gains grant, revoke and drop_graph cases, each seen failing
first ("... after the transfer is refused: OK"). Its cases, and
lock_reread_race's, now wait (bounded, 10 s) until the other session is
blocked on this one (pg_blocking_pids), instead of trusting dblink_is_busy
after a sleep, which is also true before the other session reaches the
lock. DESIGN.md §5.7 and §7 list every function that re-checks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
open_sources_as now runs under with_read_only, inside as_role and with_search_path, as refresh reads the sources. search_path_notice checks, from the server log, that set_owner raises the writable-schema NOTICE judged for the new owner (a pg_test cannot read a NOTICE), so the pg_test of the judgement drops its search_path UPDATE, which nothing read. A new pg_test shows the old owner loses read access after a transfer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Rxfe2L3iVjSwSBPdUu1Ke
# Conflicts: # DESIGN.md
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.
This is M10 step 5 (DESIGN.md §5.7, §14 item 43).
warren.set_owner(name text, owner regrole)member_can_set_role; PG 15 has no SET option, so it usesis_member_of_role. A superuser always may.search_path: 42501 if the new owner can't read them, 42804 if the columns no longer fit;owner, andreadersminus the new owner;created_by. Nothing is evicted.parallel_labels, toaccess::guard's CALLS, and topg_warren--0.5.0--0.6.0.sql.A race fix that predates this PR
GraphDefinition::locknow re-readsownerandreadersand re-checks ownership after the row lock. Before, a refresh, compact, promote, drop_version or contract queued behind an ownership change ran as the old owner.test/sql/set_owner_race.sqlfailed before the fix and passes after it.Tests
#[pg_test]s incatalog/owner.rs, written first. They cover transfer, readers, an unreadable source, a column mismatch, a caller who is not a member,WITH SET FALSE, a dropped role, the NOTICE, and a contraction.test/run.pyon the race and docs tests, plus trusted install and the shared cache turned off.schema-drift.sh: no drift.test/upgrade.pyon PG 16: upgrades from 0.1.0 through 0.5.0 to 0.6.0 pass.Orphaned graphs, whose owner role was dropped, are step 6 (§14 item 45).
Generated by Claude Code