@@ -282,44 +282,55 @@ add_paths_to_joinrel(PlannerInfo *root,
282282 * across joins unless there's a join-order-constraint-based reason to do so.
283283 * So we ignore the param_source_rels restriction when this case applies.
284284 *
285- * However, there's a pitfall: suppose the inner rel (call it A) has a
286- * parameter that is a PlaceHolderVar, and that PHV's minimum eval_at set
287- * includes the outer rel (B) and some third rel (C). If we treat this as a
288- * star-schema case and create a B/A nestloop join that's parameterized by C,
289- * we would end up with a plan in which the PHV's expression has to be
290- * evaluated as a nestloop parameter at the B/A join; and the executor is only
291- * set up to handle simple Vars as NestLoopParams. Rather than add complexity
292- * and overhead to the executor for such corner cases, it seems better to
293- * forbid the join. (Note that existence of such a PHV probably means there
294- * is a join order constraint that will cause us to consider joining B and C
295- * directly; so we can still make use of A's parameterized path, and there is
296- * no need for the star-schema exception.)To implement this exception to the
297- * exception, we check whether any PHVs used in the query could pose such a
298- * hazard. We don't have any simple way of checking whether a risky PHV would
299- * actually be used in the inner plan, and the case is so unusual that it
300- * doesn't seem worth working very hard on it.
301- *
302285 * allow_star_schema_join() returns TRUE if the param_source_rels restriction
303286 * should be overridden, ie, it's okay to perform this join.
304287 */
305- static bool
288+ static inline bool
306289allow_star_schema_join (PlannerInfo * root ,
307290Path * outer_path ,
308291Path * inner_path )
309292{
310293Relids innerparams = PATH_REQ_OUTER (inner_path );
311294Relids outerrelids = outer_path -> parent -> relids ;
312- ListCell * lc ;
313295
314296/*
315- * It'snot a star-schema caseunless the outer rel provides some but not
316- *all of the inner rel's parameterization.
297+ * It's a star-schema caseif the outer rel provides some but not all of
298+ * the inner rel's parameterization.
317299 */
318- if (!(bms_overlap (innerparams ,outerrelids )&&
319- bms_nonempty_difference (innerparams ,outerrelids )))
320- return false;
300+ return (bms_overlap (innerparams ,outerrelids )&&
301+ bms_nonempty_difference (innerparams ,outerrelids ));
302+ }
303+
304+ /*
305+ * There's a pitfall for creating parameterized nestloops: suppose the inner
306+ * rel (call it A) has a parameter that is a PlaceHolderVar, and that PHV's
307+ * minimum eval_at set includes the outer rel (B) and some third rel (C).
308+ * We might think we could create a B/A nestloop join that's parameterized by
309+ * C. But we would end up with a plan in which the PHV's expression has to be
310+ * evaluated as a nestloop parameter at the B/A join; and the executor is only
311+ * set up to handle simple Vars as NestLoopParams. Rather than add complexity
312+ * and overhead to the executor for such corner cases, it seems better to
313+ * forbid the join. (Note that existence of such a PHV probably means there
314+ * is a join order constraint that will cause us to consider joining B and C
315+ * directly; so we can still make use of A's parameterized path with B+C.)
316+ * So we check whether any PHVs used in the query could pose such a hazard.
317+ * We don't have any simple way of checking whether a risky PHV would actually
318+ * be used in the inner plan, and the case is so unusual that it doesn't seem
319+ * worth working very hard on it.
320+ *
321+ * This case can occur whether or not the join's remaining parameterization
322+ * overlaps param_source_rels, so we have to check for it separately from
323+ * allow_star_schema_join, even though it looks much like a star-schema case.
324+ */
325+ static inline bool
326+ check_hazardous_phv (PlannerInfo * root ,
327+ Path * outer_path ,
328+ Path * inner_path )
329+ {
330+ Relids innerparams = PATH_REQ_OUTER (inner_path );
331+ Relids outerrelids = outer_path -> parent -> relids ;
332+ ListCell * lc ;
321333
322- /* Check for hazardous PHVs */
323334foreach (lc ,root -> placeholder_list )
324335{
325336PlaceHolderInfo * phinfo = (PlaceHolderInfo * )lfirst (lc );
@@ -358,13 +369,15 @@ try_nestloop_path(PlannerInfo *root,
358369/*
359370 * Check to see if proposed path is still parameterized, and reject if the
360371 * parameterization wouldn't be sensible --- unless allow_star_schema_join
361- * says to allow it anyway.
372+ * says to allow it anyway. Also, we must reject if check_hazardous_phv
373+ * doesn't like the look of it.
362374 */
363375required_outer = calc_nestloop_required_outer (outer_path ,
364376inner_path );
365377if (required_outer &&
366- !bms_overlap (required_outer ,extra -> param_source_rels )&&
367- !allow_star_schema_join (root ,outer_path ,inner_path ))
378+ ((!bms_overlap (required_outer ,extra -> param_source_rels )&&
379+ !allow_star_schema_join (root ,outer_path ,inner_path ))||
380+ !check_hazardous_phv (root ,outer_path ,inner_path )))
368381{
369382/* Waste no memory when we reject a path here */
370383bms_free (required_outer );