Skip to content

fix: the cursor Material's plan node id sits above the subplans' ids (#1306 follow-up) - #1312

Merged
jdatcmd merged 1 commit into
commandprompt:mainfrom
OffgridwithJD:fix/1306-plan-node-id
Oct 12, 2026
Merged

jdatcmd merged 1 commit into
commandprompt:mainfrom
OffgridwithJD:fix/1306-plan-node-id

Conversation

@OffgridwithJD

Copy link
Copy Markdown
Collaborator

The cursor Material's node id sits above the subplans' ids (#1306 follow-up)

@jdatcmd's non-blocking note on #1306. set_plan_references numbers the main tree first and the subplans after it, from one counter. My hook took max(main tree) + 1 for the Material, so a cursor whose query had a SubPlan or InitPlan got a Material that repeated the subplan's first node id. plannodes.h says the ids are unique across the final plan.

Fix: the maximum is now taken over stmt->subplans as well, about a dozen lines in pgcolumnar_planner.

Proof, as you suggested, but kept rather than one-off. Under USE_ASSERT_CHECKING, the hook walks the final plan (the main tree plus every subplan) and raises an ERROR if any id repeats. With that check in place and without the fix, the new arm is red on PG16 assert, in both twins:

a SCROLL cursor whose query has a subplan fetches backward as the filter's plan does
  got  [SET BEGIN ERROR:  XX000 ...]
  want [SET BEGIN DECLARE CURSOR 170000|400000 169999|400000 ...]

It's your example shape: SELECT id, (SELECT max(id) FROM tr) ... under DECLARE c SCROLL CURSOR. A premise requires that the plan holds both a Tid Range Scan and an InitPlan. On a release build (CI's PGDG packages) the uniqueness check is compiled out, so there the arm checks the backward fetches only. The PR says so in TESTS.md.

Evidence:

  • tid_range_scan.sh: 36/36 plus the parallel SKIP on PG15–18, and 38/38 on PG19, after a make clean build for each major.
  • Pytest twin on PG16: 33 pass + 1 UNRUN, pytest exited 0; red without the fix.
  • Guard half: 413. Ledger: 2 rows, 1943 → 1945; the arm is dated by the fix removed, and the premise is never. Census 1694.

🤖 Generated with Claude Code

…ommandprompt#1306 follow-up)

set_plan_references numbers the main tree and then the subplans from one
counter, so the main tree's largest id is not the largest: a cursor whose query
had a subplan got a Material whose id repeated the subplan's first node. Found
by @jdatcmd reviewing commandprompt#1306. An assert build now checks every id in the final
plan is unique; the arm 'a SCROLL cursor whose query has a subplan fetches
backward as the filter's plan does' was red (XX000) on PG16 in both twins before
the fix, and is green on PG15-19 after. Ledger 1943 -> 1945, census 1694.

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

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

Approved at 622a749. I reproduced it here, without relying on the PR text:

build the fold of stmt->subplans removed as pushed
PG18 assert (/usr/local/pg18_assert) 35 passed, 1 failed: ERROR: XX000 on the subquery cursor 36/36 + 1 SKIP
PG17 (/usr/local/pg17) 35 passed, 1 failed, the same

The server log says the failure is the new check: pgcolumnar: duplicate plan_node_id after adding a Material above a cursor's plan.

One correction to my own expectation. I ran the PG17 mutant to show that a release build stays green. It doesn't, because /usr/local/pg17 here is configured with --enable-cassert too. So on our dev builds, this check catches the regression on every major. On CI's PGDG release packages, the uniqueness check is compiled out and the check guards only the backward fetches, as your TESTS.md note says. The ledger date is a true observation either way. If a future reader wonders why CI can't redden it, the mutation description could say "(assert builds)", but that's optional.

Checked:

  • Both walkers return on a NULL plan, and PlannedStmt->subplans can hold NULL entries.
  • The subplans resolve against the one flattened stmt->rtable.
  • The assert-only walk costs nothing in release builds.

I'll merge once CI is green.

@jdatcmd

jdatcmd commented Oct 12, 2026

Copy link
Copy Markdown
Collaborator

Merging now: approved at 622a749, 15/15 green.

@jdatcmd
jdatcmd merged commit d7c9951 into commandprompt:main Oct 12, 2026
15 checks passed
OffgridwithJD pushed a commit to OffgridwithJD/pgcolumnar that referenced this pull request Oct 13, 2026
…ith the commandprompt#1308 review's arms

27 rows from a five-major run, 21 dated by eleven mutations merged one log at a
time with --mutation and --target; the six 'never' rows are premises. Census
1694 -> 1700. TESTS.md section 93; cluster_tests 501 by collection. Docs and
CHANGELOG name the MAXVALUE and 1000-partition refusals.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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