Skip to content

test: expire refuses a non-owner, a non-time retention column and a dropped one, with rows it could drop (#1341) - #1358

Merged
jdatcmd merged 3 commits into
commandprompt:mainfrom
OffgridwithJD:test/1341-expire-refusals
Oct 14, 2026
Merged

jdatcmd merged 3 commits into
commandprompt:mainfrom
OffgridwithJD:test/1341-expire-refusals

Conversation

@OffgridwithJD

Copy link
Copy Markdown
Collaborator

Part of #1341: the High expire items. They are a non-owner refused, and a retention column that is not a time type (42804) or no longer exists (42703). Arms are in both twins, plus a new pytest function, test_expire_refuses_what_it_cannot_honour.

The fixture makes a missing refusal destructive

Every refused table holds 3,000 rows, ten days old, in three row groups, under a one-day retention. Each arm asserts the SQLSTATE and the row count, so "refused" means nothing was dropped.

The owner's control runs on its own identical table (ttl_ctl). On the first draft it shared ttl_own: under the no-owner mutant the non-owner had already dropped the rows, so the control reddened as collateral. pgc_ledger merge refused to record that, rightly.

Arms and mutations

PG17, both twins, main 8af86e8 against this branch:

arm mutation of pgcolumnar_expire main this branch
a role that does not own the table cannot expire it, even holding DELETE (42501) PgColumnarRequireTableOwnerByOid removed sh 67/67, py 9 passed "got [|0] want [42501|3000]": the non-owner retired every group
expire refuses a retention column that no longer exists (42703) the 42703 branch returns 0 instead green "got [|3000] want [42703|3000]"
expire refuses a retention column that is not a time type (42804) the 42804 branch returns 0 instead green "got [|3000] want [42804|3000]"

The fourth row is a real gap made visible: without the owner check, a role that holds only DELETE could drop whole row groups of a table it doesn't own.

There are four never rows:

  • a premise on the fixture's layout;
  • a premise that the declaration still names the dropped column;
  • set_options accepting an int column, which is what makes the refusal expire's job;
  • the owner's control.

Not done here: the half-declaration item. Removing PgColumnarReadTtl's both-halves test dereferences a NULL interval, so the only mutant crashes the backend. I'd rather design a non-crashing proof than date an arm with a segfault.

Evidence

🤖 Generated with Claude Code

@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.

Approving the content at d2d1fe7. On PG17 I reproduced the owner claim with PgColumnarRequireTableOwnerByOid removed from pgcolumnar_expire:

  • main: ttl_expire passes 70/70.
  • this head: "a role that does not own the table cannot expire it, even holding DELETE (42501): got [|0] want [42501|3000]". The non-owner retired every row, as you say.

Keeping the owner's control on its own table (ttl_ctl) is the right fix for the collateral red. Leaving the half-declaration item until there is a non-crashing proof is the right call too.

Needs a rebase before merge. Main is 1933577, with #1353 and #1355 in, which share ttl_expire.sh and test_ttl_expire.py. That gives:

  • Ledger: 2343 / 1796, so with your seven rows (three dated) I expect 2350 / 1800.
  • Count: cluster_tests is now 533, so yours goes to 534.

Restate both from a recount and a collection, and I'll check and merge.

jdatcmd and others added 2 commits October 14, 2026 02:33
…ropped one, with rows it could drop, in both twins (commandprompt#1341)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the refusal it controls (commandprompt#1341)

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

Copy link
Copy Markdown
Collaborator Author

@jdatcmd, rebasing onto c558971 now. #1353 and #1355 changed both ttl files since this PR's evidence. The test files auto-merged; cluster_tests conflicted and becomes 534. I'm re-running the merged files clean on 15–19, with all three mutants, and will regenerate the ledger rows from those logs rather than reuse the old ones. I'll push with the restated totals (I expect your 2361 / 1801) once the runs are in.

@OffgridwithJD

Copy link
Copy Markdown
Collaborator Author

@jdatcmd, rebased onto c558971. The new head is cc5557b, replacing d2d1fe7. Ledger: 2361 / 1801, cluster_tests 534, as you expected.

I'll ping on green CI.

@OffgridwithJD
OffgridwithJD force-pushed the test/1341-expire-refusals branch from d2d1fe7 to cc5557b Compare October 14, 2026 02:38

@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.

Re-approving cc5557b.

  • Ledger: a recount gives 2361 / 1801, which agrees with the budget. No duplicate keys, no dated premise: row.
  • Patch: the ttl_expire changes are the same 125 lines as d2d1fe7, the head I reviewed and reproduced, rebased around #1353 and #1355.
  • Counts: cluster_tests 534 by collection; the database-free set gives 429 passed.

Merging.

@jdatcmd
jdatcmd merged commit 4027b8d into commandprompt:main Oct 14, 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