From ba2883b264d7bc392604bc9f76abfc30de89f5f8 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Mon, 15 Feb 1999 03:22:37 +0000
Subject: [PATCH] Remove duplicate geqo functions, and more optimizer cleanup

---
 src/backend/nodes/copyfuncs.c            |   6 +-
 src/backend/nodes/equalfuncs.c           |   4 +-
 src/backend/nodes/freefuncs.c            |   4 +-
 src/backend/nodes/outfuncs.c             |   4 +-
 src/backend/optimizer/geqo/Makefile      |   4 +-
 src/backend/optimizer/geqo/geqo_eval.c   | 549 +----------------------
 src/backend/optimizer/geqo/geqo_params.c |   9 +-
 src/backend/optimizer/geqo/geqo_paths.c  | 104 -----
 src/backend/optimizer/path/allpaths.c    |  48 +-
 src/backend/optimizer/path/costsize.c    |  18 +-
 src/backend/optimizer/path/indxpath.c    |  16 +-
 src/backend/optimizer/path/joinpath.c    |   3 +-
 src/backend/optimizer/path/joinrels.c    |  97 ++--
 src/backend/optimizer/path/mergeutils.c  |   3 +-
 src/backend/optimizer/path/prune.c       |  10 +-
 src/backend/optimizer/plan/initsplan.c   |   8 +-
 src/backend/optimizer/plan/planmain.c    |  13 +-
 src/backend/optimizer/util/joininfo.c    |   4 +-
 src/backend/optimizer/util/pathnode.c    |  18 +-
 src/backend/optimizer/util/relnode.c     |   4 +-
 src/backend/tcop/postgres.c              |   8 +-
 src/include/nodes/relation.h             |   4 +-
 src/include/optimizer/geqo_paths.h       |  28 --
 src/include/optimizer/internal.h         |   4 +-
 src/include/optimizer/paths.h            |  15 +-
 src/include/storage/proc.h               |  13 +-
 26 files changed, 188 insertions(+), 810 deletions(-)
 delete mode 100644 src/backend/optimizer/geqo/geqo_paths.c
 delete mode 100644 src/include/optimizer/geqo_paths.h

diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 41b689126fe..ea60d4a7d7a 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.70 1999/02/13 23:15:53 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.71 1999/02/15 03:21:58 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1420,7 +1420,7 @@ _copyMergeInfo(MergeInfo *from)
  * ----------------
  */
 static JoinInfo *
-_copyJoinInfo(JoinInfo * from)
+_copyJoinInfo(JoinInfo *from)
 {
 	JoinInfo   *newnode = makeNode(JoinInfo);
 
@@ -1433,7 +1433,7 @@ _copyJoinInfo(JoinInfo * from)
 
 	newnode->mergejoinable = from->mergejoinable;
 	newnode->hashjoinable = from->hashjoinable;
-	newnode->inactive = from->inactive;
+	newnode->bushy_inactive = from->bushy_inactive;
 
 	return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 98cf643454f..5f24da3f34b 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.32 1999/02/13 23:15:55 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.33 1999/02/15 03:21:59 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -522,7 +522,7 @@ _equalSubPlan(SubPlan *a, SubPlan *b)
 }
 
 static bool
