typedef struct finalize_primnode_context
 {
        PlannerInfo *root;
-       Bitmapset  *paramids;           /* Set of PARAM_EXEC paramids found */
-       Bitmapset  *outer_params;       /* Set of accessible outer paramids */
+       Bitmapset  *paramids;           /* Non-local PARAM_EXEC paramids found */
 } finalize_primnode_context;
 
 
                                                 process_sublinks_context *context);
 static Bitmapset *finalize_plan(PlannerInfo *root,
                          Plan *plan,
-                         Bitmapset *outer_params,
                          Bitmapset *valid_params);
 static bool finalize_primnode(Node *node, finalize_primnode_context *context);
 
        }
        else
        {
-               List       *params;
                List       *args;
                ListCell   *l;
 
-               /* Adjust the Params */
-               params = generate_subquery_params(root,
-                                                                                 plan->targetlist,
-                                                                                 &splan->paramIds);
-               splan->testexpr = convert_testexpr(root,
-                                                                                  testexpr,
-                                                                                  params);
+               if (testexpr)
+               {
+                       List       *params;
+
+                       /* Adjust the Params in the testexpr */
+                       params = generate_subquery_params(root,
+                                                                                         plan->targetlist,
+                                                                                         &splan->paramIds);
+                       splan->testexpr = convert_testexpr(root,
+                                                                                          testexpr,
+                                                                                          params);
+               }
 
                /*
                 * We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types to
 void
 SS_finalize_plan(PlannerInfo *root, Plan *plan)
 {
-       Bitmapset  *outer_params,
-                          *valid_params,
+       Bitmapset  *valid_params,
                           *initExtParam,
                           *initSetParam;
        Cost            initplan_cost;
        /*
         * First, scan the param list to discover the sets of params that are
         * available from outer query levels and my own query level. We do this
-        * once to save time in the per-plan recursion steps.
+        * once to save time in the per-plan recursion steps.  (This calculation
+        * is overly generous: it can include a lot of params that actually
+        * shouldn't be referenced here.  However, valid_params is just used as
+        * a debugging crosscheck, so it's not worth trying to be exact.)
         */
-       outer_params = valid_params = NULL;
+       valid_params = NULL;
        paramid = 0;
        foreach(l, root->glob->paramlist)
        {
                if (pitem->abslevel < root->query_level)
                {
                        /* valid outer-level parameter */
-                       outer_params = bms_add_member(outer_params, paramid);
                        valid_params = bms_add_member(valid_params, paramid);
                }
                else if (pitem->abslevel == root->query_level &&
        /*
         * Now recurse through plan tree.
         */
-       (void) finalize_plan(root, plan, outer_params, valid_params);
+       (void) finalize_plan(root, plan, valid_params);
 
-       bms_free(outer_params);
        bms_free(valid_params);
 
        /*
        /* allParam must include all these params */
        plan->allParam = bms_add_members(plan->allParam, initExtParam);
        plan->allParam = bms_add_members(plan->allParam, initSetParam);
+       /* extParam must include any child extParam */
+       plan->extParam = bms_add_members(plan->extParam, initExtParam);
        /* but extParam shouldn't include any setParams */
-       initExtParam = bms_del_members(initExtParam, initSetParam);
-       /* empty test ensures extParam is exactly NULL if it's empty */
-       if (!bms_is_empty(initExtParam))
-               plan->extParam = bms_join(plan->extParam, initExtParam);
+       plan->extParam = bms_del_members(plan->extParam, initSetParam);
+       /* ensure extParam is exactly NULL if it's empty */
+       if (bms_is_empty(plan->extParam))
+               plan->extParam = NULL;
 
        plan->startup_cost += initplan_cost;
        plan->total_cost += initplan_cost;
  * This is just an internal notational convenience.
  */
 static Bitmapset *
-finalize_plan(PlannerInfo *root, Plan *plan,
-                         Bitmapset *outer_params, Bitmapset *valid_params)
+finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params)
 {
        finalize_primnode_context context;
 
 
        context.root = root;
        context.paramids = NULL;        /* initialize set to empty */
-       context.outer_params = outer_params;
 
        /*
         * When we call finalize_primnode, context.paramids sets are automatically
                                                bms_add_members(context.paramids,
                                                                                finalize_plan(root,
                                                                                                          (Plan *) lfirst(l),
-                                                                                                         outer_params,
                                                                                                          valid_params));
                                }
                        }
                                                bms_add_members(context.paramids,
                                                                                finalize_plan(root,
                                                                                                          (Plan *) lfirst(l),
-                                                                                                         outer_params,
                                                                                                          valid_params));
                                }
                        }
                                                bms_add_members(context.paramids,
                                                                                finalize_plan(root,
                                                                                                          (Plan *) lfirst(l),
-                                                                                                         outer_params,
                                                                                                          valid_params));
                                }
                        }
        context.paramids = bms_add_members(context.paramids,
                                                                           finalize_plan(root,
                                                                                                         plan->lefttree,
-                                                                                                        outer_params,
                                                                                                         valid_params));
 
        context.paramids = bms_add_members(context.paramids,
                                                                           finalize_plan(root,
                                                                                                         plan->righttree,
-                                                                                                        outer_params,
                                                                                                         valid_params));
 
        /* Now we have all the paramids */
        if (!bms_is_subset(context.paramids, valid_params))
                elog(ERROR, "plan should not reference subplan's variable");
 
-       plan->extParam = bms_intersect(context.paramids, outer_params);
-       plan->allParam = context.paramids;
-
        /*
+        * Note: by definition, extParam and allParam should have the same value
+        * in any plan node that doesn't have child initPlans.  We set them
+        * equal here, and later SS_finalize_plan will update them properly
+        * in node(s) that it attaches initPlans to.
+        *
         * For speed at execution time, make sure extParam/allParam are actually
         * NULL if they are empty sets.
         */
-       if (bms_is_empty(plan->extParam))
+       if (bms_is_empty(context.paramids))
        {
-               bms_free(plan->extParam);
                plan->extParam = NULL;
+               plan->allParam = NULL;
        }
-       if (bms_is_empty(plan->allParam))
+       else
        {
-               bms_free(plan->allParam);
-               plan->allParam = NULL;
+               plan->extParam = context.paramids;
+               plan->allParam = bms_copy(context.paramids);
        }
 
        return plan->allParam;
        {
                SubPlan    *subplan = (SubPlan *) node;
                Plan       *plan = planner_subplan_get_plan(context->root, subplan);
+               ListCell   *lc;
+               Bitmapset  *subparamids;
+
+               /* Recurse into the testexpr, but not into the Plan */
+               finalize_primnode(subplan->testexpr, context);
+
+               /*
+                * Remove any param IDs of output parameters of the subplan that were
+                * referenced in the testexpr.  These are not interesting for
+                * parameter change signaling since we always re-evaluate the subplan.
+                * Note that this wouldn't work too well if there might be uses of the
+                * same param IDs elsewhere in the plan, but that can't happen because
+                * generate_new_param never tries to merge params.
+                */
+               foreach(lc, subplan->paramIds)
+               {
+                       context->paramids = bms_del_member(context->paramids,
+                                                                                          lfirst_int(lc));
+               }
 
-               /* Add outer-level params needed by the subplan to paramids */
-               context->paramids = bms_join(context->paramids,
-                                                                        bms_intersect(plan->extParam,
-                                                                                                  context->outer_params));
-               /* fall through to recurse into subplan args */
+               /* Also examine args list */
+               finalize_primnode((Node *) subplan->args, context);
+
+               /*
+                * Add params needed by the subplan to paramids, but excluding those
+                * we will pass down to it.
+                */
+               subparamids = bms_copy(plan->extParam);
+               foreach(lc, subplan->parParam)
+               {
+                       subparamids = bms_del_member(subparamids, lfirst_int(lc));
+               }
+               context->paramids = bms_join(context->paramids, subparamids);
+
+               return false;                   /* no more to do here */
        }
        return expression_tree_walker(node, finalize_primnode,
                                                                  (void *) context);