diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2007-01-08 16:47:30 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2007-01-08 16:47:30 +0000 |
commit | 19f9376bf48216f421849ba3edf123de5df36364 (patch) | |
tree | 9d604bf5c793d9c9d55bb96af811cf55d48186f2 /src | |
parent | 9a9a143a980c3a4c9c825ce44abf57718f9f66cb (diff) | |
download | postgresql-19f9376bf48216f421849ba3edf123de5df36364.tar.gz postgresql-19f9376bf48216f421849ba3edf123de5df36364.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.
Diffstat (limited to 'src')
-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 e52015d6dc9..3dc7229cf35 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.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 { |