Repository navigation
test: native_truncate gains its pytest twin, and its GUC-off arm stops passing on a refusal (#1341) - #1513
Conversation
jdatcmd
left a comment
There was a problem hiding this comment.
Approve, at b3ec495.
My own mutant, in the dangerous direction: truncate cuts one block into live data (truncBlock -= 1 after it's computed from liveEnd, in columnar_vacuum.c). PG17:
- shell, 10 of 18 red: every parity arm (
QUERY_ERROR),row count after truncate: got [30000] want [15000],indexed lookup after truncate,truncate returned blocks,file shrank, …; - pytest: red by name first (
truncate before any delete is a no-op: got 'error: None'), then the backend is gone (connection failed). The server seems to fall over reading the cut-off blocks.
A truncate that loses data can't pass this suite.
The GUC-off arm: your finding (two statements in one -c run as an implicit transaction block, so truncate refused and the arm compared an untouched file) is the same class as my pipefail one on #1483: a harness behaviour reading as a pass. Splitting the -c plus checking size|answer is right.
Merge order with #1511: whichever is green first. You've said you'll restate the other.
|
@jdatcmd rebased onto d3b237e (#1511 and #1512 in), now
Gate rc 0 against origin/main with the five head logs; guards 439 passed. No suite or twin change. 🤖 Generated with Claude Code |
b3ec495 to
f4e30fb
Compare
jdatcmd
left a comment
There was a problem hiding this comment.
Re-approving at f4e30fba, the restate of b3ec495e (which I approved) onto main d3b237ec.
- Unchanged. Six of eight files have byte-identical patches to the approved head (per-file md5 of every
^[-+]line):check_ledger.tsv,native_truncate.sh,TESTS.md,test_compare_to_bash.py,test_native_truncate.py,unported_suites.txt. - Restated bookkeeping, checked against the files:
check_ledger.tsvcounts 4414 rows: 3066 never and 1348 dated. That equals the budget's 4396 + 18, 3055 + 11 and 1341 + 7.suites_not_coveredgoes from 190 to 189.expected_tests.txtholds exactly onecluster_testsline (753), and collection on this tree is 753.
- Harness files on this tree:
test_harness_deps.py,test_mutation_ledger.pyandtest_compare_to_bash.py: 105 passed. The one failure,test_a_cluster_test_still_needs_the_driver, fails identically on a clean checkout of main in my container, so it isn't this PR.
I'll merge once its CI is green.
|
@OffgridwithJD, two things on
|
f4e30fb to
0e9d204
Compare
…the index (#1341) The shell's "indexed lookup after gap" counted with the defaults, which plan a columnar scan for count(*) over the range, so it never had to read the index built over the gapped layout. It is now forced through n_id with the custom scan off and count(v), and a premise asserts the plan, as native_truncate's lookup is. The old lookup still went red under an index fetch that finds no row (bitmap path), so this is a guard, not a fix. The twin covers all 9 checks by the shell's name, in two tests, and the file-growth arm is an at_least on the measured growth rather than yes/no. Four runs (none, gap fill removed as before 6a16582, the test hook advancing nothing, index fetch finding no row) redden the same names in both: 0, 6, 1 and 1. Ledger: native_gap seeded, 4415 -> 4424 rows, never 3066 -> 3069, dated 1349 -> 1355, suites_not_covered 189 -> 188. cluster_tests 754 -> 756, TESTS.md §177, and the stem leaves unported_suites.txt. Stacked on #1513. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@jdatcmd restated the stack onto 4490755 (#1514–#1516 in). Only the counts moved:
At each tip:
#1518's loop-reader list keeps #1514's 🤖 Generated with Claude Code |
jdatcmd
left a comment
There was a problem hiding this comment.
Re-approving at 0e9d2047 (restated onto 44907550).
- Unchanged. Six files have byte-identical patches to
f4e30fba(per-file md5 of every^[-+]line). - Changed: only
check_ledger_budget.txtandexpected_tests.txt. - Checked on this tree:
- the tsv counts 4415 rows, 3066 never and 1349 dated. That equals main's 4397, 3055 and 1342, plus 18, 11 and 7;
suites_not_coveredis 189;- there is one
cluster_testsline (754), and collection is 754; test_harness_deps.py,test_compare_to_bash.pyandtest_mutation_ledger.py: 105 passed.
I'll merge it once CI is green. If native_backend_crash crashB reddens again, I'll treat it as the flake described above, rerun that job, and not merge on a red.
…s passing on a refusal (#1341) The shell's GUC-off arm sent "SET pgcolumnar.enable_end_truncation = off; SELECT pgcolumnar.truncate('n')" as one -c string. That is an implicit transaction block, which truncate refuses, so at head the call failed with "cannot run inside a transaction block" and the arm passed on an unchanged file. With the GUC not consulted at all, the suite as on main passes 17/17. The call is now its own statement in the same session, and the arm checks its answer as well as the size. Under the same mutant it goes red, with the GUC-on reclaim after it. The indexed lookup is forced to fetch every row through n_id (custom scan, seqscan and bitmap scans off, count(v)), and a premise asserts the plan. By default it is an Index Only Scan, which still fetches each row while the visibility map is unset (so the old lookup was red under an index fetch that finds no row) but answers from the index alone once a VACUUM marks the pages. A guard, not a fix. The twin covers all 18 checks by the shell's name, in three tests. Five mutants (none, txn refusal removed, GUC ignored, truncate returning 0, index fetch finding no row) redden the same names in both. Ledger: native_truncate seeded, 4397 -> 4415 rows, never 3055 -> 3066, dated 1342 -> 1349, suites_not_covered 190 -> 189. cluster_tests 751 -> 754, TESTS.md §176, and the stem leaves unported_suites.txt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
0e9d204 to
cde85e4
Compare
…the index (#1341) The shell's "indexed lookup after gap" counted with the defaults, which plan an Index Only Scan. That fetches each row only while the visibility map is unset (so the old suite was already red under an index fetch that finds no row) and answers from the index alone once a VACUUM marks the pages. It is now forced to fetch every row through n_id (custom scan, seqscan and bitmap scans off, count(v)), and a premise asserts the plan, as native_truncate's lookup is. A guard, not a fix. The twin covers all 9 checks by the shell's name, in two tests over a fixture that builds the gapped layout, so each stands alone, and the file-growth arm is an at_least on the measured growth rather than yes/no. Four runs (none, gap fill removed as before 6a16582, the test hook advancing nothing, index fetch finding no row) redden the same names in both: 0, 6, 1 and 1. Ledger: native_gap seeded, 4415 -> 4424 rows, never 3066 -> 3069, dated 1349 -> 1355, suites_not_covered 189 -> 188. cluster_tests 754 -> 756, TESTS.md §177, and the stem leaves unported_suites.txt. Stacked on #1513. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@jdatcmd heads-up: I changed this PR after your approval, now at cde85e4. The lookup comment (shell, twin, commit message) said the default plan was a columnar scan. It is an Index Only Scan: 🤖 Generated with Claude Code |
jdatcmd
left a comment
There was a problem hiding this comment.
Re-approving at cde85e4e.
- The diff from
0e9d2047touches two files: the lookup comment innative_truncate.shandtest_native_truncate.py, and the twin's premise string, now"Index Scan using n_id". No check name or count moves. - The new comment, measured. With an EXPLAIN before the lookup in this PR's shell, the default
count(*)plansIndex Only Scan using n_id on non both PG17 and PG18. The shell is 18/18 on both.
|
@OffgridwithJD merging #1513 now at |
@jdatcmd This adds the twin for
native_truncate, and fixes a shell arm that was passing on an error.The GUC-off arm passed on a refusal
psql_run "SET pgcolumnar.enable_end_truncation = off; SELECT pgcolumnar.truncate('n');"sends both statements as one-cstring. That runs as an implicit transaction block, andIsTransactionBlock()is true there, so truncate refuses. At head the suite log shows the call failing withpgcolumnar.truncate() cannot run inside a transaction block. The arm then compares the size of a file nothing touched, and passes.pgcolumnar_enable_end_truncation &&removed (the GUC not consulted)GUC off: truncate does nothing,GUC on: truncate reclaimsThe call is now its own
-cin the same session. The arm checkssize|answeragainstsize_before|0, so a refusal can't pass it again. The twin always sent the two statements separately, and it went red on the first run, which is how this surfaced.The indexed lookup
It's forced through
n_idwith the custom scan off, usescount(v)so the plan fetches rows, and has a premise naming the index. The old lookup already read the index: it's red under "index fetch finds no row". So this is a guard against a planner change, not a fix.The twin
It covers all 18 checks by the shell's name, in three tests. Under each mutant on PG18, the shell and the twin redden the same set:
truncate refused inside a transaction blocktruncate returned blocks,file shrank,GUC on: truncate reclaims,GUC on: file shrankindexed lookup after truncatefile unchanged after refused in-txn truncatestays green even with the refusal removed, so it arrives never.Ledger
native_truncateseeded with 18 rows: 4397 → 4415, never 3055 → 3066, dated 1342 → 1349 (restated over #1516), suites_not_covered 190 → 189. It's 18/18 on each of 15–19. The gate returns rc 0 and orphan-scan finds 0.cluster_testsgoes 751 → 754 (over #1514), TESTS.md gets §176, and the stem leavesunported_suites.txt(#1509). The grader passes the pair, and the NO_CLUSTER guards pass 440/440.🤖 Generated with Claude Code