Re: [sqlsmith] Planner error on lateral joins - Mailing list pgsql-hackers

From Tom Lane
Subject Re: [sqlsmith] Planner error on lateral joins
Date
Msg-id 1148060.1606702695@sss.pgh.pa.us
Whole thread Raw
In response to Re: [sqlsmith] Planner error on lateral joins  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-hackers
I wrote:
> Andreas Seltenreich <seltenreich@gmx.de> writes:
>> testing with sqlsmith on master at 3df51ca8b3 produced one instance of
>> the following error:
>> ERROR:  failed to build any 6-way joins

> Thanks for the test case!  The attached modification to use only
> longstanding test tables fails back to 9.5, but succeeds in 9.4.
> I've not tried to bisect yet.

Seems to be a missed consideration in add_placeholders_to_joinrel.
The attached fixes it for me.

            regards, tom lane

diff --git a/src/backend/optimizer/util/placeholder.c b/src/backend/optimizer/util/placeholder.c
index 6abdc0299b..d05ea14234 100644
--- a/src/backend/optimizer/util/placeholder.c
+++ b/src/backend/optimizer/util/placeholder.c
@@ -404,8 +404,10 @@ add_placeholders_to_base_rels(PlannerInfo *root)
  *        and if they contain lateral references, add those references to the
  *        joinrel's direct_lateral_relids.
  *
- * A join rel should emit a PlaceHolderVar if (a) the PHV is needed above
- * this join level and (b) the PHV can be computed at or below this level.
+ * A join rel should emit a PlaceHolderVar if (a) the PHV can be computed
+ * at or below this level and (b) the PHV is needed above this join level.
+ * However, condition (a) is sufficient to add to direct_lateral_relids,
+ * as explained below.
  */
 void
 add_placeholders_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel,
@@ -418,11 +420,11 @@ add_placeholders_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel,
     {
         PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc);

-        /* Is it still needed above this joinrel? */
-        if (bms_nonempty_difference(phinfo->ph_needed, relids))
+        /* Is it computable here? */
+        if (bms_is_subset(phinfo->ph_eval_at, relids))
         {
-            /* Is it computable here? */
-            if (bms_is_subset(phinfo->ph_eval_at, relids))
+            /* Is it still needed above this joinrel? */
+            if (bms_nonempty_difference(phinfo->ph_needed, relids))
             {
                 /* Yup, add it to the output */
                 joinrel->reltarget->exprs = lappend(joinrel->reltarget->exprs,
@@ -450,12 +452,26 @@ add_placeholders_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel,
                     joinrel->reltarget->cost.startup += cost.startup;
                     joinrel->reltarget->cost.per_tuple += cost.per_tuple;
                 }
-
-                /* Adjust joinrel's direct_lateral_relids as needed */
-                joinrel->direct_lateral_relids =
-                    bms_add_members(joinrel->direct_lateral_relids,
-                                    phinfo->ph_lateral);
             }
+
+            /*
+             * Also adjust joinrel's direct_lateral_relids to include the
+             * PHV's source rel(s).  We must do this even if we're not
+             * actually going to emit the PHV, otherwise join_is_legal will
+             * reject valid join orderings.  (In principle maybe we could
+             * instead remove the joinrel's lateral_relids dependency; but
+             * that's complicated to get right, and cases where we're not
+             * going to emit the PHV are too rare to justify the work.)
+             *
+             * In principle we should only do this if the join doesn't yet
+             * include the PHV's source rel(s).  But our caller
+             * build_join_rel() will clean things up by removing the join's
+             * own relids from its direct_lateral_relids, so we needn't
+             * account for that here.
+             */
+            joinrel->direct_lateral_relids =
+                bms_add_members(joinrel->direct_lateral_relids,
+                                phinfo->ph_lateral);
         }
     }
 }

pgsql-hackers by date:

Previous
From: Craig Ringer
Date:
Subject: Re: Printing LSN made easy
Next
From: Tatsuro Yamada
Date:
Subject: Re: list of extended statistics on psql