Skip to content

test: partition_rows' primary-key arm reads the key it names (#1339) - #1504

Merged
jdatcmd merged 4 commits into
mainfrom
test/1339-partition-rows-index
Oct 16, 2026
Merged

jdatcmd merged 4 commits into
mainfrom
test/1339-partition-rows-index

Conversation

@OffgridwithJD

Copy link
Copy Markdown
Collaborator

@jdatcmd The fifth #1339 custom-scan audit entry, in both twins. Stacked on #1503 (#1502 → #1503 → this). This PR's own commits are the top two.

The primary-key arm never read the key

"the primary key finds a moved row at its new key, and not at its old one, as on heap" forced the index with enable_seqscan = off alone. With pgcolumnar_index_fetch_tuple finding no row, the old suite reddened four duplicate-key arms, but this arm stayed green: the columnar parent was answered by its partitions' custom scans, not by the primary key.

Fix: IDX now also turns the custom scan off, and a premise asserts the columnar lookup reads the primary key. The premise tests the arm's own query. That query plans as an Index Only Scan, since it reads only id, and on a columnar table that still asks each row whether it is live. So the premise accepts either index node. My first version required "Index Scan using", and it was red at head on all five majors. With the mutation, the arm is now red in both twins, and the twins redden the same 5 by name.

Five-major runs at head: 16/16 for the shell and 16/16 for the twin, on each of 15–19. The guards pass 438/438.

Ledger

Census 4348 / 3029 never / 1319 dated (on #1503's 4347 / 3031 / 1316):

  • one new premise row, never;
  • three duplicate-key arms that entered never are now dated;
  • the primary-key and races arms gain the mutation in their history.

The gate gives rc 0. No tests are added.

Left from the audit: sorted_projection and audit.sh, both without twins.

🤖 Generated with Claude Code

jdatcmd and others added 4 commits October 16, 2026 18:11
…dium projections assert their plans (#1341, #1339)

test_native_fetch_bigcap.py carries all 15 checks by the shell's name in
two tests, measuring buffers as the shell's awk sums them.

Two premises are new, in both twins: the narrow (sum(tag)) and medium
(m1 || m2 || m3) projections are fetched through an index scan. Only the
payload query's plan was asserted. Both plan as Index Scans today, so these
guard against a planner change rather than fix a red. FORCE_INDEX also turns
the custom scan off, which enable_seqscan does not (#1339).

Measured and left alone:
- "the fetched rows are the right rows" compares an unforced read with an
  ORDER BY id LIMIT 10 read, which take different paths, so it reddens when
  the deferred decode corrupts a column (shell and twin). Forcing both sides
  through the index made it agree with itself, so it stays as it was.
- the two #433 ratios do not move when the cache misses every lookup or the
  cap drops every column, because those re-read only the projected columns.
  #433's own regression re-read the group's raw bytes per fetch, and there is
  no single-gate mutation for that here.

COMPLETE gains native_fetch_bigcap. TESTS.md section 173, cluster_tests
742 -> 744.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…by a deferred-decode mutation (#1341)

The suite had no rows. suites_not_covered 193 -> 192; census 4347 rows /
3031 never / 1316 dated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
"the primary key finds a moved row at its new key, and not at its old one,
as on heap" forced the index with enable_seqscan off alone, which leaves the
columnar custom scan on. Measured: with pgcolumnar_index_fetch_tuple finding
no row, the arm stayed green, because the columnar parent was answered by its
partitions' custom scans. IDX now also turns the custom scan off, and a
premise asserts the columnar lookup reads the primary key. It plans as an
Index Only Scan, which on a columnar table still asks each row whether it is
live, so the premise accepts either index node. With the same mutation the
arm is now red, in both twins.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…te-key arms are dated (#1339)

Census 4348 rows / 3029 never / 1319 dated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@jdatcmd jdatcmd left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approve, at 5aed207 (its own commits 2006aff and 5aed207, on #1503).

My own mutant, different from yours: PgColumnarRowIsLive answers live for every MVCC lookup, so a dead version reads as live. Your note that the arm's query is an Index Only Scan, which still asks each row whether it's live, is what makes this the right place. PG17:

  • shell: the primary key finds a moved row at its new key, and not at its old one, as on heap: got [1/1|1/0] want [1/0|1/0]. The moved row is found at its old key too;
  • pytest: the same, got '1/1|1/0'.

Only that arm went red, in both twins. Accepting either index node in the premise is right, since the planner's choice between Index and Index Only Scan is the planner's, not ours.

@jdatcmd

jdatcmd commented Oct 16, 2026

Copy link
Copy Markdown
Collaborator

@OffgridwithJD, merging #1504 now: approved at 5aed207, 15/15 green, CLEAN.

@jdatcmd
jdatcmd merged commit 9b08358 into main Oct 16, 2026
15 checks passed
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.

2 participants