Fix reuse of stale hash tables by duplicated hashed SubPlans

The same SubPlan can appear more than once in a plan tree.  For
example, when an equivalence class has a constant member containing a
SubPlan, each derived "member = constant" clause references that
SubPlan; a hash join's hash keys and its hash clauses can both contain
it; and extract_restriction_or_clauses() can copy it into a new
restriction clause while leaving it in the original join clause.  Each
reference gets its own SubPlanState, with its own hash tables, but
they all share the subplan's PlanState.

A hashed SubPlan whose subquery references outer query levels must
rebuild its hash tables whenever those parameters change.
ExecHashSubPlan() detected that by checking chgParam of the subplan's
PlanState.  But buildSubPlanHash() rescans that PlanState, which
clears its chgParam, so after one SubPlanState had rebuilt its hash
tables, the others no longer saw the change and kept probing hash
tables built for previous parameter values, producing wrong query
results.

To fix, give each SubPlanState its own flag to mark its hash tables as
stale.  ExecReScan() sets it, alongside propagating chgParam to the
node's subplans, ExecHashSubPlan() checks it instead of the subplan's
chgParam, and buildSubPlanHash() clears it.  The new field fits into
existing padding in SubPlanState, so this does not change the struct's
size or the offsets of its other fields.

Reported-by: Samuel Olaoye <[email protected]>
Author: Rahul Yadav <[email protected]>
Reviewed-by: Alexandra Wang <[email protected]>
Reviewed-by: Richard Guo <[email protected]>
Reviewed-by: shihao zhong <[email protected]>
Discussion: 
https://postgr.es/m/[email protected]
Backpatch-through: 14

Branch
------
REL_16_STABLE

Details
-------
https://git.postgresql.org/pg/commitdiff/06e46b6514a8994d4ebf9e39f57203151d4f0a77

Modified Files
--------------
src/backend/executor/execAmi.c          |  7 +++++++
src/backend/executor/nodeSubplan.c      |  5 +++--
src/include/nodes/execnodes.h           |  1 +
src/test/regress/expected/subselect.out | 33 +++++++++++++++++++++++++++++++++
src/test/regress/sql/subselect.sql      | 13 +++++++++++++
5 files changed, 57 insertions(+), 2 deletions(-)

Reply via email to