From bfe745ef598bb4b0811b9f02498a80575e959089 Mon Sep 17 00:00:00 2001 From: "Andrei V. Lepikhov" Date: Fri, 3 Jul 2026 11:58:04 +0200 Subject: [PATCH v1 2/2] pg_plan_advice: look through gating Results on the NestLoop inner side The preceding commit introduced a new plan shape: the inner side of a NestLoop may now be capped by a gating Result that evaluates outer-only join clauses as a one-time filter, sitting above any Material or Memoize node. pgpa_decompose_join() was unaware of this. Teach the NestLoop case to descend through a gating Result before the strategy checks. This restores the node ordering the rest of the function expects and classifies the strategy as MATERIALIZE/MEMOIZE again. A childless Result is deliberately not descended: it is itself the scan and carries its own RTIs. --- contrib/pg_plan_advice/pgpa_join.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/contrib/pg_plan_advice/pgpa_join.c b/contrib/pg_plan_advice/pgpa_join.c index 067321081e7..8c1c8c355c5 100644 --- a/contrib/pg_plan_advice/pgpa_join.c +++ b/contrib/pg_plan_advice/pgpa_join.c @@ -389,6 +389,16 @@ pgpa_decompose_join(pgpa_plan_walker_context *walker, Plan *plan, case T_NestLoop: + /* + * create_nestloop_plan() may have capped the inner side with a + * gating Result that evaluates outer-only join clauses as a + * one-time filter. It sits above any Material or Memoize node, + * so look through it before determining the join strategy. + */ + if (elidedinner == NULL && is_result_node_with_child(innerplan) && + ((Result *) innerplan)->resconstantqual != NULL) + elidedinner = pgpa_descend_node(pstmt, &innerplan); + /* * The planner may have chosen to place a Material or Memoize node * on the inner side of the NestLoop; if this is present, we -- 2.54.0