]> granicus.if.org Git - postgresql/commitdiff
My recent fix for semijoin planning didn't actually work for a semijoin with a
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 28 Nov 2008 19:29:07 +0000 (19:29 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 28 Nov 2008 19:29:07 +0000 (19:29 +0000)
RHS that can't be unique-ified --- join_is_legal has to check that before
deciding to build a join, else we'll have an unimplementable joinrel.
Per report from Greg Stark.

src/backend/optimizer/path/joinrels.c

index 5f49ee7e290136b631face5fd5ed16bd538b827b..5f2123defc548626ae38fcbc45a459b28a24b2b0 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.95 2008/11/22 22:47:06 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/path/joinrels.c,v 1.96 2008/11/28 19:29:07 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -420,11 +420,13 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
                        reversed = true;
                }
                else if (sjinfo->jointype == JOIN_SEMI &&
-                                bms_equal(sjinfo->syn_righthand, rel2->relids))
+                                bms_equal(sjinfo->syn_righthand, rel2->relids) &&
+                                create_unique_path(root, rel2, rel2->cheapest_total_path,
+                                                                       sjinfo) != NULL)
                {
                        /*
                         * For a semijoin, we can join the RHS to anything else by
-                        * unique-ifying the RHS.
+                        * unique-ifying the RHS (if the RHS can be unique-ified).
                         */
                        if (match_sjinfo)
                                return false;   /* invalid join path */
@@ -432,7 +434,9 @@ join_is_legal(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
                        reversed = false;
                }
                else if (sjinfo->jointype == JOIN_SEMI &&
-                                bms_equal(sjinfo->syn_righthand, rel1->relids))
+                                bms_equal(sjinfo->syn_righthand, rel1->relids) &&
+                                create_unique_path(root, rel1, rel1->cheapest_total_path,
+                                                                       sjinfo) != NULL)
                {
                        /* Reversed semijoin case */
                        if (match_sjinfo)
@@ -664,7 +668,10 @@ make_join_rel(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2)
                        /*
                         * If we know how to unique-ify the RHS and one input rel is
                         * exactly the RHS (not a superset) we can consider unique-ifying
-                        * it and then doing a regular join.
+                        * it and then doing a regular join.  (The create_unique_path
+                        * check here is probably redundant with what join_is_legal did,
+                        * but if so the check is cheap because it's cached.  So test
+                        * anyway to be sure.)
                         */
                        if (bms_equal(sjinfo->syn_righthand, rel2->relids) &&
                                create_unique_path(root, rel2, rel2->cheapest_total_path,