Skip to content

fix: guard against NULL subplan in full-path MERGE sub-case 1 (#2536) - #2546

Open
waterWang wants to merge 1 commit into
apache:masterfrom
waterWang:fix-2536-merge-null-subplan
Open

fix: guard against NULL subplan in full-path MERGE sub-case 1 (#2536)#2546
waterWang wants to merge 1 commit into
apache:masterfrom
waterWang:fix-2536-merge-null-subplan

Conversation

@waterWang

Copy link
Copy Markdown

Fixes #2536.

Root cause: When a full-path MERGE is the first clause followed by a
WITH (Case 3, sub-case 1, path-not-found → create path), the code assumes
node->ss.ps.lefttree is always a SubqueryScanState and reads
ExecGetResultType(sss->subplan). When the MERGE path pattern produces
no base-relation scan (e.g. empty graph), the planner emits a plain
Result plan, the SubqueryScanState cast reads through the wrong struct
layout, sss->subplan is NULL, and ExecGetResultType(NULL) segfaults.

Fix: check IsA(lefttree, SubqueryScanState) before using
SubqueryScanState internals. For a SubqueryScan child the original
code path (remake child scan slot via sss->ss + ExecGetResultType(sss->subplan))
is preserved. For a Result child, use the generic PlanState API
(ExecGetResultType(lefttree)) and store the remade slot in the MERGE
node's own ScanState.

Tests: 41/43 regression tests pass (age_load and age_upgrade are
pre-existing environment failures). New regression test added to
regress/sql/expr.sql reproduces the exact query shape from #2536.

…#2536)

When MERGE is the first clause followed by WITH (Case 3, sub-case 1),
the code assumes the child execution node is always a SubqueryScanState
and dereferences sss->subplan to obtain the tuple descriptor for the
remade scan slot.  When the MERGE path pattern produces no base-relation
scan (e.g. empty graph), the planner emits a plain Result plan instead
of a SubqueryScan, the cast-to-SubqueryScanState reads through the wrong
struct layout, sss->subplan is NULL, and ExecGetResultType(NULL) segfaults.

Fix: check IsA(lefttree, SubqueryScanState) before using SubqueryScanState
internals.  When the child is a SubqueryScan the original code path
(remake child scan slot via sss->ss + ExecGetResultType(sss->subplan))
is preserved without regression.  When the child is a Result plan, use
the generic PlanState API (ExecGetResultType(lefttree)) and store the
remade slot in the MERGE node's own ScanState.

Fixes apache#2536.
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.

Full-path MERGE followed by a WITH constant STARTS WITH predicate causes a PostgreSQL backend segmentation fault

1 participant