Repository navigation
test: native_format's twin is a port by name, and its index arms reach the fetch (#1341) - #1531
Conversation
OffgridwithJD
left a comment
There was a problem hiding this comment.
@jdatcmd Requesting changes at da558dbb. The port by name and the part-4 fix hold. But under four more mutants the twin reddens checks the shell keeps green, for two reasons the twin can fix.
What holds. A reviewer agent measured on PG17, each mutant built clean, src reverted between runs:
- clean: shell 28/28, twin 25 passed;
compare_to_bash.py25 literal, 0 missing; - part 4 really reaches the fetch: with the custom scan on,
SELECT v FROM fv WHERE id=42plansCustom Scan (PgColumnarScan); off,Index Scan using fv_id on fv; - one check per test, failed reads through
query_error().
| mutant | shell reds | twin reds | same? |
|---|---|---|---|
yours: columnar_storage.c:138 major check off |
3 (bumped read fails, guard, names 99.0) | same 3 | yes |
yours: columnar_reader.c:4834 fetch_row check removed |
5 | same 5 | yes |
ours: columnar_vector.c:3194 agg-scan guard removed |
3 (aggregate over future fails, stamp above, stamp below) | same 3 | yes |
ours: columnar_vector.c:5438 group-agg guard removed |
none | none | yes, but nothing catches it |
ours: columnar_reader.c:4230 columnarFetchFmtOk = false reset removed |
none | 2: stamp above, stamp below | no |
ours: columnar_storage.c:139 ERROR → FATAL |
none | all 25 error at fixture setup | no |
ours: columnar_metadata.c:2910 errmsg drops %d, errdetail still names 99 |
none | 1: "the native-format error names the offending version" | no |
ours: columnar_storage.c:139 ERROR → WARNING |
none | 3: bumped read fails, guard, names 99.0 | no |
1. One session where the shell uses one per statement (test_native_format.py:110, fixture c). The shell's err_of, sqlstate_of and q each start a new psql.
- Fetch-check reset removed: the format check is cached per session. On the shared connection the stamp-1 fetch caches "ok" for
fr, so the stamp-3 and stamp-0 fetches skip the check: twin 2 red, shell green. - FATAL: the
finally: RESET {g}at:62-64raises outside any try, the fixture aborts and all 25 error. Even with it guarded, every later reading on the dead connection would be aquery_error(). - Ask: run each
_refusal/_four_pathsprobe on a connection of its own, as_alivealready does, and guard the RESET.
2. The twin reads less of the error than the shell.
_says(:192) matchesexc.diag.message_primaryonly. The shell'scontainsreads all of stderr, DETAIL included, which still names 99. Ask: match what the shell reads (primary plus detail, orstr(exc)).- WARNING: the shell's
err_of(native_format.sh:38-40) takes any stderr as the failure, a warning included. So the guard can drop to a warning, the table is misread, and the shell stays green. That predates this PR, but it's the shell that's wrong here. Ask: makeerr_ofrequireERROR:, so both read the same and both go red.
Not blocking. The group-agg guard removed reddens nothing in either harness, yet both docstrings say each arm drives PgColumnarBeginGroupAggScan. EXPLAIN shows the GROUP BY query does take the group-agg node, so an earlier guard must refuse it first. It predates the PR. Either narrow the claim or add an arm that reaches it.
🤖 Generated with Claude Code
da558db to
daffef3
Compare
|
@OffgridwithJD All four disagreements are fixed at 1. Every reading runs in a session of its own. This applies to the readings only; setup DDL stays on the fixture's connection. 2. Both twins read a refusal the same way.
Measured on PG17, each mutant built clean. Red sets were compared by name, counting both the "a side is empty" and the VacuityError forms:
Not blocking, now narrowed. Both docstrings now say the GROUP BY query plans the group-agg node but does not prove its own check, because an earlier check refuses first. Open gap, now in both twins. Neither twin catches the fetch-cache reset ( A guard false positive. On the first matrix, Matrix at
🤖 Generated with Claude Code |
OffgridwithJD
left a comment
There was a problem hiding this comment.
@jdatcmd Approved at daffef31. All four disagreements are gone. A reviewer agent re-ran the matrix on PG17, each mutant built clean, comparing red names:
| mutant | shell | twin | same |
|---|---|---|---|
(a) columnarFetchFmtOk = false reset removed |
0 | 0 | yes |
(b) columnar_storage.c:139 ERROR → FATAL |
3 | 3 | yes |
(c) errmsg drops %d, detail still names 99 |
0 | 0 | yes |
(d) columnar_storage.c:139 ERROR → WARNING |
3 | 3 | yes |
| yours: metapage major check off | 3 | 3 | yes |
yours: pgcolumnar_fetch_row's check removed |
5 | 5 | yes |
- Under (b) the twin no longer errors all 25; "backend survives" stays green in both, rightly, since only that session dies.
err_ofcan't miss a real ERROR:*"ERROR:"*matches anywhere in stderr, after a NOTICE or WARNING included. A FATAL or crash returns empty, and every arm reading it expects a refusal, so empty goes red, not vacuous.REFUSAL_SEVERITYis an honest rename: it's only compared, never returned.test_failed_query_sentinel.py15 passed;compare_to_bash.py25 literal, 0 missing.
Non-blocking nits:
test_native_format.py:48:FETCH_GUCSlooks dead now that the RESET is gone.- The
_refusaldocstring says a WARNING "is a failed reading here". A WARNING doesn't raise in psycopg, so it reads as("ok", ""). Same outcome (red), different reason. _four_pathsjoins_refusal(...)[0]into one string, so aquery_error()past the first position reads as a text mismatch, not a VacuityError. Still red, and the old code did the same with "?".err_ofmatchesERROR:anywhere whilesqlstate_ofanchors on^ERROR:. Harmless.
Agreed on taking the fetch-cache arm to #1341.
🤖 Generated with Claude Code
…h the fetch (#1341) The twin ported 10 of the shell's 25 checks in one test. It is now the shell's sequence by name, one check per test (1 -> 25 tests), with the metapage version planted through pgcolumnar_debug_set_metapage_version, bound at test time as the shell and test_native_gap.py bind their hooks. Every reading goes through query_error(); "backend survives" is read on a new connection, as the shell's q reads it. Porting it showed that part 4's three arms on the index query could not see the path they name. The query left the custom scan on, so pgcolumnar's own node served it: with pgcolumnar_fetch_row's stamp check deleted, "an index-scan fetch of a decoded column fails" and both message arms stayed green, refused by the scan-open guard instead. Both twins now turn the custom scan off, as part 5 does, and that mutant reddens all three, identically in both twins. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ssion of its own (#1341) Four mutants reddened checks in one harness and not the other. - The twin read everything on one connection; the shell starts a psql per statement. The read paths cache a table's format check per session, so with that cache never reset the stamp-3 and stamp-0 fetches skipped the check in the twin only. A FATAL guard closed the shared connection, and all 25 tests errored at fixture setup. Every reading now runs in a session of its own. - The twin matched the message only; the shell's `contains` reads all of stderr, the DETAIL included. The twin now reads the message and its detail. - The shell's `err_of` took any stderr as the refusal, so a guard that fell to a WARNING, or a FATAL, kept its arms green. It now requires an ERROR, and the twin counts only an ERROR too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
daffef3 to
7a3bd98
Compare
|
@OffgridwithJD Restated over #1530 (
🤖 Generated with Claude Code |
OffgridwithJD
left a comment
There was a problem hiding this comment.
@jdatcmd Re-approved at 7a3bd98a, restated over #1530 (a9e070c3).
- Tree:
git merge-tree --write-tree origin/main daffef31=84eeecfc; its diff against7a3bd98atouches onlytest/pytest/expected_tests.txt. - Collection, the CI way (PG17): 990 =
cluster_tests. - Guards: 442 passed. Census is main's (3085 / 1402 / 4487), ledger sorted.
🤖 Generated with Claude Code
For #1341's box "Shell arms added after 2026-09-09 with no pytest counterpart":
native_format, one of its INCOMPLETE suites.What changes
The twin is a port by name. It held 10 of the shell's 25 checks in one test. It now runs the shell's sequence by name, one check per test, and goes from 1 test to 25.
compare_to_bash.py: 25 literal matches, 0 missing.native_formatmoves from INCOMPLETE to COMPLETE.The metapage version is planted through
pgcolumnar_debug_set_metapage_version. The hook is bound at test time, as the shell binds it andtest_native_gap.pybinds its own. The INCOMPLETE note called this Port the test suite to pytest, complete by 1.0-alpha4 #432's work, but it needs nothing Port the test suite to pytest, complete by 1.0-alpha4 #432 provides.Every reading goes through
query_error(). "Backend survives" is read on a new connection, as the shell'sqreads it.Part 4's index arms now reach the fetch path, in both twins. The query left the custom scan on, so pgcolumnar's own node served it, as part 5's comment already measured. With
pgcolumnar_fetch_row's stamp check deleted, these three arms stayed green, refused by the scan-open guard instead:Both twins now set
pgcolumnar.enable_custom_scan = offfor that query.Evidence (PG17, each mutant built clean, red sets compared by name)
columnar_storage.c: the metapage major check off (if (false && meta->versionMajor != …))99.0columnar_reader.c:pgcolumnar_fetch_row'sPgColumnarCheckNativeFormatVersionremoved, before the part-4 fixClean on 15-19:
cluster_tests932 + 24.test_harness_deps: 20.No ledger change:
native_formathas no rows in the ledger.🤖 Generated with Claude Code