Commit ff38837f authored by Tom Lane's avatar Tom Lane

Fix nasty bug in optimization of multiway joins: optimizer

would sometimes generate a plan that omitted a sort step before merge.
parent 97c52abc
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/hashutils.c,v 1.14 1999/02/22 05:26:18 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/hashutils.c,v 1.15 1999/04/03 00:18:27 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -29,19 +29,20 @@ static HashInfo *match_hashop_hashinfo(Oid hashop, List *hashinfo_list); ...@@ -29,19 +29,20 @@ static HashInfo *match_hashop_hashinfo(Oid hashop, List *hashinfo_list);
* hash operator. * hash operator.
* *
* 'restrictinfo_list' is the list of restrictinfo nodes * 'restrictinfo_list' is the list of restrictinfo nodes
* 'inner_relid' is the relid of the inner join relation * 'inner_relids' is the list of relids in the inner join relation
* (used to determine whether a join var is inner or outer)
* *
* Returns the new list of hashinfo nodes. * Returns the new list of hashinfo nodes.
* *
*/ */
List * List *
group_clauses_by_hashop(List *restrictinfo_list, group_clauses_by_hashop(List *restrictinfo_list,
int inner_relid) Relids inner_relids)
{ {
List *hashinfo_list = NIL; List *hashinfo_list = NIL;
RestrictInfo *restrictinfo = (RestrictInfo *) NULL; RestrictInfo *restrictinfo;
List *i = NIL; List *i;
Oid hashjoinop = 0; Oid hashjoinop;
foreach(i, restrictinfo_list) foreach(i, restrictinfo_list)
{ {
...@@ -54,23 +55,21 @@ group_clauses_by_hashop(List *restrictinfo_list, ...@@ -54,23 +55,21 @@ group_clauses_by_hashop(List *restrictinfo_list,
*/ */
if (hashjoinop) if (hashjoinop)
{ {
HashInfo *xhashinfo = (HashInfo *) NULL;
Expr *clause = restrictinfo->clause; Expr *clause = restrictinfo->clause;
Var *leftop = get_leftop(clause); Var *leftop = get_leftop(clause);
Var *rightop = get_rightop(clause); Var *rightop = get_rightop(clause);
JoinKey *joinkey = (JoinKey *) NULL; HashInfo *xhashinfo;
JoinKey *joinkey;
xhashinfo = match_hashop_hashinfo(hashjoinop, hashinfo_list); xhashinfo = match_hashop_hashinfo(hashjoinop, hashinfo_list);
joinkey = makeNode(JoinKey);
if (inner_relid == leftop->varno) if (intMember(leftop->varno, inner_relids))
{ {
joinkey = makeNode(JoinKey);
joinkey->outer = rightop; joinkey->outer = rightop;
joinkey->inner = leftop; joinkey->inner = leftop;
} }
else else
{ {
joinkey = makeNode(JoinKey);
joinkey->outer = leftop; joinkey->outer = leftop;
joinkey->inner = rightop; joinkey->inner = rightop;
} }
...@@ -79,16 +78,15 @@ group_clauses_by_hashop(List *restrictinfo_list, ...@@ -79,16 +78,15 @@ group_clauses_by_hashop(List *restrictinfo_list,
{ {
xhashinfo = makeNode(HashInfo); xhashinfo = makeNode(HashInfo);
xhashinfo->hashop = hashjoinop; xhashinfo->hashop = hashjoinop;
xhashinfo->jmethod.jmkeys = NIL; xhashinfo->jmethod.jmkeys = NIL;
xhashinfo->jmethod.clauses = NIL; xhashinfo->jmethod.clauses = NIL;
hashinfo_list = lcons(xhashinfo, hashinfo_list); hashinfo_list = lcons(xhashinfo, hashinfo_list);
} }
xhashinfo->jmethod.clauses = lcons(clause, xhashinfo->jmethod.clauses); xhashinfo->jmethod.clauses = lcons(clause,
xhashinfo->jmethod.clauses);
xhashinfo->jmethod.jmkeys = lcons(joinkey, xhashinfo->jmethod.jmkeys); xhashinfo->jmethod.jmkeys = lcons(joinkey,
xhashinfo->jmethod.jmkeys);
} }
} }
return hashinfo_list; return hashinfo_list;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.32 1999/02/22 05:26:20 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.33 1999/04/03 00:18:28 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -97,11 +97,11 @@ update_rels_pathlist_for_joins(Query *root, List *joinrels) ...@@ -97,11 +97,11 @@ update_rels_pathlist_for_joins(Query *root, List *joinrels)
if (_enable_mergejoin_) if (_enable_mergejoin_)
mergeinfo_list = group_clauses_by_order(joinrel->restrictinfo, mergeinfo_list = group_clauses_by_order(joinrel->restrictinfo,
lfirsti(innerrel->relids)); innerrel->relids);
if (_enable_hashjoin_) if (_enable_hashjoin_)
hashinfo_list = group_clauses_by_hashop(joinrel->restrictinfo, hashinfo_list = group_clauses_by_hashop(joinrel->restrictinfo,
lfirsti(innerrel->relids)); innerrel->relids);
/* need to flatten the relids list */ /* need to flatten the relids list */
joinrel->relids = nconc(listCopy(outerrelids), joinrel->relids = nconc(listCopy(outerrelids),
...@@ -173,12 +173,10 @@ best_innerjoin(List *join_paths, Relids outer_relids) ...@@ -173,12 +173,10 @@ best_innerjoin(List *join_paths, Relids outer_relids)
{ {
Path *path = (Path *) lfirst(join_path); Path *path = (Path *) lfirst(join_path);
if (intMember(lfirsti(path->joinid), outer_relids) if (intMember(lfirsti(path->joinid), outer_relids) &&
&& ((cheapest == NULL || (cheapest == NULL ||
path_is_cheaper((Path *) lfirst(join_path), cheapest)))) path_is_cheaper(path, cheapest)))
{ cheapest = path;
cheapest = (Path *) lfirst(join_path);
}
} }
return cheapest; return cheapest;
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/mergeutils.c,v 1.20 1999/03/01 00:10:32 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/mergeutils.c,v 1.21 1999/04/03 00:18:28 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -36,14 +36,15 @@ ...@@ -36,14 +36,15 @@
* Something to fix next time... * Something to fix next time...
* *
* 'restrictinfo_list' is the list of restrictinfo nodes * 'restrictinfo_list' is the list of restrictinfo nodes
* 'inner_relid' is the relid of the inner join relation * 'inner_relids' is the list of relids in the inner join relation
* (used to determine whether a join var is inner or outer)
* *
* Returns the new list of mergeinfo nodes. * Returns the new list of mergeinfo nodes.
* *
*/ */
List * List *
group_clauses_by_order(List *restrictinfo_list, group_clauses_by_order(List *restrictinfo_list,
int inner_relid) Relids inner_relids)
{ {
List *mergeinfo_list = NIL; List *mergeinfo_list = NIL;
List *xrestrictinfo; List *xrestrictinfo;
...@@ -59,26 +60,25 @@ group_clauses_by_order(List *restrictinfo_list, ...@@ -59,26 +60,25 @@ group_clauses_by_order(List *restrictinfo_list,
* Create a new mergeinfo node and add it to 'mergeinfo_list' * Create a new mergeinfo node and add it to 'mergeinfo_list'
* if one does not yet exist for this merge ordering. * if one does not yet exist for this merge ordering.
*/ */
PathOrder *pathorder;
MergeInfo *xmergeinfo;
Expr *clause = restrictinfo->clause; Expr *clause = restrictinfo->clause;
Var *leftop = get_leftop(clause); Var *leftop = get_leftop(clause);
Var *rightop = get_rightop(clause); Var *rightop = get_rightop(clause);
PathOrder *pathorder;
MergeInfo *xmergeinfo;
JoinKey *jmkeys; JoinKey *jmkeys;
pathorder = makeNode(PathOrder); pathorder = makeNode(PathOrder);
pathorder->ordtype = MERGE_ORDER; pathorder->ordtype = MERGE_ORDER;
pathorder->ord.merge = merge_ordering; pathorder->ord.merge = merge_ordering;
xmergeinfo = match_order_mergeinfo(pathorder, mergeinfo_list); xmergeinfo = match_order_mergeinfo(pathorder, mergeinfo_list);
if (inner_relid == leftop->varno) jmkeys = makeNode(JoinKey);
if (intMember(leftop->varno, inner_relids))
{ {
jmkeys = makeNode(JoinKey);
jmkeys->outer = rightop; jmkeys->outer = rightop;
jmkeys->inner = leftop; jmkeys->inner = leftop;
} }
else else
{ {
jmkeys = makeNode(JoinKey);
jmkeys->outer = leftop; jmkeys->outer = leftop;
jmkeys->inner = rightop; jmkeys->inner = rightop;
} }
...@@ -86,10 +86,8 @@ group_clauses_by_order(List *restrictinfo_list, ...@@ -86,10 +86,8 @@ group_clauses_by_order(List *restrictinfo_list,
if (xmergeinfo == NULL) if (xmergeinfo == NULL)
{ {
xmergeinfo = makeNode(MergeInfo); xmergeinfo = makeNode(MergeInfo);
xmergeinfo->m_ordering = merge_ordering; xmergeinfo->m_ordering = merge_ordering;
mergeinfo_list = lcons(xmergeinfo, mergeinfo_list = lcons(xmergeinfo, mergeinfo_list);
mergeinfo_list);
} }
xmergeinfo->jmethod.clauses = lcons(clause, xmergeinfo->jmethod.clauses = lcons(clause,
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: paths.h,v 1.26 1999/02/22 05:26:52 momjian Exp $ * $Id: paths.h,v 1.27 1999/04/03 00:18:26 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -48,7 +48,7 @@ extern List *create_or_index_paths(Query *root, RelOptInfo *rel, List *clauses); ...@@ -48,7 +48,7 @@ extern List *create_or_index_paths(Query *root, RelOptInfo *rel, List *clauses);
* routines to deal with hash keys and clauses * routines to deal with hash keys and clauses
*/ */
extern List *group_clauses_by_hashop(List *restrictinfo_list, extern List *group_clauses_by_hashop(List *restrictinfo_list,
int inner_relid); Relids inner_relids);
/* /*
* joinutils.h * joinutils.h
...@@ -70,9 +70,9 @@ extern List *new_join_pathkeys(List *outer_pathkeys, ...@@ -70,9 +70,9 @@ extern List *new_join_pathkeys(List *outer_pathkeys,
* routines to deal with merge keys and clauses * routines to deal with merge keys and clauses
*/ */
extern List *group_clauses_by_order(List *restrictinfo_list, extern List *group_clauses_by_order(List *restrictinfo_list,
int inner_relid); Relids inner_relids);
extern MergeInfo *match_order_mergeinfo(PathOrder *ordering, extern MergeInfo *match_order_mergeinfo(PathOrder *ordering,
List *mergeinfo_list); List *mergeinfo_list);
/* /*
* joinrels.h * joinrels.h
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment