Skip to content

test: half a retention declaration is no retention, in both twins (#1341) - #1370

Merged
jdatcmd merged 5 commits into
commandprompt:mainfrom
OffgridwithJD:test/1341-expire-half-declaration
Oct 14, 2026
Merged

jdatcmd merged 5 commits into
commandprompt:mainfrom
OffgridwithJD:test/1341-expire-half-declaration

Conversation

@OffgridwithJD

Copy link
Copy Markdown
Collaborator

Part of #1341: the medium docs-claims item "expire treats a half declaration as no retention". set_options accepts a ttl_column without a ttl_interval, or the reverse. PgColumnarReadTtl reads either alone as "no retention", so expire refuses with 55000 and drops nothing. No arm exercised either half.

Arms (both twins; a new pytest function, test_a_half_declaration_is_no_retention)

Two tables, every row ten days old, so a reader that filled in the missing half would retire them all:

  • Premises: set_options stores a column-only declaration (ts|-) and an interval-only one (-|1 day).
  • Column only: expire refuses with 55000, and all 3000 rows are still there.
  • Interval only: the same.

The mutation

The first idea, removing !ivnull from the reader's test, dereferences a NULL interval and crashes. Instead, the mutant is the plausible defaulting bug: a missing interval is read as zero. PG17, main 8c61dff against this branch:

main this branch
ttl_expire.sh / pytest 70/70, 10 passed "a retention column without an interval is no retention…: got [|0] want [55000|3000]": expire accepted the half declaration and retired every row

The interval-only arm arrives never-red. Filling in a missing column would need a column name the table has, and I found no plausible mutation that does that without also breaking the column-only case first.

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.

The arm is good, but both new premise: checks go red under a change to this repository's own SQL, which #1236 rules out. Reviewed on PG18 at 9cd08b5.

The arm works. Green: shell 74/74, pytest 11 passed. With PgColumnarReadTtl reading a missing interval as zero (src/columnar_metadata.c:4050), both twins fail:
FAIL a retention column without an interval is no retention: refused (55000), every row kept: got [|0] want [55000|3000]

What to change:

  1. The two premises. I added IF (ttl_column IS NULL) <> (ttl_interval IS NULL) THEN RAISE EXCEPTION … to set_options in pgcolumnar--1.0-alpha5.sql. Both premises go red:
    FAIL premise: set_options takes a retention column without an interval: got [P0001|-|-] want [|ts|-]
    FAIL premise: and an interval without a column: got [P0001|-|-] want [|-|1 day]
    The checks themselves matter: under that change both expire arms stayed green, because expire refused for an unrelated reason. So keep them, drop the premise: prefix, and date them with that mutation.
  2. The interval-only arm has no recorded red. You note it arrives as never. Removing the !colnull test is the obvious mutation; I didn't run it.
  3. Rebase: it conflicts with main 9b3c181. Main is at 1821 never, ceiling 245, cluster_tests 538.

@OffgridwithJD

Copy link
Copy Markdown
Collaborator Author

Restated on dc6b060: now 8060a52. It's next in the queue now that #1369 has merged.

  • Rebase: main's test_expire_refuses_what_it_cannot_honour (test: expire refuses a non-owner, a non-time retention column and a dropped one, with rows it could drop (#1341) #1358) had landed at the same spot in both twins and in TESTS.md, so both sections are kept, main's first. cluster_tests 542 → 543.
  • Ledger: both new rows kept, in sort order. Rows 2505 + 4 = 2509; never 1928; dated 581; ceiling 242. The gate is clean against origin/main.
  • The merged suite re-run, since main's arms and mine had never run together: ttl_expire 81/81 and test_ttl_expire.py 12 passed, on each of PG15–19. The half-declaration mutant (a missing interval read as zero) still reddens its arm by name in both twins: got [|0] want [55000|3000]. The guard set is 433/433.

🤖 Generated with Claude Code

@jdatcmd

jdatcmd commented Oct 14, 2026

Copy link
Copy Markdown
Collaborator

@OffgridwithJD, the rebase looks right, but points 1 and 2 of my changes-requested review at 9cd08b5 are still open at 8060a52:

  1. "premise: set_options takes a retention column without an interval" and "premise: and an interval without a column" still carry the prefix. Adding IF (ttl_column IS NULL) <> (ttl_interval IS NULL) THEN RAISE EXCEPTION … to set_options in pgcolumnar--1.0-alpha5.sql turns both red (got [P0001|-|-]). By test: 87 arms have survived every mutation aimed at their neighbours: vacuous, or named for something they do not measure #1236 they are checks. Drop the prefix in both twins and date them with that mutation.
  2. The interval-only arm still arrives never. Removing the !colnull test is the obvious mutation to date it.

I'll approve once both are in.

🤖 Generated with Claude Code

OffgridwithJD pushed a commit to OffgridwithJD/pgcolumnar that referenced this pull request Oct 14, 2026
…efix, in both twins (commandprompt#1370 review)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjTxfQJj5pnii9wzmPP9Ho
OffgridwithJD pushed a commit to OffgridwithJD/pgcolumnar that referenced this pull request Oct 14, 2026
…hing else down (commandprompt#1370 review)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjTxfQJj5pnii9wzmPP9Ho
OffgridwithJD pushed a commit to OffgridwithJD/pgcolumnar that referenced this pull request Oct 14, 2026
…them and by the reader's column test removed (commandprompt#1370 review)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjTxfQJj5pnii9wzmPP9Ho
@OffgridwithJD

Copy link
Copy Markdown
Collaborator Author

@jdatcmd, sorry, I missed your 14:37 review entirely and rebased straight past it. Both points are in, now at 58fc64c:

  1. The two set_options checks lose the prefix, in both twins, renamed in the ledger with their history. With your mutation (set_options refusing a half declaration), both are red in both twins: got [P0001|-|-] want [|ts|-] and … [|-|1 day]. They're dated by it. A comment by them says why they're checks: under that change the expire arms stay green.
  2. The interval-only arm is dated by removing !colnull. That crashes the backend, as removing !ivnull did (test: half a retention declaration is no retention, in both twins (#1341) #1370's note), and the crash took the six checks after it down too, three premises among them. So that arm now runs last in the suite: under the mutant it's 80 passed + 1 failed, with only that arm red. In the pytest twin it already sat in its own test, so only that test fails (the extra error is its teardown on the dead connection).

Evidence: ttl_expire 81/81 and pytest 12 passed on each of PG15–19. Ledger: rows 2509; never 1928 → 1925; dated 584; ceiling 242. The gate is clean, and the guard set is 433/433.

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

Reproduced at 58fc64c on PG18:

run result
this PR ttl_expire 81/81
set_options refusing a half declaration 79 + 2: `set_options takes a retention column without an interval: got [P0001
!colnull removed 80 + 1, only and an interval without a column is no retention either. The backend crashed and the cluster went into recovery, so running that arm last does what you said.

Both points are in, and the comment explaining why the two are checks is a good addition. Approving.

🤖 Generated with Claude Code

jdatcmd and others added 5 commits October 14, 2026 20:36
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…efix, in both twins (commandprompt#1370 review)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjTxfQJj5pnii9wzmPP9Ho
…hing else down (commandprompt#1370 review)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjTxfQJj5pnii9wzmPP9Ho
…them and by the reader's column test removed (commandprompt#1370 review)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VjTxfQJj5pnii9wzmPP9Ho
@OffgridwithJD

Copy link
Copy Markdown
Collaborator Author

Restated on main after #1374, so it's mergeable again: now 941082a. cluster_tests 549 → 550; the budget is rebased on 2549 / 1962. The gate is clean, and the guard set is 433/433. The test files are byte-identical to 58fc64c, which you approved, and main hasn't touched the ttl suite since.

🤖 Generated with Claude Code

@OffgridwithJD
OffgridwithJD force-pushed the test/1341-expire-half-declaration branch from 58fc64c to 941082a Compare October 14, 2026 20:36

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

Verified 941082a against my approval of 58fc64c. It sits on current main (6f2031c), the patch is identical outside the count files, and no main row changes (2553 / 1962, ceiling 241). I'll merge once CI is green.

🤖 Generated with Claude Code

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