]> granicus.if.org Git - postgresql/commitdiff
Tweak joinlist creation to avoid generating useless one-element subproblems
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 8 Jan 2007 16:47:30 +0000 (16:47 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 8 Jan 2007 16:47:30 +0000 (16:47 +0000)
when collapsing of JOIN trees is stopped by join_collapse_limit.  For instance
a list of 11 LEFT JOINs with limit 8 now produces something like
((1 2 3 4 5 6 7 8) 9 10 11 12)
instead of
(((1 2 3 4 5 6 7 8) (9)) 10 11 12)
The latter structure is really only required for a FULL JOIN.
Noted while studying an example from Shane Ambler.

src/backend/optimizer/plan/initsplan.c

index e52015d6dc92024f8c32f034fc5e3d1d82c819a7..3dc7229cf3557740b1ef61c190dd76d001e1da2f 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.126 2007/01/05 22:19:31 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.127 2007/01/08 16:47:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -402,13 +402,34 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join,
                 * except at a FULL JOIN or where join_collapse_limit would be
                 * exceeded.
                 */
-               if (j->jointype != JOIN_FULL &&
-                       (list_length(leftjoinlist) + list_length(rightjoinlist) <=
-                        join_collapse_limit))
+               if (j->jointype == JOIN_FULL)
+               {
+                       /* force the join order exactly at this node */
+                       joinlist = list_make1(list_make2(leftjoinlist, rightjoinlist));
+               }
+               else if (list_length(leftjoinlist) + list_length(rightjoinlist) <=
+                                join_collapse_limit)
+               {
+                       /* OK to combine subproblems */
                        joinlist = list_concat(leftjoinlist, rightjoinlist);
+               }
                else
-                       /* force the join order at this node */
-                       joinlist = list_make1(list_make2(leftjoinlist, rightjoinlist));
+               {
+                       /* can't combine, but needn't force join order above here */
+                       Node   *leftpart,
+                                  *rightpart;
+
+                       /* avoid creating useless 1-element sublists */
+                       if (list_length(leftjoinlist) == 1)
+                               leftpart = (Node *) linitial(leftjoinlist);
+                       else
+                               leftpart = (Node *) leftjoinlist;
+                       if (list_length(rightjoinlist) == 1)
+                               rightpart = (Node *) linitial(rightjoinlist);
+                       else
+                               rightpart = (Node *) rightjoinlist;
+                       joinlist = list_make2(leftpart, rightpart);
+               }
        }
        else
        {