-_equalJoinInfo(JoinInfo * a, JoinInfo * b)
+_equalJoinInfo(JoinInfo *a, JoinInfo *b)
 {
 	Assert(IsA(a, JoinInfo));
 	Assert(IsA(b, JoinInfo));
diff --git a/src/backend/nodes/freefuncs.c b/src/backend/nodes/freefuncs.c
index fb96af2a831..b533ee3d719 100644
--- a/src/backend/nodes/freefuncs.c
+++ b/src/backend/nodes/freefuncs.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.10 1999/02/13 23:15:56 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/Attic/freefuncs.c,v 1.11 1999/02/15 03:21:59 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1018,7 +1018,7 @@ _freeMergeInfo(MergeInfo *node)
  * ----------------
  */
 static void
-_freeJoinInfo(JoinInfo * node)
+_freeJoinInfo(JoinInfo *node)
 {
 	/* ----------------
 	 *	free remainder of node
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index dda46b1f054..c39d4c6672c 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- *  $Id: outfuncs.c,v 1.72 1999/02/13 23:15:59 momjian Exp $
+ *  $Id: outfuncs.c,v 1.73 1999/02/15 03:21:59 momjian Exp $
  *
  * NOTES
  *	  Every (plan) node in POSTGRES has an associated "out" routine which
@@ -1196,7 +1196,7 @@ _outHashInfo(StringInfo str, HashInfo *node)
  *	JoinInfo is a subclass of Node.
  */
 static void
-_outJoinInfo(StringInfo str, JoinInfo * node)
+_outJoinInfo(StringInfo str, JoinInfo *node)
 {
 	appendStringInfo(str, " JINFO :otherrels ");
 	_outIntList(str, node->otherrels);
diff --git a/src/backend/optimizer/geqo/Makefile b/src/backend/optimizer/geqo/Makefile
index 9a2cef66020..4864300e645 100644
--- a/src/backend/optimizer/geqo/Makefile
+++ b/src/backend/optimizer/geqo/Makefile
@@ -5,7 +5,7 @@
 #
 # Copyright (c) 1994, Regents of the University of California
 #
-# $Id: Makefile,v 1.10 1998/04/06 00:23:07 momjian Exp $
+# $Id: Makefile,v 1.11 1999/02/15 03:22:00 momjian Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -19,7 +19,7 @@ CFLAGS+= -Wno-error
 endif
 
 OBJS =	geqo_copy.o geqo_eval.o geqo_main.o geqo_misc.o \
-	geqo_params.o geqo_paths.o geqo_pool.o geqo_recombination.o \
+	geqo_params.o geqo_pool.o geqo_recombination.o \
 	geqo_selection.o \
 	geqo_erx.o geqo_pmx.o geqo_cx.o geqo_px.o geqo_ox1.o geqo_ox2.o
 
diff --git a/src/backend/optimizer/geqo/geqo_eval.c b/src/backend/optimizer/geqo/geqo_eval.c
index 00dbffa4ea3..a109ecc48ef 100644
--- a/src/backend/optimizer/geqo/geqo_eval.c
+++ b/src/backend/optimizer/geqo/geqo_eval.c
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: geqo_eval.c,v 1.31 1999/02/15 02:04:58 tgl Exp $
+ * $Id: geqo_eval.c,v 1.32 1999/02/15 03:22:00 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -47,15 +47,7 @@
 
 #include "optimizer/geqo_gene.h"
 #include "optimizer/geqo.h"
-#include "optimizer/geqo_paths.h"
 
-
-static List *gimme_clause_joins(Query *root, RelOptInfo *outer_rel, RelOptInfo *inner_rel);
-static RelOptInfo *gimme_clauseless_join(RelOptInfo *outer_rel, RelOptInfo *inner_rel);
-static RelOptInfo *init_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo * joininfo);
-static List *new_join_tlist(List *tlist, List *other_relids, int first_resdomno);
-static List *new_joininfo_list(List *joininfo_list, List *join_relids);
-static void geqo_joinrel_size(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel);
 static RelOptInfo *geqo_nth(int stop, List *rels);
 
 /*
@@ -123,15 +115,18 @@ gimme_tree(Query *root, Gene *tour, int rel_count, int num_gene, RelOptInfo *out
 		}
 		else
 		{						/* tree main part */
-
-			if (!(new_rels = gimme_clause_joins(root, outer_rel, inner_rel)))
+			if (!(new_rels = make_rels_by_clause_joins(root, outer_rel,
+													   inner_rel->joininfo,
+													   inner_rel->relids)))
 			{
+#ifdef NOT_USED
 				if (BushyPlanFlag)
-				{
-					new_rels = lcons(gimme_clauseless_join(outer_rel, outer_rel), NIL); /* ??? MAU */
-				}
+					new_rels = make_rels_by_clauseless_joins(outer_rel,
+													 lcons(outer_rel,NIL));
 				else
-					new_rels = lcons(gimme_clauseless_join(outer_rel, inner_rel), NIL);
+#endif
+				new_rels = make_rels_by_clauseless_joins(outer_rel,
+												 	lcons(inner_rel,NIL));
 			}
 
 			/* process new_rel->pathlist */
@@ -150,7 +145,7 @@ gimme_tree(Query *root, Gene *tour, int rel_count, int num_gene, RelOptInfo *out
 			 * not possible
 			 */
 			if (length(new_rels) > 1)
-				new_rels = geqo_prune_rels(new_rels);
+				merge_rels_with_same_relids(new_rels);
 
 			if (length(new_rels) > 1)
 			{					/* should never be reached ... */
@@ -161,7 +156,7 @@ gimme_tree(Query *root, Gene *tour, int rel_count, int num_gene, RelOptInfo *out
 			new_rel = (RelOptInfo *) lfirst(new_rels);
 			rel_count++;
 
-			geqo_set_cheapest(new_rel);
+			set_cheapest(new_rel, new_rel->pathlist);
 
 			/* processing of other new_rel attributes */
 			if (new_rel->size <= 0)
@@ -178,526 +173,6 @@ gimme_tree(Query *root, Gene *tour, int rel_count, int num_gene, RelOptInfo *out
 	return outer_rel;			/* tree finished ... */
 }
 
-/*
- * gimme_clause_joins
- *
- * 'outer_rel' is the relation entry for the outer relation
- * 'inner_rel' is the relation entry for the inner relation
- *
- * Returns a list of new join relations.
- */
-
-static List *
-gimme_clause_joins(Query *root, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
-{
-	List	   *join_list = NIL;
-	List	   *i = NIL;
-	List	   *joininfo_list = (List *) outer_rel->joininfo;
-
-	foreach(i, joininfo_list)
-	{
-		JoinInfo   *joininfo = (JoinInfo *) lfirst(i);
-		RelOptInfo *rel = NULL;
-
-		if (!joininfo->inactive)
-		{
-			List	   *other_rels = (List *) joininfo->otherrels;
-
-			if (other_rels != NIL)
-			{
-				if ((length(other_rels) == 1))
-				{
-
-					if (same(other_rels, inner_rel->relids))
-					{			/* look if inner_rel is it... */
-						rel = init_join_rel(outer_rel, inner_rel, joininfo);
-					}
-				}
-				else if (BushyPlanFlag)
-				{				/* ?!? MAU */
-					rel = init_join_rel(outer_rel, get_join_rel(root, other_rels), joininfo);
-				}
-				else
-					rel = NULL;
-
-				if (rel != NULL)
-					join_list = lappend(join_list, rel);
-
-			}
-		}
-	}
-
-	return join_list;
-}
-
-/*
- * gimme_clauseless_join
- *	  Given an outer relation 'outer_rel' and an inner relation
- *	  'inner_rel', create a join relation between 'outer_rel' and 'inner_rel'
- *
- * Returns a new join relation.
- */
-
-static RelOptInfo *
-gimme_clauseless_join(RelOptInfo *outer_rel, RelOptInfo *inner_rel)
-{
-	return init_join_rel(outer_rel, inner_rel, (JoinInfo *) NULL);
-}
-
-/*
- * init_join_rel
- *	  Creates and initializes a new join relation.
- *
- * 'outer_rel' and 'inner_rel' are relation nodes for the relations to be
- *		joined
- * 'joininfo' is the joininfo node(join clause) containing both
- *		'outer_rel' and 'inner_rel', if any exists
- *
- * Returns the new join relation node.
- */
-static RelOptInfo *
-init_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo * joininfo)
-{
-	RelOptInfo *joinrel = makeNode(RelOptInfo);
-	List	   *joinrel_joininfo_list = NIL;
-	List	   *new_outer_tlist;
-	List	   *new_inner_tlist;
-
-	/*
-	 * Create a new tlist by removing irrelevant elements from both tlists
-	 * of the outer and inner join relations and then merging the results
-	 * together.
-	 */
-	new_outer_tlist = new_join_tlist(outer_rel->targetlist,	/* XXX 1-based attnos */
-					   inner_rel->relids, 1);
-	new_inner_tlist = new_join_tlist(inner_rel->targetlist,	/* XXX 1-based attnos */
-					   outer_rel->relids,
-					   length(new_outer_tlist) + 1);
-
-	joinrel->relids = NIL;
-	joinrel->indexed = false;
-	joinrel->pages = 0;
-	joinrel->tuples = 0;
-	joinrel->width = 0;
-/*	  joinrel->targetlist = NIL;*/
-	joinrel->pathlist = NIL;
-	joinrel->cheapestpath = (Path *) NULL;
-	joinrel->pruneable = true;
-	joinrel->classlist = NULL;
-	joinrel->relam = InvalidOid;
-	joinrel->ordering = NULL;
-	joinrel->restrictinfo = NIL;
-	joinrel->joininfo = NULL;
-	joinrel->innerjoin = NIL;
-	joinrel->superrels = NIL;
-
-	joinrel->relids = lcons(outer_rel->relids, lcons(inner_rel->relids, NIL));
-
-	new_outer_tlist = nconc(new_outer_tlist, new_inner_tlist);
-	joinrel->targetlist = new_outer_tlist;
-
-	if (joininfo)
-	{
-		joinrel->restrictinfo = joininfo->jinfo_restrictinfo;
-		if (BushyPlanFlag)
-			joininfo->inactive = true;
-	}
-
-	joinrel_joininfo_list =
-		new_joininfo_list(append(outer_rel->joininfo, inner_rel->joininfo),
-						intAppend(outer_rel->relids, inner_rel->relids));
-
-	joinrel->joininfo = joinrel_joininfo_list;
-
-	geqo_joinrel_size(joinrel, outer_rel, inner_rel);
-
-	return joinrel;
-}
-
-/*
- * new_join_tlist
- *	  Builds a join relations's target list by keeping those elements that
- *	  will be in the final target list and any other elements that are still
- *	  needed for future joins.	For a target list entry to still be needed
- *	  for future joins, its 'joinlist' field must not be empty after removal
- *	  of all relids in 'other_relids'.
- *
- * 'tlist' is the target list of one of the join relations
- * 'other_relids' is a list of relids contained within the other
- *				join relation
- * 'first_resdomno' is the resdom number to use for the first created
- *				target list entry
- *
- * Returns the new target list.
- */
-static List *
-new_join_tlist(List *tlist,
-			   List *other_relids,
-			   int first_resdomno)
-{
-	int			resdomno = first_resdomno - 1;
-	TargetEntry *xtl = NULL;
-	List	   *t_list = NIL;
-	List	   *i = NIL;
-	List	   *join_list = NIL;
-	bool		in_final_tlist = false;
-
-	foreach(i, tlist)
-	{
-		xtl = lfirst(i);
-		/* XXX surely this is wrong?  join_list is never changed?  tgl 2/99 */
-		in_final_tlist = (join_list == NIL);
-		if (in_final_tlist)
-		{
-			resdomno += 1;
-			t_list = lappend(t_list,
-							 create_tl_element(get_expr(xtl), resdomno));
-		}
-	}
-
-	return t_list;
-}
-
-/*
- * new_joininfo_list
- *	  Builds a join relation's joininfo list by checking for join clauses
- *	  which still need to used in future joins involving this relation.  A
- *	  join clause is still needed if there are still relations in the clause
- *	  not contained in the list of relations comprising this join relation.
- *	  New joininfo nodes are only created and added to
- *	  'current_joininfo_list' if a node for a particular join hasn't already
- *	  been created.
- *
- * 'current_joininfo_list' contains a list of those joininfo nodes that
- *		have already been built
- * 'joininfo_list' is the list of join clauses involving this relation
- * 'join_relids' is a list of relids corresponding to the relations
- *		currently being joined
- *
- * Returns a list of joininfo nodes, new and old.
- */
-static List *
-new_joininfo_list(List *joininfo_list, List *join_relids)
-{
-	List	   *current_joininfo_list = NIL;
-	List	   *new_otherrels = NIL;
-	JoinInfo   *other_joininfo = (JoinInfo *) NULL;
-	List	   *xjoininfo = NIL;
-
-	foreach(xjoininfo, joininfo_list)
-	{
-		List	   *or;
-		JoinInfo   *joininfo = (JoinInfo *) lfirst(xjoininfo);
-
-		new_otherrels = joininfo->otherrels;
-		foreach(or, new_otherrels)
-		{
-			if (intMember(lfirsti(or), join_relids))
-				new_otherrels = lremove((void *) lfirst(or), new_otherrels);
-		}
-		joininfo->otherrels = new_otherrels;
-		if (new_otherrels != NIL)
-		{
-			other_joininfo = joininfo_member(new_otherrels,
-											 current_joininfo_list);
-			if (other_joininfo)
-			{
-				other_joininfo->jinfo_restrictinfo =
-					(List *) LispUnion(joininfo->jinfo_restrictinfo,
-									   other_joininfo->jinfo_restrictinfo);
-			}
-			else
-			{
-				other_joininfo = makeNode(JoinInfo);
-
-				other_joininfo->otherrels = joininfo->otherrels;
-				other_joininfo->jinfo_restrictinfo = joininfo->jinfo_restrictinfo;
-				other_joininfo->mergejoinable = joininfo->mergejoinable;
-				other_joininfo->hashjoinable = joininfo->hashjoinable;
-				other_joininfo->inactive = false;
-
-				current_joininfo_list = lcons(other_joininfo,
-											  current_joininfo_list);
-			}
-		}
-	}
-
-	return current_joininfo_list;
-}
-
-#ifdef	NOTUSED
-/*
- * add_new_joininfos
- *	  For each new join relation, create new joininfos that
- *	  use the join relation as inner relation, and add
- *	  the new joininfos to those rel nodes that still
- *	  have joins with the join relation.
- *
- * 'joinrels' is a list of join relations.
- *
- * Modifies the joininfo field of appropriate rel nodes.
- */
-static void
-geqo_add_new_joininfos(Query *root, List *joinrels, List *outerrels)
-{
-	List	   *xjoinrel = NIL;
-	List	   *xrelid = NIL;
-	List	   *xrel = NIL;
-	List	   *xjoininfo = NIL;
-
-	RelOptInfo *rel;
-	List	   *relids;
-
-	List	   *super_rels;
-	List	   *xsuper_rel = NIL;
-	JoinInfo   *new_joininfo;
-
-	foreach(xjoinrel, joinrels)
-	{
-		RelOptInfo *joinrel = (RelOptInfo *) lfirst(xjoinrel);
-
-		foreach(xrelid, joinrel->relids)
-		{
-
-			/*
-			 * length(joinrel->relids) should always be greater that 1,
-			 * because of *JOIN*
-			 */
-
-			/*
-			 * ! BUG BUG ! Relid relid = (Relid)lfirst(xrelid); RelOptInfo
-			 * *rel = get_join_rel(root, relid);
-			 */
-
-			/*
-			 * if ( (root->join_rel_list) != NIL ) { rel =
-			 * get_join_rel(root, xrelid); } else { rel =
-			 * get_base_rel(root, lfirsti(xrelid)); }
-			 */
-
-			/* NOTE: STILL BUGGY FOR CLAUSE-JOINS: */
-
-			/*
-			 * relids = lconsi(lfirsti(xrelid), NIL); rel =
-			 * rel_member(relids, outerrels);
-			 */
-
-			relids = lconsi(lfirsti(xrelid), NIL);
-			rel = rel_member(relids, root->base_rel_list);
-
-			add_superrels(rel, joinrel);
-		}
-	}
-	foreach(xjoinrel, joinrels)
-	{
-		RelOptInfo *joinrel = (RelOptInfo *) lfirst(xjoinrel);
-
-		foreach(xjoininfo, joinrel->joininfo)
-		{
-			JoinInfo   *joininfo = (JoinInfo *) lfirst(xjoininfo);
-			List	   *other_rels = joininfo->otherrels;
-			List	   *restrict_info = joininfo->jinfo_restrictinfo;
-			bool		mergejoinable = joininfo->mergejoinable;
-			bool		hashjoinable = joininfo->hashjoinable;
-
-			foreach(xrelid, other_rels)
-			{
-
-				/*
-				 * ! BUG BUG ! Relid relid = (Relid)lfirst(xrelid);
-				 * RelOptInfo *rel = get_join_rel(root, relid);
-				 */
-
-				/*
-				 * if ( (root->join_rel_list) != NIL ) { rel =
-				 * get_join_rel(root, xrelid); } else { rel =
-				 * get_base_rel(root, lfirsti(xrelid)); }
-				 */
-
-				/* NOTE: STILL BUGGY FOR CLAUSE-JOINS: */
-
-				/*
-				 * relids = lconsi(lfirsti(xrelid), NIL); rel =
-				 * rel_member(relids, outerrels);
-				 */
-
-				relids = lconsi(lfirsti(xrelid), NIL);
-				rel = rel_member(relids, root->base_rel_list);
-
-				super_rels = rel->superrels;
-				new_joininfo = makeNode(JoinInfo);
-
-				new_joininfo->otherrels = joinrel->relids;
-				new_joininfo->jinfo_restrictinfo = restrict_info;
-				new_joininfo->mergejoinable = mergejoinable;
-				new_joininfo->hashjoinable = hashjoinable;
-				new_joininfo->inactive = false;
-				rel->joininfo = lappend(rel->joininfo, new_joininfo);
-
-				foreach(xsuper_rel, super_rels)
-				{
-					RelOptInfo *super_rel = (RelOptInfo *) lfirst(xsuper_rel);
-
-					if (nonoverlap_rels(super_rel, joinrel))
-					{
-						List	   *new_relids = super_rel->relids;
-						JoinInfo   *other_joininfo = joininfo_member(new_relids,
-										joinrel->joininfo);
-
-						if (other_joininfo)
-						{
-							other_joininfo->jinfo_restrictinfo =
-								(List *) LispUnion(restrict_info,
-										other_joininfo->jinfo_restrictinfo);
-						}
-						else
-						{
-							JoinInfo   *new_joininfo = makeNode(JoinInfo);
-
-							new_joininfo->otherrels = new_relids;
-							new_joininfo->jinfo_restrictinfo = restrict_info;
-							new_joininfo->mergejoinable = mergejoinable;
-							new_joininfo->hashjoinable = hashjoinable;
-							new_joininfo->inactive = false;
-							joinrel->joininfo = lappend(joinrel->joininfo,
-										new_joininfo);
-						}
-					}
-				}
-			}
-		}
-	}
-	foreach(xrel, outerrels)
-	{
-		rel = (RelOptInfo *) lfirst(xrel);
-		rel->superrels = NIL;
-	}
-}
-
-/*
- * final_join_rels
- *	   Find the join relation that includes all the original
- *	   relations, i.e. the final join result.
- *
- * 'join_rel_list' is a list of join relations.
- *
- * Returns the list of final join relations.
- */
-static List *
-geqo_final_join_rels(List *join_rel_list)
-{
-	List	   *xrel = NIL;
-	List	   *t_list = NIL;
-
-	/*
-	 * find the relations that has no further joins, i.e., its joininfos
-	 * all have otherrels nil.
-	 */
-	foreach(xrel, join_rel_list)
-	{
-		RelOptInfo *rel = (RelOptInfo *) lfirst(xrel);
-		List	   *xjoininfo = NIL;
-		bool		final = true;
-
-		foreach(xjoininfo, rel->joininfo)
-		{
-			JoinInfo   *joininfo = (JoinInfo *) lfirst(xjoininfo);
-
-			if (joininfo->otherrels != NIL)
-			{
-				final = false;
-				break;
-			}
-		}
-		if (final)
-		{
-			t_list = lappend(t_list, rel);
-		}
-	}
-
-	return t_list;
-}
-
-/*
- * add_superrels
- *	  add rel to the temporary property list superrels.
- *
- * 'rel' a rel node
- * 'super_rel' rel node of a join relation that includes rel
- *
- * Modifies the superrels field of rel
- */
-static void
-add_superrels(RelOptInfo *rel, RelOptInfo *super_rel)
-{
-	rel->superrels = lappend(rel->superrels, super_rel);
-}
-
-/*
- * nonoverlap_rels
- *	  test if two join relations overlap, i.e., includes the same
- *	  relation.
- *
- * 'rel1' and 'rel2' are two join relations
- *
- * Returns non-nil if rel1 and rel2 do not overlap.
- */
-static bool
-nonoverlap_rels(RelOptInfo *rel1, RelOptInfo *rel2)
-{
-	return nonoverlap_sets(rel1->relids, rel2->relids);
-}
-
-static bool
-nonoverlap_sets(List *s1, List *s2)
-{
-	List	   *x = NIL;
-
-	foreach(x, s1)
-	{
-		int			e = lfirsti(x);
-
-		if (intMember(e, s2))
-			return false;
-	}
-	return true;
-}
-
-#endif	 /* NOTUSED */
-
-/*
- * geqo_joinrel_size
- *	  compute estimate for join relation tuples, even for
- *	  long join queries; so get logarithm of size when MAXINT overflow;
- */
-static void
-geqo_joinrel_size(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
-{
-	Cost		temp;
-	int			ntuples;
-
-	temp = (Cost) inner_rel->tuples * (Cost) outer_rel->tuples; /* cartesian product */
-
-	if (joinrel->restrictinfo)
-		temp = temp * product_selec(joinrel->restrictinfo);
-
-	if (temp >= (MAXINT - 1))
-		ntuples = ceil(geqo_log((double) temp, (double) GEQO_LOG_BASE));
-	else
-		ntuples = ceil((double) temp);
-
-	if (ntuples < 1)
-		ntuples = 1;			/* make the best case 1 instead of 0 */
-
-	joinrel->tuples = ntuples;
-}
-
-double
-geqo_log(double x, double b)
-{
-	return log(x) / log(b);
-}
-
 static RelOptInfo *
 geqo_nth(int stop, List *rels)
 {
diff --git a/src/backend/optimizer/geqo/geqo_params.c b/src/backend/optimizer/geqo/geqo_params.c
index 56fa631282b..1c664c1b3b1 100644
--- a/src/backend/optimizer/geqo/geqo_params.c
+++ b/src/backend/optimizer/geqo/geqo_params.c
@@ -5,7 +5,7 @@
 *
 * Copyright (c) 1994, Regents of the University of California
 *
-* $Id: geqo_params.c,v 1.13 1999/02/13 23:16:10 momjian Exp $
+* $Id: geqo_params.c,v 1.14 1999/02/15 03:22:01 momjian Exp $
 *
 *-------------------------------------------------------------------------
 */
@@ -61,6 +61,7 @@
 static int	gimme_pool_size(int string_length);
 static int	gimme_number_generations(int pool_size, int effort);
 static int	next_token(FILE *, char *, int);
+static double geqo_log(double x, double b);
 
 /*
  * geqo_param
@@ -338,3 +339,9 @@ gimme_number_generations(int pool_size, int effort)
 
 	return effort * number_gens;
 }
+
+static double
+geqo_log(double x, double b)
+{
+	return (log(x) / log(b));
+}
diff --git a/src/backend/optimizer/geqo/geqo_paths.c b/src/backend/optimizer/geqo/geqo_paths.c
deleted file mode 100644
index 8f1902a18c7..00000000000
--- a/src/backend/optimizer/geqo/geqo_paths.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * geqo_paths.c
- *	  Routines to process redundant paths and relations
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- * $Id: geqo_paths.c,v 1.21 1999/02/15 02:04:58 tgl Exp $
- *
- *-------------------------------------------------------------------------
- */
-
-#include "postgres.h"
-
-#include "nodes/pg_list.h"
-#include "nodes/relation.h"
-#include "nodes/primnodes.h"
-
-#include "utils/palloc.h"
-#include "utils/elog.h"
-
-#include "optimizer/internal.h"
-#include "optimizer/paths.h"
-#include "optimizer/pathnode.h"
-#include "optimizer/clauses.h"
-#include "optimizer/cost.h"
-
-#include "optimizer/geqo_paths.h"
-
-
-static List *geqo_prune_rel(RelOptInfo *rel, List *other_rels);
-
-/*
- * geqo_prune_rels
- *	  Removes any redundant relation entries from a list of rel nodes
- *	  'rel_list'.
- *
- * Returns the resulting list.
- *
- */
-List *
-geqo_prune_rels(List *rel_list)
-{
-	List	   *temp_list = NIL;
-
-	if (rel_list != NIL)
-	{
-		temp_list = lcons(lfirst(rel_list),
-		  geqo_prune_rels(geqo_prune_rel((RelOptInfo *) lfirst(rel_list),
-										 lnext(rel_list))));
-	}
-	return temp_list;
-}
-
-/*
- * geqo_prune_rel
- *	  Prunes those relations from 'other_rels' that are redundant with
- *	  'rel'.  A relation is redundant if it is built up of the same
- *	  relations as 'rel'.  Paths for the redundant relation are merged into
- *	  the pathlist of 'rel'.
- *
- * Returns a list of non-redundant relations, and sets the pathlist field
- * of 'rel' appropriately.
- *
- */
-static List *
-geqo_prune_rel(RelOptInfo *rel, List *other_rels)
-{
-	List	   *t_list = NIL;
-	List	   *i;
-	RelOptInfo *other_rel;
-
-	foreach(i, other_rels)
-	{
-		other_rel = (RelOptInfo *) lfirst(i);
-		if (same(rel->relids, other_rel->relids))
-		{
-			rel->pathlist = add_pathlist(rel,
-										 rel->pathlist,
-										 other_rel->pathlist);
-		}
-		else
-		{
-			t_list = lappend(t_list, other_rel);
-		}
-	}
-	return t_list;
-}
-
-/*
- * geqo_set_cheapest
- *	  For a relation 'rel' (which corresponds to a join
- *	  relation), set pointers to the cheapest path
- */
-void
-geqo_set_cheapest(RelOptInfo *rel)
-{
-	JoinPath *cheapest = (JoinPath *)set_cheapest(rel, rel->pathlist);
-
-	if (IsA_JoinPath(cheapest))
-		rel->size = compute_joinrel_size(cheapest);
-	else
-		rel->size = 0;
-}
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 3c7b1117695..eec20b250da 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.34 1999/02/14 05:27:11 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.35 1999/02/15 03:22:03 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -44,7 +44,7 @@ int32		_use_geqo_rels_ = GEQO_RELS;
 
 
 static void find_base_rel_paths(Query *root, List *rels);
-static List *find_join_paths(Query *root, List *outer_rels, int levels_needed);
+static RelOptInfo *make_one_rel_by_joins(Query *root, List *outer_rels, int levels_needed);
 
 #ifdef OPTIMIZER_DEBUG
 static void debug_print_rel(Query *root, RelOptInfo *rel);
@@ -52,14 +52,14 @@ static void debug_print_rel(Query *root, RelOptInfo *rel);
 #endif
 
 /*
- * find_paths
- *	  Finds all possible access paths for executing a query, returning the
- *	  top level list of relation entries.
+ * make_one_rel
+ *	  Finds all possible access paths for executing a query, returning a
+ *	  single rel.
  *
  * 'rels' is the list of single relation entries appearing in the query
  */
-List *
-find_paths(Query *root, List *rels)
+RelOptInfo *
+make_one_rel(Query *root, List *rels)
 {
 	int			levels_needed;
 
@@ -69,7 +69,7 @@ find_paths(Query *root, List *rels)
 	levels_needed = length(rels);
 
 	if (levels_needed <= 0)
-		return NIL;
+		return NULL;
 
 	find_base_rel_paths(root, rels);
 
@@ -78,7 +78,7 @@ find_paths(Query *root, List *rels)
 		/*
 		 * Unsorted single relation, no more processing is required.
 		 */
-		return rels;
+		return lfirst(rels);
 	}
 	else
 	{
@@ -88,7 +88,7 @@ find_paths(Query *root, List *rels)
 		 */
 		set_rest_relselec(root, rels);
 
-		return find_join_paths(root, rels, levels_needed);
+		return make_one_rel_by_joins(root, rels, levels_needed);
 	}
 }
 
@@ -142,7 +142,7 @@ find_base_rel_paths(Query *root, List *rels)
 }
 
 /*
- * find_join_paths
+ * make_one_rel_by_joins
  *	  Find all possible joinpaths for a query by successively finding ways
  *	  to join single relations into join relations.
  *
@@ -158,8 +158,8 @@ find_base_rel_paths(Query *root, List *rels)
  * Returns the final level of join relations, i.e., the relation that is
  * the result of joining all the original relations together.
  */
-static List *
-find_join_paths(Query *root, List *outer_rels, int levels_needed)
+static RelOptInfo *
+make_one_rel_by_joins(Query *root, List *outer_rels, int levels_needed)
 {
 	List	   *x;
 	List	   *joined_rels = NIL;
@@ -170,7 +170,7 @@ find_join_paths(Query *root, List *outer_rels, int levels_needed)
 	 *	  <utesch@aut.tu-freiberg.de>		   *
 	 *******************************************/
 	if ((_use_geqo_) && length(root->base_rel_list) >= _use_geqo_rels_)
-		return lcons(geqo(root), NIL);  /* returns *one* Rel, so lcons it */
+		return geqo(root);
 	
 	/*******************************************
 	 * rest will be deprecated in case of GEQO *
@@ -184,7 +184,7 @@ find_join_paths(Query *root, List *outer_rels, int levels_needed)
 		 * modify 'joined_rels' accordingly, then eliminate redundant join
 		 * relations.
 		 */
-		joined_rels = make_new_rels_by_joins(root, outer_rels);
+		joined_rels = make_rels_by_joins(root, outer_rels);
 
 		update_rels_pathlist_for_joins(root, joined_rels);
 
@@ -202,9 +202,9 @@ find_join_paths(Query *root, List *outer_rels, int levels_needed)
 
 		rels_set_cheapest(joined_rels);
 
+#ifdef NOT_USED
 		if (BushyPlanFlag)
 		{
-
 			/*
 			 * In case of bushy trees if there is still a join between a
 			 * join relation and another relation, add a new joininfo that
@@ -213,6 +213,7 @@ find_join_paths(Query *root, List *outer_rels, int levels_needed)
 			 */
 			add_new_joininfos(root, joined_rels, outer_rels);
 		}
+#endif
 
 		foreach(x, joined_rels)
 		{
@@ -228,6 +229,7 @@ find_join_paths(Query *root, List *outer_rels, int levels_needed)
 #endif
 		}
 
+#ifdef NOT_USED
 		if (BushyPlanFlag)
 		{
 			/*
@@ -243,16 +245,24 @@ find_join_paths(Query *root, List *outer_rels, int levels_needed)
 			root->join_rel_list = outer_rels;
 		}
 		else
-			root->join_rel_list = joined_rels;
+#endif
+		root->join_rel_list = joined_rels;
 
+#ifdef NOT_USED
 		if (!BushyPlanFlag)
-			outer_rels = joined_rels;
+#endif
+		outer_rels = joined_rels;
+
 	}
 
+	Assert(length(joined_rels) == 1);
+
+#ifdef NOT_USED
 	if (BushyPlanFlag)
 		return final_join_rels(outer_rels);
 	else
-		return joined_rels;
+#endif
+	return lfirst(joined_rels);
 }
 
 /*****************************************************************************
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c
index facadef913b..cb30dec42cc 100644
--- a/src/backend/optimizer/path/costsize.c
+++ b/src/backend/optimizer/path/costsize.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.32 1999/02/13 23:16:16 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.33 1999/02/15 03:22:04 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -440,21 +440,19 @@ compute_joinrel_size(JoinPath *joinpath)
 	Cost		temp = 1.0;
 	int			temp1 = 0;
 
+	/* cartesian product */
 	temp *= ((Path *) joinpath->outerjoinpath)->parent->size;
 	temp *= ((Path *) joinpath->innerjoinpath)->parent->size;
 
 	temp = temp * product_selec(joinpath->pathinfo);
-	if (temp >= (MAXINT - 1))
-		temp1 = MAXINT;
-	else
+	if (temp >= (MAXINT-1)/2)
 	{
-
-		/*
-		 * should be ceil here, we don't want joinrel size's of one, do
-		 * we?
-		 */
-		temp1 = ceil((double) temp);
+		/* if we exceed (MAXINT-1)/2, we switch to log scale */
+		/* +1 prevents log(0) */
+		temp1 = ceil(log(temp + 1 - (MAXINT-1)/2) + (MAXINT-1)/2);
 	}
+	else
+		temp1 = ceil((double) temp);
 	Assert(temp1 >= 0);
 
 	return temp1;
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 1c616883737..3a66153fa7b 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.46 1999/02/15 02:04:55 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.47 1999/02/15 03:22:05 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1302,13 +1302,13 @@ index_innerjoin(Query *root, RelOptInfo *rel, List *clausegroup_list,
 		pathnode->path.joinid = ((RestrictInfo *) lfirst(clausegroup))->restrictinfojoinid;
 
 		pathnode->path.path_cost = cost_index((Oid) lfirsti(index->relids),
-					   (int) temp_pages,
-					   temp_selec,
-					   rel->pages,
-					   rel->tuples,
-					   index->pages,
-					   index->tuples,
-					   true);
+											   (int) temp_pages,
+											   temp_selec,
+											   rel->pages,
+											   rel->tuples,
+											   index->pages,
+											   index->tuples,
+											   true);
 
 		/*
 		 * copy restrictinfo list into path for expensive function
diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c
index 9dd7580570c..3577ebfda26 100644
--- a/src/backend/optimizer/path/joinpath.c
+++ b/src/backend/optimizer/path/joinpath.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.26 1999/02/15 02:04:57 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.27 1999/02/15 03:22:05 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -78,6 +78,7 @@ update_rels_pathlist_for_joins(Query *root, List *joinrels)
 		Path	   *bestinnerjoin;
 		List	   *pathlist = NIL;
 
+		/* flatten out relids later in this function */
 		innerrelids = lsecond(joinrel->relids);
 		outerrelids = lfirst(joinrel->relids);
 
diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c
index 5b063db4c79..cd0a082b736 100644
--- a/src/backend/optimizer/path/joinrels.c
+++ b/src/backend/optimizer/path/joinrels.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinrels.c,v 1.22 1999/02/15 02:04:57 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinrels.c,v 1.23 1999/02/15 03:22:05 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -31,20 +31,15 @@ bool		_use_right_sided_plans_ = false;
 
 #endif
 
-static List *find_clause_joins(Query *root, RelOptInfo *outer_rel, List *joininfo_list);
-static List *find_clauseless_joins(RelOptInfo *outer_rel, List *inner_rels);
-static RelOptInfo *init_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo * joininfo);
-static List *new_join_tlist(List *tlist, List *other_relids,
-			   int first_resdomno);
 static List *new_joininfo_list(List *joininfo_list, List *join_relids);
 static void add_superrels(RelOptInfo *rel, RelOptInfo *super_rel);
 static bool nonoverlap_rels(RelOptInfo *rel1, RelOptInfo *rel2);
 static bool nonoverlap_sets(List *s1, List *s2);
 static void set_joinrel_size(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel,
-				 JoinInfo * jinfo);
+				 JoinInfo *jinfo);
 
 /*
- * make_new_rels_by_joins
+ * make_rels_by_joins
  *	  Find all possible joins for each of the outer join relations in
  *	  'outer_rels'.  A rel node is created for each possible join relation,
  *	  and the resulting list of nodes is returned.	If at all possible, only
@@ -57,7 +52,7 @@ static void set_joinrel_size(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptI
  * Returns a list of rel nodes corresponding to the new join relations.
  */
 List *
-make_new_rels_by_joins(Query *root, List *outer_rels)
+make_rels_by_joins(Query *root, List *outer_rels)
 {
 	List	   *joins = NIL;
 	List	   *join_list = NIL;
@@ -67,16 +62,20 @@ make_new_rels_by_joins(Query *root, List *outer_rels)
 	{
 		RelOptInfo *outer_rel = (RelOptInfo *) lfirst(r);
 
-		if (!(joins = find_clause_joins(root, outer_rel, outer_rel->joininfo)))
+		if (!(joins = make_rels_by_clause_joins(root, outer_rel,
+													outer_rel->joininfo,
+													NIL)))
 		{
 			/*
 			 * Oops, we have a relation that is not joined to any other
 			 * relation.  Cartesian product time.
 			 */
+#ifdef NOT_USED
 			if (BushyPlanFlag)
-				joins = find_clauseless_joins(outer_rel, outer_rels);
+				joins = make_rels_by_clauseless_joins(outer_rel, outer_rels);
 			else
-				joins = find_clauseless_joins(outer_rel, root->base_rel_list);
+#endif
+			joins = make_rels_by_clauseless_joins(outer_rel, root->base_rel_list);
 		}
 
 		join_list = nconc(join_list, joins);
@@ -86,7 +85,7 @@ make_new_rels_by_joins(Query *root, List *outer_rels)
 }
 
 /*
- * find_clause_joins
+ * make_rels_by_clause_joins
  *	  Determines whether joins can be performed between an outer relation
  *	  'outer_rel' and those relations within 'outer_rel's joininfo nodes
  *	  (i.e., relations that participate in join clauses that 'outer_rel'
@@ -100,8 +99,9 @@ make_new_rels_by_joins(Query *root, List *outer_rels)
  *
  * Returns a list of new join relations.
  */
-static List *
-find_clause_joins(Query *root, RelOptInfo *outer_rel, List *joininfo_list)
+List *
+make_rels_by_clause_joins(Query *root, RelOptInfo *outer_rel,
+				 				List *joininfo_list, List *only_relids)
 {
 	List	   *join_list = NIL;
 	List	   *i = NIL;
@@ -111,15 +111,18 @@ find_clause_joins(Query *root, RelOptInfo *outer_rel, List *joininfo_list)
 		JoinInfo   *joininfo = (JoinInfo *) lfirst(i);
 		RelOptInfo *rel;
 
-		if (!joininfo->inactive)
+		if (!joininfo->bushy_inactive)
 		{
 			List	   *other_rels = joininfo->otherrels;
 
 			if (other_rels != NIL)
 			{
-				if (length(other_rels) == 1)
+				if (length(other_rels) == 1 &&
+					(only_relids == NIL ||
+					/* geqo only wants certain relids to make new rels */
+					 same(joininfo->otherrels, only_relids)))
 				{
-					rel = init_join_rel(outer_rel,
+					rel = make_join_rel(outer_rel,
 								 get_base_rel(root, lfirsti(other_rels)),
 										joininfo);
 					/* how about right-sided plan ? */
@@ -128,18 +131,20 @@ find_clause_joins(Query *root, RelOptInfo *outer_rel, List *joininfo_list)
 					{
 						if (rel != NULL)
 							join_list = lappend(join_list, rel);
-						rel = init_join_rel(get_base_rel(root,
+						rel = make_join_rel(get_base_rel(root,
 														 lfirsti(other_rels)),
 											outer_rel,
 											joininfo);
 					}
 				}
+#ifdef NOT_USED
 				else if (BushyPlanFlag)
 				{
-					rel = init_join_rel(outer_rel,
+					rel = make_join_rel(outer_rel,
 										get_join_rel(root, other_rels),
 										joininfo);
 				}
+#endif
 				else
 					rel = NULL;
 
@@ -153,15 +158,15 @@ find_clause_joins(Query *root, RelOptInfo *outer_rel, List *joininfo_list)
 }
 
 /*
- * find_clauseless_joins
+ * make_rels_by_clauseless_joins
  *	  Given an outer relation 'outer_rel' and a list of inner relations
  *	  'inner_rels', create a join relation between 'outer_rel' and each
  *	  member of 'inner_rels' that isn't already included in 'outer_rel'.
  *
  * Returns a list of new join relations.
  */
-static List *
-find_clauseless_joins(RelOptInfo *outer_rel, List *inner_rels)
+List *
+make_rels_by_clauseless_joins(RelOptInfo *outer_rel, List *inner_rels)
 {
 	RelOptInfo *inner_rel;
 	List	   *t_list = NIL;
@@ -173,7 +178,7 @@ find_clauseless_joins(RelOptInfo *outer_rel, List *inner_rels)
 		if (nonoverlap_rels(inner_rel, outer_rel))
 		{
 			t_list = lappend(t_list,
-							 init_join_rel(outer_rel,
+							 make_join_rel(outer_rel,
 										   inner_rel,
 										   (JoinInfo *) NULL));
 		}
@@ -183,7 +188,7 @@ find_clauseless_joins(RelOptInfo *outer_rel, List *inner_rels)
 }
 
 /*
- * init_join_rel
+ * make_join_rel
  *	  Creates and initializes a new join relation.
  *
  * 'outer_rel' and 'inner_rel' are relation nodes for the relations to be
@@ -193,8 +198,8 @@ find_clauseless_joins(RelOptInfo *outer_rel, List *inner_rels)
  *
  * Returns the new join relation node.
  */
-static RelOptInfo *
-init_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo * joininfo)
+RelOptInfo *
+make_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo *joininfo)
 {
 	RelOptInfo *joinrel = makeNode(RelOptInfo);
 	List	   *joinrel_joininfo_list = NIL;
@@ -217,7 +222,7 @@ init_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo * joininfo)
 	joinrel->pages = 0;
 	joinrel->tuples = 0;
 	joinrel->width = 0;
-/*	  joinrel->targetlist = NIL;*/
+/*	joinrel->targetlist = NIL;*/
 	joinrel->pathlist = NIL;
 	joinrel->cheapestpath = (Path *) NULL;
 	joinrel->pruneable = true;
@@ -229,9 +234,11 @@ init_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo * joininfo)
 	joinrel->innerjoin = NIL;
 	joinrel->superrels = NIL;
 
-	joinrel->relids = lcons(outer_rel->relids,	/* ??? aren't they lists?
-												 * -ay */
-							lcons(inner_rel->relids, NIL));
+	/*
+	 * This function uses a trick to pass inner/outer rels as
+	 * different lists, and then flattens it out later.
+	 */
+	joinrel->relids = lcons(outer_rel->relids, lcons(inner_rel->relids, NIL));
 
 	new_outer_tlist = nconc(new_outer_tlist, new_inner_tlist);
 	joinrel->targetlist = new_outer_tlist;
@@ -239,8 +246,10 @@ init_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo * joininfo)
 	if (joininfo)
 	{
 		joinrel->restrictinfo = joininfo->jinfo_restrictinfo;
+#ifdef NOT_USED
 		if (BushyPlanFlag)
-			joininfo->inactive = true;
+			joininfo->bushy_inactive = true;
+#endif
 	}
 
 	joinrel_joininfo_list = new_joininfo_list(append(outer_rel->joininfo, inner_rel->joininfo),
@@ -269,7 +278,7 @@ init_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo * joininfo)
  *
  * Returns the new target list.
  */
-static List *
+List *
 new_join_tlist(List *tlist,
 			   List *other_relids,
 			   int first_resdomno)
@@ -352,7 +361,7 @@ new_joininfo_list(List *joininfo_list, List *join_relids)
 				other_joininfo->jinfo_restrictinfo = joininfo->jinfo_restrictinfo;
 				other_joininfo->mergejoinable = joininfo->mergejoinable;
 				other_joininfo->hashjoinable = joininfo->hashjoinable;
-				other_joininfo->inactive = false;
+				other_joininfo->bushy_inactive = false;
 
 				current_joininfo_list = lcons(other_joininfo,
 											  current_joininfo_list);
@@ -418,7 +427,7 @@ add_new_joininfos(Query *root, List *joinrels, List *outerrels)
 				new_joininfo->jinfo_restrictinfo = restrict_info;
 				new_joininfo->mergejoinable = mergejoinable;
 				new_joininfo->hashjoinable = hashjoinable;
-				new_joininfo->inactive = false;
+				new_joininfo->bushy_inactive = false;
 				rel->joininfo = lappend(rel->joininfo, new_joininfo);
 
 				foreach(xsuper_rel, super_rels)
@@ -444,7 +453,7 @@ add_new_joininfos(Query *root, List *joinrels, List *outerrels)
 							new_joininfo->jinfo_restrictinfo = restrict_info;
 							new_joininfo->mergejoinable = mergejoinable;
 							new_joininfo->hashjoinable = hashjoinable;
-							new_joininfo->inactive = false;
+							new_joininfo->bushy_inactive = false;
 							joinrel->joininfo = lappend(joinrel->joininfo,
 										new_joininfo);
 						}
@@ -461,6 +470,7 @@ add_new_joininfos(Query *root, List *joinrels, List *outerrels)
 	}
 }
 
+#ifdef NOT_USED
 /*
  * final_join_rels
  *	   Find the join relation that includes all the original
@@ -470,11 +480,11 @@ add_new_joininfos(Query *root, List *joinrels, List *outerrels)
  *
  * Returns the list of final join relations.
  */
-List *
+RelOptInfo *
 final_join_rels(List *join_rel_list)
 {
 	List	   *xrel = NIL;
-	List	   *t_list = NIL;
+	RelOptInfo *final_rel = NULL;
 
 	/*
 	 * find the relations that has no further joins, i.e., its joininfos
@@ -497,13 +507,14 @@ final_join_rels(List *join_rel_list)
 			}
 		}
 		if (final)
-		{
-			t_list = lappend(t_list, rel);
-		}
+			if (final_rel == NULL ||
+				path_is_cheaper(rel->cheapestpath, final_rel->cheapestpath))
+				final_rel = rel;
 	}
 
-	return t_list;
+	return final_rel;
 }
+#endif
 
 /*
  * add_superrels
@@ -551,7 +562,7 @@ nonoverlap_sets(List *s1, List *s2)
 }
 
 static void
-set_joinrel_size(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo * jinfo)
+set_joinrel_size(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo *jinfo)
 {
 	int			ntuples;
 	float		selec;
diff --git a/src/backend/optimizer/path/mergeutils.c b/src/backend/optimizer/path/mergeutils.c
index d6af886f1ef..7d0009c3e8b 100644
--- a/src/backend/optimizer/path/mergeutils.c
+++ b/src/backend/optimizer/path/mergeutils.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/mergeutils.c,v 1.18 1999/02/13 23:16:20 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/mergeutils.c,v 1.19 1999/02/15 03:22:06 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -47,7 +47,6 @@ group_clauses_by_order(List *restrictinfo_list,
 
 		if (merge_ordering)
 		{
-
 			/*
 			 * Create a new mergeinfo node and add it to 'mergeinfo_list'
 			 * if one does not yet exist for this merge ordering.
diff --git a/src/backend/optimizer/path/prune.c b/src/backend/optimizer/path/prune.c
index 828b8cce80f..ab1e8fff664 100644
--- a/src/backend/optimizer/path/prune.c
+++ b/src/backend/optimizer/path/prune.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/prune.c,v 1.32 1999/02/14 04:56:47 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/prune.c,v 1.33 1999/02/15 03:22:06 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -106,7 +106,7 @@ rels_set_cheapest(List *rel_list)
 	}
 }
 
-
+#ifdef NOT_USED
 /*
  * merge_joinrels
  *	  Given two lists of rel nodes that are already
@@ -133,7 +133,7 @@ merge_joinrels(List *rel_list1, List *rel_list2)
 
 /*
  * prune_oldrels
- *	  If all the joininfo's in a rel node are inactive,
+ *	  If all the joininfo's in a rel node are bushy_inactive,
  *	  that means that this node has been joined into
  *	  other nodes in all possible ways, therefore
  *	  this node can be discarded.  If not, it will cause
@@ -165,7 +165,7 @@ prune_oldrels(List *old_rels)
 			{
 				JoinInfo   *joininfo = (JoinInfo *) lfirst(xjoininfo);
 
-				if (!joininfo->inactive)
+				if (!joininfo->bushy_inactive)
 				{
 					temp_list = lcons(rel, temp_list);
 					break;
@@ -175,3 +175,5 @@ prune_oldrels(List *old_rels)
 	}
 	return temp_list;
 }
+#endif
+
diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index e379a2bbedf..bb6b48b5362 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.25 1999/02/15 01:06:58 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.26 1999/02/15 03:22:11 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -339,14 +339,14 @@ set_joininfo_mergeable_hashable(List *rel_list)
 
 					if (_enable_mergejoin_)
 						sortop = mergejoinop(clause);
-					if (_enable_hashjoin_)
-						hashop = hashjoinop(clause);
-
 					if (sortop)
 					{
 						restrictinfo->mergejoinorder = sortop;
 						joininfo->mergejoinable = true;
 					}
+
+					if (_enable_hashjoin_)
+						hashop = hashjoinop(clause);
 					if (hashop)
 					{
 						restrictinfo->hashjoinoperator = hashop;
diff --git a/src/backend/optimizer/plan/planmain.c b/src/backend/optimizer/plan/planmain.c
index ff84df67eda..24b746e6062 100644
--- a/src/backend/optimizer/plan/planmain.c
+++ b/src/backend/optimizer/plan/planmain.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.32 1999/02/14 04:56:50 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planmain.c,v 1.33 1999/02/15 03:22:12 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -215,7 +215,6 @@ query_planner(Query *root,
 	}
 
 #ifdef NOT_USED
-
 	/*
 	 * Destructively modify the query plan's targetlist to add fjoin lists
 	 * to flatten functions that return sets of base types
@@ -243,7 +242,6 @@ subplanner(Query *root,
 		   List *qual)
 {
 	RelOptInfo *final_rel;
-	List	   *final_rel_list;
 
 	/*
 	 * Initialize the targetlist and qualification, adding entries to
@@ -259,12 +257,7 @@ subplanner(Query *root,
 
 	set_joininfo_mergeable_hashable(root->base_rel_list);
 
-	final_rel_list = find_paths(root, root->base_rel_list);
-
-	if (final_rel_list)
-		final_rel = (RelOptInfo *) lfirst(final_rel_list);
-	else
-		final_rel = (RelOptInfo *) NIL;
+	final_rel = make_one_rel(root, root->base_rel_list);
 
 #if 0							/* fix xfunc */
 
@@ -297,7 +290,7 @@ subplanner(Query *root,
 		return create_plan((Path *) final_rel->cheapestpath);
 	else
 	{
-		elog(NOTICE, "final relation is nil");
+		elog(NOTICE, "final relation is null");
 		return create_plan((Path *) NULL);
 	}
 
diff --git a/src/backend/optimizer/util/joininfo.c b/src/backend/optimizer/util/joininfo.c
index 4b9dce6e5a3..339a4550182 100644
--- a/src/backend/optimizer/util/joininfo.c
+++ b/src/backend/optimizer/util/joininfo.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/joininfo.c,v 1.15 1999/02/13 23:16:45 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/joininfo.c,v 1.16 1999/02/15 03:22:16 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -74,7 +74,7 @@ find_joininfo_node(RelOptInfo *this_rel, List *join_relids)
 		joininfo->jinfo_restrictinfo = NIL;
 		joininfo->mergejoinable = false;
 		joininfo->hashjoinable = false;
-		joininfo->inactive = false;
+		joininfo->bushy_inactive = false;
 		this_rel->joininfo = lcons(joininfo, this_rel->joininfo);
 	}
 	return joininfo;
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index cf3072a8be7..8e72cabb740 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.35 1999/02/13 23:16:46 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.36 1999/02/15 03:22:16 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -381,15 +381,15 @@ create_index_path(Query *root,
 /* is the statement above really true?	what about IndexScan as the
    inner of a join? */
 		pathnode->path.path_cost = cost_index(lfirsti(index->relids),
-					   index->pages,
-					   1.0,
-					   rel->pages,
-					   rel->tuples,
-					   index->pages,
-					   index->tuples,
-					   false);
-		/* add in expensive functions cost!  -- JMH, 7/7/92 */
+											   index->pages,
+											   1.0,
+											   rel->pages,
+											   rel->tuples,
+											   index->pages,
+											   index->tuples,
+											   false);
 #if 0
+		/* add in expensive functions cost!  -- JMH, 7/7/92 */
 		if (XfuncMode != XFUNC_OFF)
 		{
 			pathnode->path_cost = (pathnode->path_cost +
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index 1b0c1d69474..63c0ca4f47b 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.13 1999/02/13 23:16:48 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.14 1999/02/15 03:22:17 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -64,14 +64,12 @@ get_base_rel(Query *root, int relid)
 		 */
 		if (relid < 0)
 		{
-
 			/*
 			 * If the relation is a materialized relation, assume
 			 * constants for sizes.
 			 */
 			rel->pages = _NONAME_RELATION_PAGES_;
 			rel->tuples = _NONAME_RELATION_TUPLES_;
-
 		}
 		else
 		{
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 059772767f9..adf4ddd43e2 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.99 1999/02/13 23:18:45 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.100 1999/02/15 03:22:21 momjian Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -173,8 +173,10 @@ int			UseNewLine = 0;		/* Use EOF as query delimiters */
  *		plans
  * ----------------
  */
+#ifdef NOT_USED
 int			BushyPlanFlag = 0;	/* default to false -- consider only
 								 * left-deep trees */
+#endif
 
 /*
 ** Flags for expensive function optimization -- JMH 3/9/92
@@ -1041,6 +1043,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
 #endif
 				break;
 
+#ifdef NOT_USED
 			case 'b':
 				/* ----------------
 				 *	set BushyPlanFlag to true.
@@ -1048,6 +1051,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
 				 */
 				BushyPlanFlag = 1;
 				break;
+#endif
 
 			case 'B':
 				/* ----------------
@@ -1538,7 +1542,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
 	if (!IsUnderPostmaster)
 	{
 		puts("\nPOSTGRES backend interactive interface ");
-		puts("$Revision: 1.99 $ $Date: 1999/02/13 23:18:45 $\n");
+		puts("$Revision: 1.100 $ $Date: 1999/02/15 03:22:21 $\n");
 	}
 
 	/* ----------------
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index f3f08f8efa6..250fc29dfeb 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: relation.h,v 1.23 1999/02/13 23:21:42 momjian Exp $
+ * $Id: relation.h,v 1.24 1999/02/15 03:22:23 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -250,7 +250,7 @@ typedef struct JoinInfo
 	List	   *jinfo_restrictinfo;
 	bool		mergejoinable;
 	bool		hashjoinable;
-	bool		inactive;
+	bool		bushy_inactive;
 } JoinInfo;
 
 typedef struct Iter
diff --git a/src/include/optimizer/geqo_paths.h b/src/include/optimizer/geqo_paths.h
deleted file mode 100644
index 2a62b459be7..00000000000
--- a/src/include/optimizer/geqo_paths.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * geqo_paths.h
- *	  prototypes for various subroutines in geqo_path.c
- *
- * Copyright (c) 1994, Regents of the University of California
- *
- * $Id: geqo_paths.h,v 1.9 1999/02/13 23:21:47 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-
-/* contributed by:
-   =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
-   *  Martin Utesch				 * Institute of Automatic Control	   *
-   =							 = University of Mining and Technology =
-   *  utesch@aut.tu-freiberg.de  * Freiberg, Germany				   *
-   =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=
- */
-
-#ifndef GEQO_PATHS_H
-#define GEQO_PATHS_H
-
-
-extern List *geqo_prune_rels(List *rel_list);
-extern void geqo_set_cheapest(RelOptInfo *rel);
-
-#endif	 /* GEQO_PATHS_H */
diff --git a/src/include/optimizer/internal.h b/src/include/optimizer/internal.h
index d818cec7700..c372e63e5df 100644
--- a/src/include/optimizer/internal.h
+++ b/src/include/optimizer/internal.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: internal.h,v 1.14 1999/02/13 23:21:49 momjian Exp $
+ * $Id: internal.h,v 1.15 1999/02/15 03:22:31 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -80,7 +80,9 @@
 #define FLOAT_EQUAL(X,Y) ((X) - (Y) < TOLERANCE)
 #define FLOAT_IS_ZERO(X) (FLOAT_EQUAL(X,0.0))
 
+#ifdef NOT_USED
 extern int	BushyPlanFlag;
+#endif
 
 /* #define deactivate_joininfo(joininfo)		joininfo->inactive=true*/
 /*#define joininfo_inactive(joininfo)	joininfo->inactive */
diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h
index 99a1cad9804..990cf79224f 100644
--- a/src/include/optimizer/paths.h
+++ b/src/include/optimizer/paths.h
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: paths.h,v 1.16 1999/02/14 04:56:55 momjian Exp $
+ * $Id: paths.h,v 1.17 1999/02/15 03:22:31 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,7 +21,7 @@
 /*
  * allpaths.h
  */
-extern List *find_paths(Query *root, List *rels);
+extern RelOptInfo *make_one_rel(Query *root, List *rels);
 
 /*
  * indxpath.h
@@ -77,16 +77,19 @@ extern MergeInfo *match_order_mergeinfo(PathOrder *ordering,
  * joinrels.h
  *	  routines to determine which relations to join
  */
-extern List *make_new_rels_by_joins(Query *root, List *outer_rels);
+extern List *make_rels_by_joins(Query *root, List *outer_rels);
 extern void add_new_joininfos(Query *root, List *joinrels, List *outerrels);
-extern List *final_join_rels(List *join_rel_list);
+extern List *make_rels_by_clause_joins(Query *root, RelOptInfo *outer_rel,
+								List *joininfo_list, List *only_relids);
+extern List *make_rels_by_clauseless_joins(RelOptInfo *outer_rel,
+												List *inner_rels);
+extern RelOptInfo *make_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo *joininfo);
+extern List *new_join_tlist(List *tlist, List *other_relids,int first_resdomno);
 
 /*
  * prototypes for path/prune.c
  */
 extern void merge_rels_with_same_relids(List *rel_list);
 extern void rels_set_cheapest(List *rel_list);
-extern List *merge_joinrels(List *rel_list1, List *rel_list2);
-extern List *prune_oldrels(List *old_rels);
 
 #endif	 /* PATHS_H */
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index aae5b704427..e58572b0c77 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: proc.h,v 1.17 1999/02/13 23:22:09 momjian Exp $
+ * $Id: proc.h,v 1.18 1999/02/15 03:22:37 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -75,8 +75,15 @@ typedef struct procglobal
 
 extern PROC *MyProc;
 
-#define PROC_INCR_SLOCK(lock) if (MyProc) ((MyProc->sLocks[(lock)])++)
-#define PROC_DECR_SLOCK(lock) if (MyProc) ((MyProc->sLocks[(lock)])--)
+#define PROC_INCR_SLOCK(lock) \
+do { \
+	if (MyProc) (MyProc->sLocks[(lock)])++; \
+} while (0)
+
+#define PROC_DECR_SLOCK(lock) \
+do { \
+	if (MyProc) (MyProc->sLocks[(lock)])--; \
+} while (0)
 
 /*
  * flags explaining why process woke up
-- 
GitLab