Repository navigation
test: native_dict_underfill gets its pytest twin, and a crash can no longer pass its survival arm (#1341) - #1455
Conversation
jdatcmd
left a comment
There was a problem hiding this comment.
Approving ec9d941.
Measured on PG17: native_dict_underfill.sh 4/4, and test_native_dict_underfill.py 4 checks. The tsv at this head is 3691 / 2705 / 986, matching its budget.
The abort mutant, run myself: DECODE_CORRUPT("DICT output length does not match raw length") → abort().
- shell 2/4:
under-filled DICT chunk is rejected with a clean error,got [no SQLSTATE (server closed the connection unexpectedly)] want [XX001]; andbackend survives the under-filled DICT chunk,got [|1 backend crashes]. - pytest: the rejection arm, with the same
no SQLSTATE (…). Its "1 error" is teardown losing the connection to the crashed server.
So neither a crash nor an "out of memory" can pass for the refusal any more.
…es ALTER EXTENSION UPDATE (#1341 item 66) Between installing a new library and running ALTER EXTENSION pgcolumnar UPDATE, a database runs the 1.0-alpha5 library over its 1.0-alpha4 catalog. The library deletes from pgcolumnar.retired_group, which that catalog lacks, so DROP TABLE, TRUNCATE and pgcolumnar.vacuum() on a columnar table fail there with 42P01 'columnar metadata table "pgcolumnar.retired_group" does not exist', which names neither the cause nor the remedy. Measured: each refusal changes nothing, reads and writes work throughout, and after the update all three succeed on the same rows. open_columnar_table's error now carries a hint naming the update. docs/installation.md's "If you skipped step 3" shows the error and the hint. Red first, both twins, PG18: native_upgrade_converge gains the window's arms in a database at the previous release's catalog (the newest fixture), and the three refusal arms fail on main with `got [42P01|no-hint]`. test_native_upgrade_converge.py is their partial twin, declared INCOMPLETE; it stages the previous release's base script from test/fixtures as the shell does. Green on 15-19 in both twins. cluster_tests 660 -> 661 by collection; TESTS.md gets section 143. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… still be set to a row store (#1341) test_fk_referencing.py asserts every shell check by name; compare_to_bash grades it as covering all 28 (27 checks on PG17+, and the pre-17 branch's own), and it joins COMPLETE. The conversion guard's over-rejection control converted a table with no foreign key back to heap, so it could not see a guard that refused every SET ACCESS METHOD on a referenced table whatever the target: with the guard's columnar-target test removed, the suite stayed 26/26. A new arm sets the referenced table itself to heap; under that mutant both twins now fail it. cluster_tests 661 -> 666 by collection; TESTS.md gets section 144. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tations of the foreign-key guards (#1341) 28 rows from five-major runs (27/27 on 17-19, 26/26 on 15-16). Dated on PG18 by: the referenced-side refusal removed (5), the guard keyed on the referencing table (8), the conversion refusal removed (8), and the conversion refused whatever the target (1). suites_not_covered 219 -> 218; the census is 3647 rows, 2686 never, 961 dated, restated on main db56168. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
test_truncate_cleanup.py asserts every shell check by name; compare_to_bash grades it as covering all 25, and it joins COMPLETE. It runs in a private database, since the snapshot counts every pgcolumnar catalog row and the shared one holds every other test's. The shell suite needed no change: each of its arms already goes red under a mutation of the path it names. cluster_tests 666 -> 672 by collection; TESTS.md gets section 145. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mutations of the truncate paths (#1341) 25 rows from five-major runs (25/25 on each of 15-19). Dated on PG18 by a rewrite that keeps the retired storage's rows (7) or its stale write state (1), an in-place truncate that skips the projections' storages (8), and a storage-tree delete that skips them (1). suites_not_covered 218 -> 217; the census is 3672 rows, 2695 never, 977 dated, restated on main db56168. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…zone-map answer that ignores deletes (#1341) test_native_dml.py asserts every shell check by name; compare_to_bash grades it as covering all 15, and it joins COMPLETE. The min/max arm could not fail as its comment claimed. The deletes (id % 7 = 0) removed neither the smallest nor the largest id, so min and max were the same whether or not the deleted rows counted; and measured with groups that hold deletes left on the zone-map path, min/max(id) still came out right while min/max(k) came out wrong (10|50000 for 20|49990). The suite stayed 13/13. The deletes now include ids 1 and 5000, a premise asserts on heap that min and max moved, and the arm takes min/max over k as well as id; under that mutant both twins fail it. The index arms gain a premise that the lookups take the primary-key index, so they test the index fetch's delete check rather than the scan. cluster_tests 672 -> 673 by collection; TESTS.md gets section 146. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ons (#1341) 15 rows from five-major runs (15/15 on each of 15-19). Dated on PG18 by: a row group with deletes still answering min/max from zone maps (1), count(*) from metadata not subtracting deleted rows (3), and the index fetch ignoring the delete vector (5). suites_not_covered 217 -> 216; the census is 3687 rows, 2702 never, 985 dated, restated on main db56168. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…longer pass its survival arm (#1341) test_native_dict_underfill.py asserts every shell check by name; compare_to_bash grades it as covering all 4, and it joins COMPLETE. It turns the post-codec encoding choice off for its own session, where the shell sets it for its database. The survival arm was a fresh SELECT 1, which a crashed backend passes once crash recovery has finished, and the suite computed a crash flag it never checked. It now counts "terminated by signal" in the server log. The rejection arm matched 'does not match|corrupt|invalid|out of' in any message, which "out of memory" satisfies too; it now requires XX001. A premise asserts the inflation rewrote the chunk's descriptor. cluster_tests 673 -> 674 by collection; TESTS.md gets section 147. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4 rows from five-major runs (4/4 on each of 15-19). Dated on PG18 by the DICT fill check removed (1) and replaced by a crash (2, one shared). suites_not_covered 216 -> 215; the census is 3691 rows, 2704 never, 987 dated, restated on main db56168. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ec9d941 to
2548d98
Compare
jdatcmd
left a comment
There was a problem hiding this comment.
Re-approving 2548d98, the restate onto main db56168. I compared every commit's patch with the approved stack using git range-diff. The test and source commits are unchanged, and the ledger-seed commits changed only by re-anchoring on #1470. The census at this head matches its budget paragraph, and the counts step consistently. At #1467's head: the guards pass (438), 687 collected (matching the file), and harness_selftest is 1245/1245.
#1341, the twin-less suites:
native_dict_underfill.shhad no pytest twin. This PR adds one, every check by the shell's name, seeds the suite into the ledger, and tightens the shell's two arms, which accepted more than a clean refusal.Stacked on #1454, at the top of my chain. This branch is #1454's head plus two commits.
What changes
test/pytest/test_native_dict_underfill.py, the twin: one test in a private schema. It turns the post-codec encoding choice (opt: every encoder but FSST decides on pre-codec size, costing 7.17% of stored bytes on real data #1132) off for its own session, where the shell sets it for its database, so the change can't reach other tests.compare_to_bash.pygrades it as covering all 4 names, and it joinsCOMPLETE.SELECT 1, which a crashed backend passes once crash recovery has finished, and the suite computed acrashflag it never checked. It now counts "terminated by signal" in the server log. This is the same fix as test: corruption gets its pytest twin, and a backend crash can no longer pass for a refusal (#1341 item 25) #1446's corruption suite.does not match|corrupt|invalid|out ofin any message. "out of memory" satisfies that too. It now requires XX001, read withVERBOSITY verbose.native_dict_underfillis seeded with 4 rows from five-major runs, and 2 of the 4 rows dated.suites_not_coveredgoes 216 → 215, and the census is 3687 + 4 = 3691 rows, 2703 + 2 = 2705 never and 984 + 2 = 986 dated, matching the tsv. The gate gives rc=0 against origin/main.Red first
Each mutation of the DICT fill check (
columnar_encoding.c:1424) was run on PG18, through both twins, with the.somd5 printed every time.native_dict_underfill.shtest_native_dict_underfill.pyabort()no SQLSTATE (server closed the connection unexpectedly); survival:1 backend crashesBefore this PR, the abort mutant was caught by the survival arm only because
SELECT 1reached the server before recovery finished.Never red (2): the two premises.
Runs
native_dict_underfill.shtest_native_dict_underfill.pyAlso measured: the guard half (438 tests), harness_selftest 1245/1245 and docs_style.
cluster_testsgoes 673 → 674 by collection, and TESTS.md gets §147.🤖 Generated with Claude Code