aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/path/pathkeys.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/path/pathkeys.c')
-rw-r--r--src/backend/optimizer/path/pathkeys.c41
1 files changed, 24 insertions, 17 deletions
diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c
index 6d7b67bee3d..c6eccddab19 100644
--- a/src/backend/optimizer/path/pathkeys.c
+++ b/src/backend/optimizer/path/pathkeys.c
@@ -11,7 +11,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.24 2000/08/08 15:41:31 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.25 2000/09/12 21:06:53 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -694,8 +694,8 @@ find_mergeclauses_for_pathkeys(List *pathkeys, List *restrictinfos)
*
* 'mergeclauses' is a list of RestrictInfos for mergejoin clauses
* that will be used in a merge join.
- * 'tlist' is a relation target list for either the inner or outer
- * side of the proposed join rel. (Not actually needed anymore)
+ * 'rel' is the relation the pathkeys will apply to (ie, either the inner
+ * or outer side of the proposed join rel).
*
* Returns a pathkeys list that can be applied to the indicated relation.
*
@@ -706,7 +706,7 @@ find_mergeclauses_for_pathkeys(List *pathkeys, List *restrictinfos)
List *
make_pathkeys_for_mergeclauses(Query *root,
List *mergeclauses,
- List *tlist)
+ RelOptInfo *rel)
{
List *pathkeys = NIL;
List *i;
@@ -722,30 +722,37 @@ make_pathkeys_for_mergeclauses(Query *root,
Assert(restrictinfo->mergejoinoperator != InvalidOid);
/*
- * Find the key and sortop needed for this mergeclause.
- *
- * Both sides of the mergeclause should appear in one of the query's
- * pathkey equivalence classes, so it doesn't matter which one we
- * use here.
+ * Which key and sortop is needed for this relation?
*/
key = (Node *) get_leftop(restrictinfo->clause);
sortop = restrictinfo->left_sortop;
+ if (!IsA(key, Var) ||
+ !intMember(((Var *) key)->varno, rel->relids))
+ {
+ key = (Node *) get_rightop(restrictinfo->clause);
+ sortop = restrictinfo->right_sortop;
+ if (!IsA(key, Var) ||
+ !intMember(((Var *) key)->varno, rel->relids))
+ elog(ERROR, "make_pathkeys_for_mergeclauses: can't identify which side of mergeclause to use");
+ }
/*
- * Find pathkey sublist for this sort item. We expect to find the
- * canonical set including the mergeclause's left and right sides;
- * if we get back just the one item, something is rotten.
+ * Find or create canonical pathkey sublist for this sort item.
*/
item = makePathKeyItem(key, sortop);
pathkey = make_canonical_pathkey(root, item);
- Assert(length(pathkey) > 1);
/*
- * Since the item we just made is not in the returned canonical
- * set, we can free it --- this saves a useful amount of storage
- * in a big join tree.
+ * Most of the time we will get back a canonical pathkey set
+ * including both the mergeclause's left and right sides (the only
+ * case where we don't is if the mergeclause appeared in an OUTER
+ * JOIN, which causes us not to generate an equijoin set from it).
+ * Therefore, most of the time the item we just made is not part
+ * of the returned structure, and we can free it. This check
+ * saves a useful amount of storage in a big join tree.
*/
- pfree(item);
+ if (item != (PathKeyItem *) lfirst(pathkey))
+ pfree(item);
pathkeys = lappend(pathkeys, pathkey);
}