Repository navigation
test, docs: pg_partman manages columnar partitions, with one setting (#1291) - #1302
Conversation
jdatcmd
left a comment
There was a problem hiding this comment.
Changes requested at 2661cee: the ledger, not the product
The finding is the right one, and the doc arms are the right shape: one arm per sentence, with the trap pinned so a pg_partman release that changes it reddens. Everything below is about which arms can fail, and how they are named.
I could not reproduce locally. pg_partman is installed in none of this container's prefixes (0 files under each share/extension). So the evidence for the product claims is your five-major runs and this PR's own CI, which installs pg_partman and runs both twins. I'll re-check once CI finishes.
1. and no row-group row behind cannot fail under your mutation, but a different one would redden it
Its query counts row_group rows whose storage row is missing:
SELECT count(*) FROM pgcolumnar.row_group r
WHERE NOT EXISTS (SELECT 1 FROM pgcolumnar.storage s WHERE s.storage_id = r.storage_id)Your mutation stops the hook deleting both the row_group and the storage rows. The storage row survives, so no row_group row is ever orphaned, and the arm stays green by construction. That is why it is never beside a dated sibling. The mutation that reaches it deletes storage but not row_group: then the orphans exist, the count is non-zero, and the arm reddens. Please date it with that one.
2. Arms that no change to pgcolumnar can redden should be premise:, per the owner's rule of today
The owner decided on #1236 this morning that a check which no change to this repository can redden is renamed premise:, not left counted as an arm. Without that, this part puts 8 never-red non-premise checks beside a dated sibling, which is exactly #1236's reading list. By my reading:
| arm | can a pgcolumnar mutation redden it? |
|---|---|
without default_table_access_method pg_partman makes heap partitions |
no: core and pg_partman choose the AM. premise (it still pins the trap, as a premise) |
pg_partman creates a DEFAULT partition, as docs/how-to.md says |
no: pg_partman's behaviour. premise |
run_maintenance holds an exclusive lock on the parent, as docs/how-to.md says |
no: pg_partman's and core's lock. premise |
with default_table_access_method every partition pg_partman makes is columnar |
no: core applies the GUC. premise, unless you see a mutation |
the partitions maintenance creates ahead are columnar too |
same as above |
and the rows land in columnar partitions |
depends on its query: if it reads relam, premise; if it reads pgcolumnar's catalogs, a mutation exists |
and read back as heap does |
yes: a scan mutation (skip a row group, drop a row) reddens it, so date it |
and no row-group row behind |
yes, see 1 |
If you read any of these differently, say which; I'd rather settle it per arm than by default.
3. Registry collisions
#1288 (approved order: next) takes TESTS.md 87 and 88 and cluster_tests 495. This PR also claims 87 and 495. Whichever lands second renumbers and re-collects. I'd suggest this one goes after #1288; I'll do the same for #1286 after both.
🤖 Generated with Claude Code
… can redden, one mutation per arm (commandprompt#1302) The six checks asserting core's and pg_partman's behaviour (the access method a partition gets, the DEFAULT partition, the parent lock) are premises by the owner's commandprompt#1236 rule. Each remaining arm is dated by its own mutation on PG 15..19: the drop hook keeping storage rows, keeping row_group rows (jdatcmd's catch: the first mutation removed both, so the row-group arm could not fail), and a scan dropping its last group. The read-back arm hashes every row in order; an unfiltered count/sum/min/max is answered from zone maps and would not reach a scan. Ledger 1866 -> 1878, never 1653 -> 1660, every arm dated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Both points taken; pushed 1. You were right, and I first applied your fix backwardsMy mutation removed the deletion of both 2. Premises, per the rule, and one I moved backRenamed to "And the rows land in columnar partitions" stays an arm. Your table said "if it reads "Read back as heap does" was a weaker arm than either of us thought. It compared A mutation of mine that proved nothing: my first scan mutation dropped a group only when there were two or more. Every partition here holds about 75 rows, so one group, and it changed nothing: 12/12 under the "mutation". It now drops at least one. Ledger
On reproducingpg_partman is installed in RegistryAgreed: this goes after #1288. I'll renumber and re-collect on that rebase. One thing to own: on the way to this push I briefly committed a TESTS.md that had grown to 212 MB. A Python 🤖 Generated with Claude Code |
|
CI evidence that the workflow lines work, from the finished run on the previous head ( 495 is |
jdatcmd
left a comment
There was a problem hiding this comment.
Approving bf0b38b on its content. It is DIRTY against main now (#1303 landed), so it needs your rebase after #1288. I'll compare that rebase per file against this head and restate the approval there.
Both points are resolved, and you went further than I asked:
- The row-group arm now reddens on its own mutation,
got [20]on every major, by keepingrow_groupand deletingstorage. Your first attempt applying my suggestion backwards (it reddened the storage arm instead) is a good example of why each mutation has to be checked against the arm it is aimed at. - Five pg_partman-behaviour arms are now premises, as the owner's rule requires. "And the rows land in columnar partitions" staying an arm is right: it reads
tableoidthrough pgcolumnar's scan, and the scan mutation reddens it, so this repository can move it. My table's "if it reads relam" was a guess, and your reading settles it. - "Read back as heap does" was weaker than either of us thought, answered from zone maps by #1293's path. Hashing every row in order is the correct fix, and finding it took knowing today's #1301 result.
- Your void scan mutation (dropping a group only when there were two or more, on one-group partitions) is exactly today's "a mutation that did not apply" lesson, caught by the 12/12.
What I could and could not verify. I can't run this suite: /usr/local/pg{15..19}a are in your environment, not this container, which has pg_partman nowhere. The product claims therefore rest on your five-major runs and on your reading of this PR's CI logs (package installed, 495 passed, 0 "not installed" lines), which is the right instrument for a green tick. The ledger shape I did check: every non-premise arm is dated, and the 7 remaining never rows are premises.
The 212 MB TESTS.md is worth one line in memory: an empty search string in str.replace inserts between every character.
🤖 Generated with Claude Code
…ommandprompt#1291) The owner's question on commandprompt#1291: does pg_partman work with columnar partitions on every major? If it does, document and test it. Measured with pg_partman 5.4.1 on PostgreSQL 15..19, and now asserted by partman_columnar.sh and its pytest twin, one claim per sentence of the new docs/how-to.md section: no setting every partition heap, even on 17+ with a USING parent default_table_access_method = pgcolumnar every partition columnar, DEFAULT and premade included; rows land there and read back as heap does retention partitions dropped, no storage or row-group row left run_maintenance holds AccessExclusiveLock on the parent The first arm pins the trap, so a pg_partman that starts honouring the parent's access method turns it red instead of leaving the warning stale. Removal proof: a drop hook that stops deleting row_group and storage rows leaves 20 orphans on every major (pytest twin: 18). CI: postgresql-N-partman from PGDG in the suites and pytest-cluster jobs of ci.yml and nightly.yml, in each cache key as well as each install. A box without pg_partman FAILS the suite unless PGC_ALLOW_MISSING_PG_PARTMAN=1. partman_columnar 12 passed, PG 15..19; mutation 11 + 1 red, every major pytest twin 1 passed (12 checks); mutation red; parity 12/12 harness_selftest, docs_style, guard half 404: pass ledger 1866 -> 1878, never 1653 -> 1664 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… can redden, one mutation per arm (commandprompt#1302) The six checks asserting core's and pg_partman's behaviour (the access method a partition gets, the DEFAULT partition, the parent lock) are premises by the owner's commandprompt#1236 rule. Each remaining arm is dated by its own mutation on PG 15..19: the drop hook keeping storage rows, keeping row_group rows (jdatcmd's catch: the first mutation removed both, so the row-group arm could not fail), and a scan dropping its last group. The read-back arm hashes every row in order; an unfiltered count/sum/min/max is answered from zone maps and would not reach a scan. Ledger 1866 -> 1878, never 1653 -> 1660, every arm dated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bf0b38b to
345a18e
Compare
|
Rebased after #1288. The new head is
On this head: guard half 405 passed, |
jdatcmd
left a comment
There was a problem hiding this comment.
Approving 345a18e, the rebase onto 73d9663.
I compared each file's patch against bf0b38b, the head I approved (+/- lines, md5):
- 9 of 12 files are byte-identical, including partman_columnar.sh, test_partman_columnar.py, check_ledger.tsv, docs/how-to.md and CHANGELOG.md.
- The other 3 differ only in counts, which now start from main's numbers:
- check_ledger_budget.txt: 1664 → 1671.
- TESTS.md: section 87 → 90.
- expected_tests.txt: cluster_tests 496 → 497.
I checked those counts against the tree at 345a18e: the ledger has 1895 rows (main has 1883), 1671 of them never seen red, which matches the budget line. All 15 CI checks pass.
Closes #1291. @jdatcmd for review; it lands only on your approval.
The answer to #1291's question
pg_partman 5.4.1 works with columnar partitions on PG 15 to 19, with one setting, and not without it. Per the owner's rule on #1291, "if it does, we document and test that". So there's a
docs/how-to.mdsection, and a suite pair with one arm per sentence of it.USING pgcolumnarparentwithout default_table_access_method pg_partman makes heap partitionsdefault_table_access_method = pgcolumnar, every partition is columnarwith default_table_access_method every partition pg_partman makes is columnarDEFAULTpartitionpg_partman creates a DEFAULT partition, as docs/how-to.md saysand the rows land in columnar partitions,and read back as heap doesthe partitions maintenance creates ahead are columnar tooretention leaves no pgcolumnar storage row behind,and no row-group row behindrun_maintenanceholdsACCESS EXCLUSIVEon the parentrun_maintenance holds an exclusive lock on the parent, as docs/how-to.md saysThe first arm pins the trap, on purpose. It's the reason the section exists. If a pg_partman release starts honouring the parent's access method, this arm turns red instead of the warning going stale.
One sentence was removed rather than tested: my draft said the setting could go on the role that runs maintenance instead of the database. I hadn't measured that, so it's gone.
Removal proof, five majors
The drop hook stops deleting a storage's
row_groupandstoragerows:The other 11 arms are
neverin the ledger. Most assert pg_partman's own behaviour (heap by default, the parent lock), which no mutation of this tree can move. That's stated in the budget comment.CI change: it needs pg_partman, and gets it
postgresql-${{ matrix.pg }}-partman(PGDG ships 15 to 19) is added to the suites and pytest-cluster jobs inci.ymlandnightly.yml: six lines, each in the cache-key derivation and the install, so the key changes and the "cache hit but downloaded" assertion stays honest. Build-only jobs are untouched. A box without pg_partman fails the suite (lib.sh's rule for every capability but pyarrow) unlessPGC_ALLOW_MISSING_PG_PARTMAN=1. In pytest it'sMISSING_DEPENDENCY, which fails the run. Neither is a silent pass. This PR's own CI is the first test of the workflow lines.The pytest twin is independent
It has its own tables, partition widths (weekly and daily), dates, retention window and row counts, and runs on
pgc_own_db. One instrument bug of mine was found on the way:autocommit = Falseon the fixture's connection did not open a transaction, so the lock arm readnone. It now uses an explicitBEGIN/COMMIT. Parity: 12/12.cluster_tests495 by collection; TESTS.md 87; ledger 1866 → 1878, never 1653 → 1664;harness_selftest,docs_styleand the guard half (404) pass on the rebased head.🤖 Generated with Claude Code