diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2007-01-08 16:47:35 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2007-01-08 16:47:35 +0000 |
commit | 757dfd6327b6abeb592aef8c689d59faf6b3f82e (patch) | |
tree | 42baf330fc046e6afe5bb7010db51fea2aa48412 | |
parent | 9c1443e66fa30357365ab2225ff6543721641eb8 (diff) | |
download | postgresql-757dfd6327b6abeb592aef8c689d59faf6b3f82e.tar.gz postgresql-757dfd6327b6abeb592aef8c689d59faf6b3f82e.zip |
Tweak joinlist creation to avoid generating useless one-element subproblems
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.
-rw-r--r-- | src/backend/optimizer/plan/initsplan.c | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 9604bf8e6db..05e2de6e3fd 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.123.2.1 2006/12/07 19:33:48 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.123.2.2 2007/01/08 16:47:35 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 { |