From 43515ba3f8523e492143e2a1a1159022b5424431 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter_e@gmx.net>
Date: Wed, 24 Jul 2002 19:16:43 +0000
Subject: [PATCH] Remove _deadcode.

---
 src/backend/commands/_deadcode/recipe.c       | 1318 ---------------
 src/backend/commands/_deadcode/version.c      |  346 ----
 src/backend/executor/_deadcode/nodeTee.c      |  499 ------
 .../optimizer/path/_deadcode/predmig.c        |  810 ---------
 src/backend/optimizer/path/_deadcode/xfunc.c  | 1479 -----------------
 src/include/optimizer/_deadcode/xfunc.h       |   83 -
 6 files changed, 4535 deletions(-)
 delete mode 100644 src/backend/commands/_deadcode/recipe.c
 delete mode 100644 src/backend/commands/_deadcode/version.c
 delete mode 100644 src/backend/executor/_deadcode/nodeTee.c
 delete mode 100644 src/backend/optimizer/path/_deadcode/predmig.c
 delete mode 100644 src/backend/optimizer/path/_deadcode/xfunc.c
 delete mode 100644 src/include/optimizer/_deadcode/xfunc.h

diff --git a/src/backend/commands/_deadcode/recipe.c b/src/backend/commands/_deadcode/recipe.c
deleted file mode 100644
index f1b3d84ab48..00000000000
--- a/src/backend/commands/_deadcode/recipe.c
+++ /dev/null
@@ -1,1318 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * recipe.c
- *	  routines for handling execution of Tioga recipes
- *
- * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/_deadcode/Attic/recipe.c,v 1.17 2002/06/20 20:29:27 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres.h"
-
-#include "catalog/pg_type.h"
-#include "commands/recipe.h"
-#include "executor/executor.h"
-#include "libpq/libpq-be.h"
-#include "nodes/execnodes.h"
-#include "nodes/makefuncs.h"
-#include "nodes/parsenodes.h"
-#include "nodes/plannodes.h"
-#include "optimizer/planner.h"
-#include "parser/parse_node.h"
-#include "rewrite/rewriteHandler.h"
-#include "rewrite/rewriteManip.h"
-#include "tcop/dest.h"
-#include "tcop/pquery.h"
-#include "utils/builtins.h"
-#include "utils/relcache.h"
-
-/* from tcop/postgres.c */
-extern CommandDest whereToSendOutput;
-
-#ifndef TIOGA
-
-void
-beginRecipe(RecipeStmt *stmt)
-{
-	elog(WARNING, "You must compile with TIOGA defined in order to use recipes\n");
-}
-
-#else
-
-#include "tioga/tgRecipe.h"
-
-#define DEBUG_RECIPE 1
-
-/* structure to keep track of the tee node plans */
-typedef struct _teePlanInfo
-{
-	char	   *tpi_relName;
-	Query	   *tpi_parsetree;
-	Plan	   *tpi_plan;
-}	TeePlanInfo;
-
-typedef struct _teeInfo
-{
-	int			num;
-	TeePlanInfo *val;
-}	TeeInfo;
-
-QueryTreeList *appendQlist(QueryTreeList * q1, QueryTreeList * q2);
-void		OffsetVarAttno(Node *node, int varno, int offset);
-
-static void appendTeeQuery(TeeInfo * teeInfo,
-			   QueryTreeList * q,
-			   char *teeNodeName);
-
-static Plan *replaceTeeScans(Plan *plan,
-				Query *parsetree,
-				TeeInfo * teeInfo);
-static void replaceSeqScan(Plan *plan,
-			   Plan *parent,
-			   int rt_ind,
-			   Plan *tplan);
-
-static void tg_rewriteQuery(TgRecipe * r, TgNode * n,
-				QueryTreeList * q,
-				QueryTreeList * inputQlist);
-static Node *tg_replaceNumberedParam(Node *expression,
-						int pnum,
-						int rt_ind,
-						char *teeRelName);
-static Node *tg_rewriteParamsInExpr(Node *expression,
-					   QueryTreeList * inputQlist);
-static QueryTreeList *tg_parseSubQuery(TgRecipe * r,
-				 TgNode * n,
-				 TeeInfo * teeInfo);
-static QueryTreeList *tg_parseTeeNode(TgRecipe * r,
-				TgNode * n,
-				int i,
-				QueryTreeList * qList,
-				TeeInfo * teeInfo);
-
-
-/*
-   The Tioga recipe rewrite algorithm:
-
-   To parse a Tioga recipe, we start from an eye node and go backwards through
-   its input nodes.  To rewrite a Tioga node, we do the following:
-
-	  1) parse the node we're at in the standard way (calling parser() )
-	  2) rewrite its input nodes recursively using Tioga rewrite
-	  3) now, with the rewritten input parse trees and the original parse tree
-		 of the node,  we rewrite the the node.
-		 To do the rewrite, we use the target lists, range tables, and
-		 qualifications of the input parse trees
-*/
-
-/*
- * beginRecipe:
- *	  this is the main function to recipe execution
- *	 this function is invoked for EXECUTE RECIPE ...  statements
- *
- *	takes in a RecipeStmt structure from the parser
- * and returns a list of cursor names
- */
-
-void
-beginRecipe(RecipeStmt *stmt)
-{
-	TgRecipe   *r;
-	int			i,
-				numTees;
-	QueryTreeList *qList;
-	char		portalName[1024];
-
-	Plan	   *plan;
-	TupleDesc	attinfo;
-	QueryDesc  *queryDesc;
-	Query	   *parsetree;
-
-	TeeInfo    *teeInfo;
-
-	/*
-	 * retrieveRecipe() reads the recipe from the database and returns a
-	 * TgRecipe* structure we can work with
-	 */
-
-	r = retrieveRecipe(stmt->recipeName);
-
-	if (r == NULL)
-		return;
-
-	/* find the number of tees in the recipe */
-	numTees = r->tees->num;
-
-	if (numTees > 0)
-	{
-		/* allocate a teePlan structure */
-		teeInfo = (TeeInfo *) malloc(sizeof(TeeInfo));
-		teeInfo->num = numTees;
-		teeInfo->val = (TeePlanInfo *) malloc(numTees * sizeof(TeePlanInfo));
-		for (i = 0; i < numTees; i++)
-		{
-			teeInfo->val[i].tpi_relName = r->tees->val[i]->nodeName;
-			teeInfo->val[i].tpi_parsetree = NULL;
-			teeInfo->val[i].tpi_plan = NULL;
-		}
-	}
-	else
-		teeInfo = NULL;
-
-	/*
-	 * for each viewer in the recipe, go backwards from each viewer input
-	 * and generate a plan.  Attach the plan to cursors.
-	 */
-	for (i = 0; i < r->eyes->num; i++)
-	{
-		TgNodePtr	e;
-
-		e = r->eyes->val[i];
-		if (e->inNodes->num > 1)
-		{
-			elog(WARNING,
-				 "beginRecipe: Currently eyes cannot have more than one input");
-		}
-		if (e->inNodes->num == 0)
-		{
-			/* no input to this eye, skip it */
-			continue;
-		}
-
-#ifdef DEBUG_RECIPE
-		elog(WARNING, "beginRecipe: eyes[%d] = %s\n", i, e->nodeName);
-#endif   /* DEBUG_RECIPE */
-
-		qList = tg_parseSubQuery(r, e->inNodes->val[0], teeInfo);
-
-		if (qList == NULL)
-		{
-			/* eye is directly connected to a tee node */
-			/* XXX TODO: handle this case */
-		}
-
-		/* now, plan the queries */
-
-		/*
-		 * should really do everything pg_plan() does, but for now, we
-		 * skip the rule rewrite and time qual stuff
-		 */
-
-		/*
-		 * 1) plan the main query, everything from an eye node back to a
-		 * Tee
-		 */
-		parsetree = qList->qtrees[0];
-
-		/*
-		 * before we plan, we want to see all the changes we did, during
-		 * the rewrite phase, such as creating the tee tables,
-		 * CommandCounterIncrement() allows us to see the changes
-		 */
-		CommandCounterIncrement();
-
-		plan = planner(parsetree);
-
-		/*
-		 * 2) plan the tee queries, (subgraphs rooted from a Tee) by the
-		 * time the eye is processed, all tees that contribute to that eye
-		 * will have been included in the teeInfo list
-		 */
-		if (teeInfo)
-		{
-			int			t;
-			Plan	   *tplan;
-			Tee		   *newplan;
-
-			for (t = 0; t < teeInfo->num; t++)
-			{
-				if (teeInfo->val[t].tpi_plan == NULL)
-				{
-					/* plan it in the usual fashion */
-					tplan = planner(teeInfo->val[t].tpi_parsetree);
-
-					/* now add a tee node to the root of the plan */
-					elog(WARNING, "adding tee plan node to the root of the %s\n",
-						 teeInfo->val[t].tpi_relName);
-					newplan = (Tee *) makeNode(Tee);
-					newplan->plan.targetlist = tplan->targetlist;
-					newplan->plan.qual = NULL;	/* tplan->qual; */
-					newplan->plan.lefttree = tplan;
-					newplan->plan.righttree = NULL;
-					newplan->leftParent = NULL;
-					newplan->rightParent = NULL;
-
-					/*
-					 * the range table of the tee is the range table of
-					 * the tplan
-					 */
-					newplan->rtentries = teeInfo->val[t].tpi_parsetree->rtable;
-					strcpy(newplan->teeTableName,
-						   teeInfo->val[t].tpi_relName);
-					teeInfo->val[t].tpi_plan = (Plan *) newplan;
-				}
-			}
-
-			/*
-			 * 3) replace the tee table scans in the main plan with actual
-			 * tee plannodes
-			 */
-
-			plan = replaceTeeScans(plan, parsetree, teeInfo);
-
-		}						/* if (teeInfo) */
-
-		/* define a portal for this viewer input */
-		/* for now, eyes can only have one input */
-		snprintf(portalName, 1024, "%s%d", e->nodeName, 0);
-
-		queryDesc = CreateQueryDesc(parsetree,
-									plan,
-									whereToSendOutput);
-
-		/*
-		 * call ExecStart to prepare the plan for execution
-		 */
-		attinfo = ExecutorStart(queryDesc, NULL);
-
-		ProcessPortal(portalName,
-					  parsetree,
-					  plan,
-					  attinfo,
-					  whereToSendOutput);
-		elog(WARNING, "beginRecipe: cursor named %s is now available", portalName);
-	}
-
-}
-
-
-
-/*
- * tg_rewriteQuery -
- *	  r - the recipe being rewritten
- *	  n - the node that we're current at
- *	  q - a QueryTree List containing the parse tree of the node
- *	  inputQlist - the parsetrees of its input nodes,
- *				   the size of inputQlist must be the same as the
- *				   number of input nodes.  Some elements in the inpuQlist
- *				   may be null if the inputs to those nodes are unconnected
- *
- *	this is the main routine for rewriting the recipe queries
- *	the original query tree 'q' is modified
- */
-
-static void
-tg_rewriteQuery(TgRecipe * r,
-				TgNode * n,
-				QueryTreeList * q,
-				QueryTreeList * inputQlist)
-{
-	Query	   *orig;
-	Query	   *inputQ;
-	int			i;
-	List	   *rtable;
-	List	   *input_rtable;
-	int			rt_length;
-
-	/* orig is the original parse tree of the node */
-	orig = q->qtrees[0];
-
-
-	/*
-	 * step 1:
-	 *
-	 * form a combined range table from all the range tables in the original
-	 * query as well as the input nodes
-	 *
-	 * form a combined qualification from the qual in the original plus the
-	 * quals of the input nodes
-	 */
-
-	/* start with the original range table */
-	rtable = orig->rtable;
-	rt_length = length(rtable);
-
-	for (i = 0; i < n->inNodes->num; i++)
-	{
-		if (n->inNodes->val[i] != NULL &&
-			n->inNodes->val[i]->nodeType != TG_TEE_NODE)
-		{
-			inputQ = inputQlist->qtrees[i];
-			input_rtable = inputQ->rtable;
-
-			/*
-			 * need to offset the var nodes in the qual and targetlist
-			 * because they are indexed off the original rtable
-			 */
-			OffsetVarNodes((Node *) inputQ->qual, rt_length, 0);
-			OffsetVarNodes((Node *) inputQ->targetList, rt_length, 0);
-
-			/* append the range tables from the children nodes	*/
-			rtable = nconc(rtable, input_rtable);
-
-			/*
-			 * append the qualifications of the child node into the
-			 * original qual list
-			 */
-			AddQual(orig, inputQ->qual);
-		}
-	}
-	orig->rtable = rtable;
-
-	/*
-	 * step 2: rewrite the target list of the original parse tree if there
-	 * are any references to params, replace them with the appropriate
-	 * target list entry of the children node
-	 */
-	if (orig->targetList != NIL)
-	{
-		List	   *tl;
-		TargetEntry *tle;
-
-		foreach(tl, orig->targetList)
-		{
-			tle = lfirst(tl);
-			if (tle->resdom != NULL)
-				tle->expr = tg_rewriteParamsInExpr(tle->expr, inputQlist);
-		}
-	}
-
-	/*
-	 * step 3: rewrite the qual of the original parse tree if there are
-	 * any references to params, replace them with the appropriate target
-	 * list entry of the children node
-	 */
-	if (orig->qual)
-	{
-		if (nodeTag(orig->qual) == T_List)
-			elog(ERROR, "tg_rewriteQuery: Whoa! why is my qual a List???");
-		orig->qual = tg_rewriteParamsInExpr(orig->qual, inputQlist);
-	}
-
-	/*
-	 * at this point, we're done with the rewrite, the querytreelist q has
-	 * been modified
-	 */
-
-}
-
-
-/* tg_replaceNumberedParam:
-
-   this procedure replaces the specified numbered param with a
-   reference to a range table
-
-   this procedure recursively calls itself
-
-   it returns a (possibly modified) Node*.
-
-*/
-static Node *
-tg_replaceNumberedParam(Node *expression,
-						int pnum,		/* the number of the parameter */
-						int rt_ind,		/* the range table index */
-						char *teeRelName)		/* the relname of the tee
-												 * table */
-{
-	TargetEntry *param_tle;
-	Param	   *p;
-	Var		   *newVar,
-			   *oldVar;
-
-	if (expression == NULL)
-		return NULL;
-
-	switch (nodeTag(expression))
-	{
-		case T_Param:
-			{
-				/*
-				 * the node is a parameter, substitute the entry from the
-				 * target list of the child that corresponds to the
-				 * parameter number
-				 */
-				p = (Param *) expression;
-
-				/* we only deal with the case of numbered parameters */
-				if (p->paramkind == PARAM_NUM && p->paramid == pnum)
-				{
-
-					if (p->param_tlist)
-					{
-						/*
-						 * we have a parameter with an attribute like
-						 * $N.foo so replace it with a new var node
-						 */
-
-						/* param tlist can only have one entry in them! */
-						param_tle = (TargetEntry *) (lfirst(p->param_tlist));
-						oldVar = (Var *) param_tle->expr;
-						oldVar->varno = rt_ind;
-						oldVar->varnoold = rt_ind;
-						return (Node *) oldVar;
-					}
-					else
-					{
-						/* we have $N without the .foo */
-						bool		defined;
-						bool		isRel;
-
-						/*
-						 * TODO here, we need to check to see whether the
-						 * type of the tee is a complex type (relation) or
-						 * a simple type
-						 */
-
-						/*
-						 * if it is a simple type, then we need to get the
-						 * "result" attribute from the tee relation
-						 */
-
-						isRel = (typeidTypeRelid(p->paramtype) != 0);
-						if (isRel)
-						{
-							newVar = makeVar(rt_ind,
-											 0, /* the whole tuple */
-										   TypeGet(teeRelName, &defined),
-											 -1,
-											 0,
-											 rt_ind,
-											 0);
-							return (Node *) newVar;
-						}
-						else
-							newVar = makeVar(rt_ind,
-											 1, /* just the first field,
-												 * which is 'result' */
-										   TypeGet(teeRelName, &defined),
-											 -1,
-											 0,
-											 rt_ind,
-											 0);
-						return (Node *) newVar;
-
-					}
-				}
-				else
-					elog(WARNING, "tg_replaceNumberedParam: unexpected paramkind value of %d", p->paramkind);
-			}
-			break;
-		case T_Expr:
-			{
-				/*
-				 * the node is an expression, we need to recursively call
-				 * ourselves until we find parameter nodes
-				 */
-				List	   *l;
-				Expr	   *expr = (Expr *) expression;
-				List	   *newArgs;
-
-				/*
-				 * we have to make a new args lists because Params can be
-				 * replaced by Var nodes in tg_replaceNumberedParam()
-				 */
-				newArgs = NIL;
-
-				/*
-				 * we only care about argument to expressions, it doesn't
-				 * matter when the opType is
-				 */
-				/* recursively rewrite the arguments of this expression */
-				foreach(l, expr->args)
-				{
-					newArgs = lappend(newArgs,
-									  tg_replaceNumberedParam(lfirst(l),
-															  pnum,
-															  rt_ind,
-															teeRelName));
-				}
-				/* change the arguments of the expression */
-				expr->args = newArgs;
-			}
-			break;
-		default:
-			{
-				/* ignore other expr types */
-			}
-	}
-
-	return expression;
-}
-
-
-
-
-
-/* tg_rewriteParamsInExpr:
-
-   rewrite the params in expressions by using the targetlist entries
-   from the input parsetrees
-
-   this procedure recursively calls itself
-
-   it returns a (possibly modified) Node*.
-
-*/
-static Node *
-tg_rewriteParamsInExpr(Node *expression, QueryTreeList * inputQlist)
-{
-	List	   *tl;
-	TargetEntry *param_tle,
-			   *tle;
-	Param	   *p;
-	int			childno;
-	char	   *resname;
-
-	if (expression == NULL)
-		return NULL;
-
-	switch (nodeTag(expression))
-	{
-		case T_Param:
-			{
-				/*
-				 * the node is a parameter, substitute the entry from the
-				 * target list of the child that corresponds to the
-				 * parameter number
-				 */
-				p = (Param *) expression;
-
-				/* we only deal with the case of numbered parameters */
-				if (p->paramkind == PARAM_NUM)
-				{
-					/* paramid's start from 1 */
-					childno = p->paramid - 1;
-
-					if (p->param_tlist)
-					{
-						/*
-						 * we have a parameter with an attribute like
-						 * $N.foo so match the resname "foo" against the
-						 * target list of the (N-1)th inputQlist
-						 */
-
-						/* param tlist can only have one entry in them! */
-						param_tle = (TargetEntry *) (lfirst(p->param_tlist));
-						resname = param_tle->resdom->resname;
-
-						if (inputQlist->qtrees[childno])
-						{
-							foreach(tl, inputQlist->qtrees[childno]->targetList)
-							{
-								tle = lfirst(tl);
-								if (strcmp(resname, tle->resdom->resname) == 0)
-									return tle->expr;
-							}
-						}
-						else
-							elog(ERROR, "tg_rewriteParamsInExpr:can't substitute for parameter %d when that input is unconnected", p->paramid);
-
-					}
-					else
-					{
-						/* we have $N without the .foo */
-						/* use the first resdom in the targetlist of the */
-						/* appropriate child query */
-						tl = inputQlist->qtrees[childno]->targetList;
-						tle = lfirst(tl);
-						return tle->expr;
-					}
-				}
-				else
-					elog(WARNING, "tg_rewriteParamsInExpr: unexpected paramkind value of %d", p->paramkind);
-			}
-			break;
-		case T_Expr:
-			{
-				/*
-				 * the node is an expression, we need to recursively call
-				 * ourselves until we find parameter nodes
-				 */
-				List	   *l;
-				Expr	   *expr = (Expr *) expression;
-				List	   *newArgs;
-
-				/*
-				 * we have to make a new args lists because Params can be
-				 * replaced by Var nodes in tg_rewriteParamsInExpr()
-				 */
-				newArgs = NIL;
-
-				/*
-				 * we only care about argument to expressions, it doesn't
-				 * matter when the opType is
-				 */
-				/* recursively rewrite the arguments of this expression */
-				foreach(l, expr->args)
-				{
-					newArgs = lappend(newArgs,
-						  tg_rewriteParamsInExpr(lfirst(l), inputQlist));
-				}
-				/* change the arguments of the expression */
-				expr->args = newArgs;
-			}
-			break;
-		default:
-			{
-				/* ignore other expr types */
-			}
-	}
-
-	return expression;
-}
-
-
-
-/*
-   getParamTypes:
-	  given an element, finds its parameter types.
-	  the typev array argument is set to the parameter types.
-	  the parameterCount is returned
-
-   this code is very similar to ProcedureDefine() in pg_proc.c
-*/
-static int
-getParamTypes(TgElement * elem, Oid *typev)
-{
-	/* this code is similar to ProcedureDefine() */
-	int16		parameterCount;
-	bool		defined;
-	Oid			toid;
-	char	   *t;
-	int			i,
-				j;
-
-	parameterCount = 0;
-	for (i = 0; i < FUNC_MAX_ARGS; i++)
-		typev[i] = 0;
-	for (j = 0; j < elem->inTypes->num; j++)
-	{
-		if (parameterCount == FUNC_MAX_ARGS)
-		{
-			elog(ERROR,
-				 "getParamTypes: Ingredients cannot take > %d arguments", FUNC_MAX_ARGS);
-		}
-		t = elem->inTypes->val[j];
-		if (strcmp(t, "opaque") == 0)
-		{
-			elog(ERROR,
-				 "getParamTypes: Ingredient functions cannot take type 'opaque'");
-		}
-		else
-		{
-			toid = TypeGet(elem->inTypes->val[j], &defined);
-			if (!OidIsValid(toid))
-				elog(ERROR, "getParamTypes: arg type '%s' is not defined", t);
-			if (!defined)
-				elog(WARNING, "getParamTypes: arg type '%s' is only a shell", t);
-		}
-		typev[parameterCount++] = toid;
-	}
-
-	return parameterCount;
-}
-
-
-/*
- * tg_parseTeeNode
- *
- *	 handles the parsing of the tee node
- *
- *
- */
-
-static QueryTreeList *
-tg_parseTeeNode(TgRecipe * r,
-				TgNode * n,		/* the tee node */
-				int i,			/* which input this node is to its parent */
-				QueryTreeList * qList,
-				TeeInfo * teeInfo)
-
-{
-	QueryTreeList *q;
-	char	   *tt;
-	int			rt_ind;
-	Query	   *orig;
-
-	/*
-	 * the input Node is a tee node, so we need to do the following: we
-	 * need to parse the child of the tee node, we add that to our query
-	 * tree list we need the name of the tee node table the tee node table
-	 * is the table into which the tee node may materialize results.  Call
-	 * it TT we add a range table to our existing query with TT in it we
-	 * need to replace the parameter $i with TT (otherwise the optimizer
-	 * won't know to use the table on expression containining $i) After
-	 * that rewrite, the optimizer will generate sequential scans of TT
-	 *
-	 * Later, in the glue phase, we replace all instances of TT sequential
-	 * scans with the actual Tee node
-	 */
-	q = tg_parseSubQuery(r, n, teeInfo);
-
-	/* tt is the name of the tee node table */
-	tt = n->nodeName;
-
-	if (q)
-		appendTeeQuery(teeInfo, q, tt);
-
-	orig = qList->qtrees[0];
-	rt_ind = RangeTablePosn(orig->rtable, tt);
-
-	/*
-	 * check to see that this table is not part of the range table
-	 * already.  This usually only happens if multiple inputs are
-	 * connected to the same Tee.
-	 */
-	if (rt_ind == 0)
-	{
-		orig->rtable = lappend(orig->rtable,
-							   addRangeTableEntry(NULL,
-												  tt,
-												  tt,
-												  FALSE,
-												  FALSE));
-		rt_ind = length(orig->rtable);
-	}
-
-	orig->qual = tg_replaceNumberedParam(orig->qual,
-										 i + 1, /* params start at 1 */
-										 rt_ind,
-										 tt);
-	return qList;
-}
-
-
-/*
- * tg_parseSubQuery:
- *	  go backwards from a node and parse the query
- *
- *	 the result parse tree is passed back
- *
- * could return NULL if trying to parse a teeNode
- * that's already been processed by another parent
- *
- */
-
-static QueryTreeList *
-tg_parseSubQuery(TgRecipe * r, TgNode * n, TeeInfo * teeInfo)
-{
-	TgElement  *elem;
-	char	   *funcName;
-	Oid			typev[FUNC_MAX_ARGS],	/* eight arguments maximum	*/
-				relid;
-	int			i,
-				parameterCount;
-
-	QueryTreeList *qList;		/* the parse tree of the nodeElement */
-	QueryTreeList *inputQlist;	/* the list of parse trees for the inputs
-								 * to this node */
-	QueryTreeList *q;
-	TgNode	   *child;
-	Relation	rel;
-	unsigned int len;
-	TupleDesc	tupdesc;
-
-	qList = NULL;
-
-	if (n->nodeType == TG_INGRED_NODE)
-	{
-		/* parse each ingredient node in turn */
-
-		elem = n->nodeElem;
-		switch (elem->srcLang)
-		{
-			case TG_SQL:
-				{
-					/*
-					 * for SQL ingredients, the SQL query is contained in
-					 * the 'src' field
-					 */
-
-#ifdef DEBUG_RECIPE
-					elog(WARNING, "calling parser with %s", elem->src);
-#endif   /* DEBUG_RECIPE */
-
-					parameterCount = getParamTypes(elem, typev);
-
-					qList = parser(elem->src, typev, parameterCount);
-
-					if (qList->len > 1)
-					{
-						elog(WARNING,
-							 "tg_parseSubQuery: parser produced > 1 query tree");
-					}
-				}
-				break;
-			case TG_C:
-				{
-					/* C ingredients are registered functions in postgres */
-
-					/*
-					 * we create a new query string by using the function
-					 * name (found in the 'src' field) and adding
-					 * parameters to it so if the function was FOOBAR and
-					 * took in two arguments, we would create a string
-					 * select FOOBAR($1,$2)
-					 */
-					char		newquery[1000];
-
-					funcName = elem->src;
-					parameterCount = getParamTypes(elem, typev);
-
-					if (parameterCount > 0)
-					{
-						int			i;
-
-						snprintf(newquery, 1000, "select %s($1", funcName);
-						for (i = 1; i < parameterCount; i++)
-							snprintf(newquery, 1000, "%s,$%d", pstrdup(newquery), i);
-						snprintf(newquery, 1000, "%s)", pstrdup(newquery));
-					}
-					else
-						snprintf(newquery, 1000, "select %s()", funcName);
-
-#ifdef DEBUG_RECIPE
-					elog(WARNING, "calling parser with %s", newquery);
-#endif   /* DEBUG_RECIPE */
-
-					qList = parser(newquery, typev, parameterCount);
-					if (qList->len > 1)
-					{
-						elog(WARNING,
-							 "tg_parseSubQuery: parser produced > 1 query tree");
-					}
-				}
-				break;
-			case TG_RECIPE_GRAPH:
-				elog(WARNING, "tg_parseSubQuery: can't parse recipe graph ingredients yet!");
-				break;
-			case TG_COMPILED:
-				elog(WARNING, "tg_parseSubQuery: can't parse compiled ingredients yet!");
-				break;
-			default:
-				elog(WARNING, "tg_parseSubQuery: unknown srcLang: %d", elem->srcLang);
-		}
-
-		/* parse each of the subrecipes that are input to this node */
-
-		if (n->inNodes->num > 0)
-		{
-			inputQlist = malloc(sizeof(QueryTreeList));
-			inputQlist->len = n->inNodes->num + 1;
-			inputQlist->qtrees = (Query **) malloc(inputQlist->len * sizeof(Query *));
-			for (i = 0; i < n->inNodes->num; i++)
-			{
-
-				inputQlist->qtrees[i] = NULL;
-				if (n->inNodes->val[i])
-				{
-					if (n->inNodes->val[i]->nodeType == TG_TEE_NODE)
-					{
-						qList = tg_parseTeeNode(r, n->inNodes->val[i],
-												i, qList, teeInfo);
-					}
-					else
-					{			/* input node is not a Tee */
-						q = tg_parseSubQuery(r, n->inNodes->val[i],
-											 teeInfo);
-						Assert(q->len == 1);
-						inputQlist->qtrees[i] = q->qtrees[0];
-					}
-				}
-			}
-
-			/* now, we have all the query trees from our input nodes */
-			/* transform the original parse tree appropriately */
-			tg_rewriteQuery(r, n, qList, inputQlist);
-		}
-	}
-	else if (n->nodeType == TG_EYE_NODE)
-	{
-		/*
-		 * if we hit an eye, we need to stop and make what we have into a
-		 * subrecipe query block
-		 */
-		elog(WARNING, "tg_parseSubQuery: can't handle eye nodes yet");
-	}
-	else if (n->nodeType == TG_TEE_NODE)
-	{
-		/*
-		 * if we hit a tee, check to see if the parsing has been done for
-		 * this tee already by the other parent
-		 */
-
-		rel = RelationNameGetRelation(n->nodeName);
-		if (RelationIsValid(rel))
-		{
-			/*
-			 * this tee has already been visited, no need to do any
-			 * further processing
-			 */
-			return NULL;
-		}
-		else
-		{
-			/* we need to process the child of the tee first, */
-			child = n->inNodes->val[0];
-
-			if (child->nodeType == TG_TEE_NODE)
-			{
-				/* nested Tee nodes */
-				qList = tg_parseTeeNode(r, child, 0, qList, teeInfo);
-				return qList;
-			}
-
-			Assert(child != NULL);
-
-			/* parse the input node */
-			q = tg_parseSubQuery(r, child, teeInfo);
-			Assert(q->len == 1);
-
-			/* add the parsed query to the main list of queries */
-			qList = appendQlist(qList, q);
-
-			/* need to create the tee table here */
-
-			/*
-			 * the tee table created is used both for materializing the
-			 * values at the tee node, and for parsing and optimization.
-			 * The optimization needs to have a real table before it will
-			 * consider scans on it
-			 */
-
-			/*
-			 * first, find the type of the tuples being produced by the
-			 * tee.  The type is the same as the output type of the child
-			 * node.
-			 *
-			 * NOTE: we are assuming that the child node only has a single
-			 * output here!
-			 */
-			getParamTypes(child->nodeElem, typev);
-
-			/*
-			 * the output type is either a complex type, (and is thus a
-			 * relation) or is a simple type
-			 */
-
-			rel = RelationNameGetRelation(child->nodeElem->outTypes->val[0]);
-
-			if (RelationIsValid(rel))
-			{
-				/*
-				 * for complex types, create new relation with the same
-				 * tuple descriptor as the output table type
-				 */
-				len = length(q->qtrees[0]->targetList);
-				tupdesc = rel->rd_att;
-
-				relid = heap_create_with_catalog(
-									   child->nodeElem->outTypes->val[0],
-									   tupdesc, RELKIND_RELATION, false);
-			}
-			else
-			{
-				/*
-				 * we have to create a relation with one attribute of the
-				 * simple base type.  That attribute will have an attr
-				 * name of "result"
-				 */
-				/* NOTE: ignore array types for the time being */
-
-				len = 1;
-				tupdesc = CreateTemplateTupleDesc(len);
-
-				if (!TupleDescInitEntry(tupdesc, 1,
-										"result",
-										InvalidOid,
-										-1, 0, false))
-					elog(WARNING, "tg_parseSubQuery: unexpected result from TupleDescInitEntry");
-				else
-				{
-					relid = heap_create_with_catalog(
-									   child->nodeElem->outTypes->val[0],
-									   tupdesc, RELKIND_RELATION, false);
-				}
-			}
-		}
-	}
-	else if (n->nodeType == TG_RECIPE_NODE)
-		elog(WARNING, "tg_parseSubQuery: can't handle embedded recipes yet!");
-	else
-		elog(WARNING, "unknown nodeType: %d", n->nodeType);
-
-	return qList;
-}
-
-/*
- * OffsetVarAttno -
- *	  recursively find all the var nodes with the specified varno
- * and offset their varattno with the offset
- *
- *	code is similar to OffsetVarNodes in rewriteManip.c
- */
-
-void
-OffsetVarAttno(Node *node, int varno, int offset)
-{
-	if (node == NULL)
-		return;
-	switch (nodeTag(node))
-	{
-		case T_TargetEntry:
-			{
-				TargetEntry *tle = (TargetEntry *) node;
-
-				OffsetVarAttno(tle->expr, varno, offset);
-			}
-			break;
-		case T_Expr:
-			{
-				Expr	   *expr = (Expr *) node;
-
-				OffsetVarAttno((Node *) expr->args, varno, offset);
-			}
-			break;
-		case T_Var:
-			{
-				Var		   *var = (Var *) node;
-
-				if (var->varno == varno)
-					var->varattno += offset;
-			}
-			break;
-		case T_List:
-			{
-				List	   *l;
-
-				foreach(l, (List *) node)
-					OffsetVarAttno(lfirst(l), varno, offset);
-			}
-			break;
-		default:
-			/* ignore the others */
-			break;
-	}
-}
-
-/*
- * appendQlist
- *	  add the contents of a QueryTreeList q2 to the end of the QueryTreeList
- *	 q1
- *
- *	returns a new querytree list
- */
-
-QueryTreeList *
-appendQlist(QueryTreeList * q1, QueryTreeList * q2)
-{
-	QueryTreeList *newq;
-	int			i,
-				j;
-	int			newlen;
-
-	if (q1 == NULL)
-		return q2;
-
-	if (q2 == NULL)
-		return q1;
-
-	newlen = q1->len + q2->len;
-	newq = (QueryTreeList *) malloc(sizeof(QueryTreeList));
-	newq->len = newlen;
-	newq->qtrees = (Query **) malloc(newlen * sizeof(Query *));
-	for (i = 0; i < q1->len; i++)
-		newq->qtrees[i] = q1->qtrees[i];
-	for (j = 0; j < q2->len; j++)
-		newq->qtrees[i + j] = q2->qtrees[j];
-	return newq;
-}
-
-/*
- * appendTeeQuery
- *
- *	modify the query field of the teeInfo list of the particular tee node
- */
-static void
-appendTeeQuery(TeeInfo * teeInfo, QueryTreeList * q, char *teeNodeName)
-{
-	int			i;
-
-	Assert(teeInfo);
-
-	for (i = 0; i < teeInfo->num; i++)
-	{
-		if (strcmp(teeInfo->val[i].tpi_relName, teeNodeName) == 0)
-		{
-
-			Assert(q->len == 1);
-			teeInfo->val[i].tpi_parsetree = q->qtrees[0];
-			return;
-		}
-	}
-	elog(WARNING, "appendTeeQuery: teeNodeName '%s' not found in teeInfo");
-}
-
-
-
-/*
- * replaceSeqScan
- *	  replaces sequential scans of a specified relation with the tee plan
- *	the relation is specified by its index in the range table,	 rt_ind
- *
- * returns the modified plan
- * the offset_attno is the offset that needs to be added to the parent's
- * qual or targetlist because the child plan has been replaced with a tee node
- */
-static void
-replaceSeqScan(Plan *plan, Plan *parent,
-			   int rt_ind, Plan *tplan)
-{
-	Scan	   *snode;
-	Tee		   *teePlan;
-	Result	   *newPlan;
-
-	if (plan == NULL)
-		return;
-
-	if (plan->type == T_SeqScan)
-	{
-		snode = (Scan *) plan;
-		if (snode->scanrelid == rt_ind)
-		{
-			/*
-			 * found the sequential scan that should be replaced with the
-			 * tplan.
-			 */
-			/* we replace the plan, but we also need to modify its parent */
-
-			/*
-			 * replace the sequential scan with a Result node the reason
-			 * we use a result node is so that we get the proper
-			 * projection behavior.  The Result node is simply (ab)used as
-			 * a projection node
-			 */
-
-			newPlan = makeNode(Result);
-			newPlan->plan.cost = 0.0;
-			newPlan->plan.state = (EState *) NULL;
-			newPlan->plan.targetlist = plan->targetlist;
-			newPlan->plan.lefttree = tplan;
-			newPlan->plan.righttree = NULL;
-			newPlan->resconstantqual = NULL;
-			newPlan->resstate = NULL;
-
-			/* change all the varno's to 1 */
-			ChangeVarNodes((Node *) newPlan->plan.targetlist,
-						   snode->scanrelid, 1);
-
-			if (parent)
-			{
-				teePlan = (Tee *) tplan;
-
-				if (parent->lefttree == plan)
-					parent->lefttree = (Plan *) newPlan;
-				else
-					parent->righttree = (Plan *) newPlan;
-
-
-				if (teePlan->leftParent == NULL)
-					teePlan->leftParent = (Plan *) newPlan;
-				else
-					teePlan->rightParent = (Plan *) newPlan;
-
-/* comment for now to test out executor-stuff
-				if (parent->state) {
-					ExecInitNode((Plan*)newPlan, parent->state, (Plan*)newPlan);
-				}
-*/
-			}
-		}
-
-	}
-	else
-	{
-		if (plan->lefttree)
-			replaceSeqScan(plan->lefttree, plan, rt_ind, tplan);
-		if (plan->righttree)
-			replaceSeqScan(plan->righttree, plan, rt_ind, tplan);
-	}
-}
-
-/*
- * replaceTeeScans
- *	  places the sequential scans of the Tee table with
- * a connection to the actual tee plan node
- */
-static Plan *
-replaceTeeScans(Plan *plan, Query *parsetree, TeeInfo * teeInfo)
-{
-
-	int			i;
-	List	   *rtable;
-	RangeTblEntry *rte;
-	char		prefix[5];
-	int			rt_ind;
-	Plan	   *tplan;
-
-	rtable = parsetree->rtable;
-	if (rtable == NULL)
-		return plan;
-
-	/*
-	 * look through the range table for the tee relation entry, that will
-	 * give use the varno we need to detect which sequential scans need to
-	 * be replaced with tee nodes
-	 */
-
-	rt_ind = 0;
-	while (rtable != NIL)
-	{
-		rte = lfirst(rtable);
-		rtable = lnext(rtable);
-		rt_ind++;				/* range table references in varno fields
-								 * start w/ 1 */
-
-		/*
-		 * look for the "tee_" prefix in the refname, also check to see
-		 * that the relname and the refname are the same this should
-		 * eliminate any user-specified table and leave us with the tee
-		 * table entries only
-		 */
-		if ((strlen(rte->refname) < 4) ||
-			(strcmp(rte->relname, rte->refname) != 0))
-			continue;
-		StrNCpy(prefix, rte->refname, 5);
-		if (strcmp(prefix, "tee_") == 0)
-		{
-			/* okay, we found a tee node entry in the range table */
-
-			/* find the appropriate plan in the teeInfo list */
-			tplan = NULL;
-			for (i = 0; i < teeInfo->num; i++)
-			{
-				if (strcmp(teeInfo->val[i].tpi_relName,
-						   rte->refname) == 0)
-					tplan = teeInfo->val[i].tpi_plan;
-			}
-			if (tplan == NULL)
-				elog(WARNING, "replaceTeeScans didn't find the corresponding tee plan");
-
-			/*
-			 * replace the sequential scan node with that var number with
-			 * the tee plan node
-			 */
-			replaceSeqScan(plan, NULL, rt_ind, tplan);
-		}
-	}
-
-	return plan;
-}
-
-
-#endif   /* TIOGA */
diff --git a/src/backend/commands/_deadcode/version.c b/src/backend/commands/_deadcode/version.c
deleted file mode 100644
index a88247e684b..00000000000
--- a/src/backend/commands/_deadcode/version.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * version.c
- *	  This file contains all the rules that govern all version semantics.
- *
- * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *	The version stuff has not been tested under postgres95 and probably
- *	doesn't work! - jolly 8/19/95
- *
- *
- *	$Id: version.c,v 1.30 2002/06/20 20:29:27 momjian Exp $
- *
- * NOTES
- *	At the point the version is defined, 2 physical relations are created
- *	<vname>_added and <vname>_deleted.
- *
- *	In addition, 4 rules are defined which govern the semantics of
- *	versions w.r.t retrieves, appends, replaces and deletes.
- *
- *-------------------------------------------------------------------------
- */
-
-#include "postgres.h"
-
-
-#define MAX_QUERY_LEN 1024
-
-char		rule_buf[MAX_QUERY_LEN];
-
-/*
- * problem: the version system assumes that the rules it declares will
- *			be fired in the order of declaration, it also assumes
- *			goh's silly instead semantics.  Unfortunately, it is a pain
- *			to make the version system work with the new semantics.
- *			However the whole problem can be solved, and some nice
- *			functionality can be achieved if we get multiple action rules
- *			to work.  So thats what I did						-- glass
- *
- * Well, at least they've been working for about 20 minutes.
- *
- * So any comments in this code about 1 rule per transction are false...:)
- *
- */
-
-/*
- *	This is needed because the rule system only allows
- *	*1* rule to be defined per transaction.
- *
- * NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- *
- * DONT DO THAT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- *
- * If you commit the current Xact all the palloced memory GOES AWAY
- * and could be re-palloced in the new Xact and the whole hell breaks
- * loose and poor people like me spend 2 hours of their live chassing
- * a strange memory bug instead of watching the "Get Smart" marathon
- * in NICK !
- * DO NOT COMMIT THE XACT, just increase the Cid counter!
- *														_sp.
- */
-#ifdef NOT_USED
-static void
-eval_as_new_xact(char *query)
-{
-
-	/*------
-	 * WARNING! do not uncomment the following lines WARNING!
-	 *
-	 *	CommitTransactionCommand();
-	 *	StartTransactionCommand();
-	 *------
-	 */
-	CommandCounterIncrement();
-	pg_exec_query(query);
-}
-#endif
-/*
- *	Define a version.
- */
-#ifdef NOT_USED
-void
-DefineVersion(char *name, char *fromRelname, char *date)
-{
-	char	   *bname;
-	static char saved_basename[512];
-	static char saved_snapshot[512];
-
-	if (date == NULL)
-	{
-		/* no time ranges */
-		bname = fromRelname;
-		strcpy(saved_basename, (char *) bname);
-		*saved_snapshot = (char) NULL;
-	}
-	else
-	{
-		/* version is a snapshot */
-		bname = fromRelname;
-		strcpy(saved_basename, (char *) bname);
-		sprintf(saved_snapshot, "['%s']", date);
-	}
-
-
-	/*
-	 * Calls the routine ``GetAttrList'' get the list of attributes from
-	 * the base relation. Code is put here so that we only need to look up
-	 * the attribute once for both appends and replaces.
-	 */
-	setAttrList(bname);
-
-	VersionCreate(name, saved_basename);
-	VersionAppend(name, saved_basename);
-	VersionDelete(name, saved_basename, saved_snapshot);
-	VersionReplace(name, saved_basename, saved_snapshot);
-	VersionRetrieve(name, saved_basename, saved_snapshot);
-}
-#endif
-
-/*
- *	Creates the deltas.
- */
-#ifdef NOT_USED
-void
-VersionCreate(char *vname, char *bname)
-{
-	static char query_buf[MAX_QUERY_LEN];
-
-	/*
-	 * Creating the dummy version relation for triggering rules.
-	 */
-	sprintf(query_buf, "SELECT * INTO TABLE %s from %s where 1 =2",
-			vname, bname);
-
-	pg_exec_query(query_buf);
-
-	/*
-	 * Creating the ``v_added'' relation
-	 */
-	sprintf(query_buf, "SELECT * INTO TABLE %s_added from %s where 1 = 2",
-			vname, bname);
-	eval_as_new_xact(query_buf);
-
-	/*
-	 * Creating the ``v_deleted'' relation.
-	 */
-	sprintf(query_buf, "CREATE TABLE %s_del (DOID oid)", vname);
-	eval_as_new_xact(query_buf);
-}
-#endif
-
-
-/*
- * Given the relation name, does a catalog lookup for that relation and
- * sets the global variable 'attr_list' with the list of attributes (names)
- * for that relation.
- */
-#ifdef NOT_USED
-static void
-setAttrList(char *bname)
-{
-	Relation	rel;
-	int			i = 0;
-	int			maxattrs = 0;
-	char	   *attrname;
-	char		temp_buf[512];
-	int			notfirst = 0;
-
-	rel = heap_openr(bname);
-	if (rel == NULL)
-	{
-		elog(ERROR, "Unable to expand all -- amopenr failed ");
-		return;
-	}
-	maxattrs = RelationGetNumberOfAttributes(rel);
-
-	attr_list[0] = '\0';
-
-	for (i = maxattrs - 1; i > -1; --i)
-	{
-		attrname = NameStr(rel->rd_att->attrs[i]->attname);
-
-		if (notfirst == 1)
-			sprintf(temp_buf, ", %s = new.%s", attrname, attrname);
-		else
-		{
-			sprintf(temp_buf, "%s = new.%s", attrname, attrname);
-			notfirst = 1;
-		}
-		strcat(attr_list, temp_buf);
-	}
-
-	heap_close(rel);
-
-	return;
-}
-#endif
-
-/*
- * This routine defines the rule governing the append semantics of
- * versions.  All tuples appended to a version gets appended to the
- * <vname>_added relation.
- */
-#ifdef NOT_USED
-static void
-VersionAppend(char *vname, char *bname)
-{
-	sprintf(rule_buf,
-			"define rewrite rule %s_append is on INSERT to %s do instead append %s_added(%s)",
-			vname, vname, vname, attr_list);
-
-	eval_as_new_xact(rule_buf);
-}
-#endif
-
-/*
- * This routine defines the rule governing the retrieval semantics of
- * versions.  To retrieve tuples from a version , we need to:
- *
- *		1. Retrieve all tuples in the <vname>_added relation.
- *		2. Retrieve all tuples in the base relation which are not in
- *		   the <vname>_del relation.
- */
-#ifdef NOT_USED
-void
-VersionRetrieve(char *vname, char *bname, char *snapshot)
-{
-
-	sprintf(rule_buf,
-			"define rewrite rule %s_retrieve is on SELECT to %s do instead\n\
-SELECT %s_1.oid, %s_1.* from _%s in %s%s, %s_1 in (%s_added | _%s) \
-where _%s.oid !!= '%s_del.DOID'",
-			vname, vname, vname, vname, bname,
-			bname, snapshot,
-			vname, vname, bname, bname, vname);
-
-	eval_as_new_xact(rule_buf);
-
-	/* printf("%s\n",rule_buf); */
-
-}
-#endif
-
-/*
- * This routine defines the rules that govern the delete semantics of
- * versions. Two things happens when we delete a tuple from a version:
- *
- *	   1. If the tuple to be deleted was added to the version *after*
- *		  the version was created, then we simply delete the tuple
- *		  from the <vname>_added relation.
- *	   2. If the tuple to be deleted is actually in the base relation,
- *		  then we have to mark that tuple as being deleted by adding
- *		  it to the <vname>_del relation.
- */
-#ifdef NOT_USED
-void
-VersionDelete(char *vname, char *bname, char *snapshot)
-{
-
-	sprintf(rule_buf,
-			"define rewrite rule %s_delete1 is on delete to %s do instead\n \
-[delete %s_added where current.oid = %s_added.oid\n \
- append %s_del(DOID = current.oid) from _%s in %s%s \
- where current.oid = _%s.oid] \n",
-			vname, vname, vname, vname, vname,
-			bname, bname, snapshot, bname);
-
-	eval_as_new_xact(rule_buf);
-#ifdef OLD_REWRITE
-	sprintf(rule_buf,
-			"define rewrite rule %s_delete2 is on delete to %s do instead \n \
-    append %s_del(DOID = current.oid) from _%s in %s%s \
-    where current.oid = _%s.oid \n",
-			vname, vname, vname, bname, bname, snapshot, bname);
-
-	eval_as_new_xact(rule_buf);
-#endif   /* OLD_REWRITE */
-}
-#endif
-
-/*
- *	This routine defines the rules that govern the update semantics
- *	of versions. To update a tuple in a version:
- *
- *		1. If the tuple is in <vname>_added, we simply ``replace''
- *		   the tuple (as per postgres style).
- *		2. if the tuple is in the base relation, then two things have to
- *		   happen:
- *		   2.1	The tuple is marked ``deleted'' from the base relation by
- *				adding the tuple to the <vname>_del relation.
- *		   2.2	A copy of the tuple is appended to the <vname>_added relation
- */
-#ifdef NOT_USED
-void
-VersionReplace(char *vname, char *bname, char *snapshot)
-{
-	sprintf(rule_buf,
-			"define rewrite rule %s_replace1 is on replace to %s do instead \n\
-[replace %s_added(%s) where current.oid = %s_added.oid \n\
- append %s_del(DOID = current.oid) from _%s in %s%s \
- where current.oid = _%s.oid\n\
- append %s_added(%s) from _%s in %s%s \
- where current.oid !!= '%s_added.oid' and current.oid = _%s.oid]\n",
-			vname, vname, vname, attr_list, vname,
-			vname, bname, bname, snapshot, bname,
-			vname, attr_list, bname, bname, snapshot, vname, bname);
-
-	eval_as_new_xact(rule_buf);
-
-/*	printf("%s\n",rule_buf); */
-#ifdef OLD_REWRITE
-	sprintf(rule_buf,
-			"define rewrite rule %s_replace2 is on replace to %s do \n\
-    append %s_del(DOID = current.oid) from _%s in %s%s \
-    where current.oid = _%s.oid\n",
-			vname, vname, vname, bname, bname, snapshot, bname);
-
-	eval_as_new_xact(rule_buf);
-
-	sprintf(rule_buf,
-			"define rewrite rule %s_replace3 is on replace to %s do instead\n\
-    append %s_added(%s) from _%s in %s%s \
-    where current.oid !!= '%s_added.oid' and current.oid = \
-    _%s.oid\n",
-	vname, vname, vname, attr_list, bname, bname, snapshot, vname, bname);
-
-	eval_as_new_xact(rule_buf);
-#endif   /* OLD_REWRITE */
-/*	printf("%s\n",rule_buf); */
-
-}
-
-#endif
diff --git a/src/backend/executor/_deadcode/nodeTee.c b/src/backend/executor/_deadcode/nodeTee.c
deleted file mode 100644
index e02f8cb59f5..00000000000
--- a/src/backend/executor/_deadcode/nodeTee.c
+++ /dev/null
@@ -1,499 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * nodeTee.c
- *
- *
- * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *	 DESCRIPTION
- *		This code provides support for a tee node, which allows
- *		multiple parent in a megaplan.
- *
- *	 INTERFACE ROUTINES
- *		ExecTee
- *		ExecInitTee
- *		ExecEndTee
- *
- *	$Id: nodeTee.c,v 1.12 2002/06/20 20:29:28 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-
-#include <sys/types.h>
-#include <sys/file.h>
-#include "postgres.h"
-
-#include "access/heapam.h"
-#include "catalog/catalog.h"
-#include "catalog/heap.h"
-#include "executor/executor.h"
-#include "executor/nodeTee.h"
-#include "optimizer/internal.h"
-#include "storage/bufmgr.h"
-#include "storage/smgr.h"
-#include "tcop/pquery.h"
-#include "utils/relcache.h"
-
-/* ------------------------------------------------------------------
- *		ExecInitTee
- *
- *		Create tee state
- *
- * ------------------------------------------------------------------
- */
-bool
-ExecInitTee(Tee * node, EState *currentEstate, Plan *parent)
-{
-	TeeState   *teeState;
-	Plan	   *outerPlan;
-	int			len;
-	Relation	bufferRel;
-	TupleDesc	tupType;
-	EState	   *estate;
-
-	/*
-	 * it is possible that the Tee has already been initialized since it
-	 * can be reached by multiple parents. If it is already initialized,
-	 * simply return and do not initialize the children nodes again
-	 */
-	if (node->plan.state)
-		return TRUE;
-
-	/*
-	 * assign the node's execution state
-	 */
-
-	/*
-	 * make a new executor state, because we have a different
-	 * es_range_table
-	 */
-
-/*	   node->plan.state = estate;*/
-
-	estate = CreateExecutorState();
-	estate->es_direction = currentEstate->es_direction;
-	estate->es_BaseId = currentEstate->es_BaseId;
-	estate->es_BaseId = currentEstate->es_BaseId;
-	estate->es_tupleTable = currentEstate->es_tupleTable;
-	estate->es_refcount = currentEstate->es_refcount;
-	estate->es_junkFilter = currentEstate->es_junkFilter;
-	estate->es_snapshot = currentEstate->es_snapshot;
-
-	/*
-	 * use the range table for Tee subplan since the range tables for the
-	 * two parents may be different
-	 */
-	if (node->rtentries)
-		estate->es_range_table = node->rtentries;
-	else
-		estate->es_range_table = currentEstate->es_range_table;
-
-	node->plan.state = estate;
-
-
-	/*
-	 * create teeState structure
-	 */
-	teeState = makeNode(TeeState);
-	teeState->tee_leftPlace = 0;
-	teeState->tee_rightPlace = 0;
-	teeState->tee_lastPlace = 0;
-	teeState->tee_bufferRel = NULL;
-	teeState->tee_leftScanDesc = NULL;
-	teeState->tee_rightScanDesc = NULL;
-
-
-	node->teestate = teeState;
-
-	/* ----------------
-	 *	Miscellanious initialization
-	 *
-	 *		 +	assign node's base_id
-	 *		 +	assign debugging hooks and
-	 *		 +	create expression context for node
-	 * ----------------
-	 */
-	ExecAssignNodeBaseInfo(estate, &(teeState->cstate), parent);
-	ExecAssignExprContext(estate, &(teeState->cstate));
-
-#define TEE_NSLOTS 2
-
-	/*
-	 * initialize tuple slots
-	 */
-	ExecInitResultTupleSlot(estate, &(teeState->cstate));
-
-	/* initialize child nodes */
-	outerPlan = outerPlan((Plan *) node);
-	ExecInitNode(outerPlan, estate, (Plan *) node);
-
-	/*
-	 * the tuple type info is from the outer plan of this node the result
-	 * type is also the same as the outerplan
-	 */
-	ExecAssignResultTypeFromOuterPlan((Plan *) node, &(teeState->cstate));
-	ExecAssignProjectionInfo((Plan *) node, &teeState->cstate);
-
-	/*
-	 * initialize temporary relation to buffer tuples
-	 */
-	tupType = ExecGetResultType(&(teeState->cstate));
-	len = ExecTargetListLength(((Plan *) node)->targetlist);
-
-	/*
-	 * create a catalogued relation even though this is a temporary
-	 * relation
-	 */
-	/* cleanup of catalogued relations is easier to do */
-
-	if (node->teeTableName[0] != '\0')
-	{
-		Relation	r;
-
-		teeState->tee_bufferRelname = pstrdup(node->teeTableName);
-
-		/*
-		 * we are given an tee table name, if a relation by that name
-		 * exists, then we open it, else we create it and then open it
-		 */
-		r = RelationNameGetRelation(teeState->tee_bufferRelname);
-
-		if (RelationIsValid(r))
-			bufferRel = heap_openr(teeState->tee_bufferRelname);
-		else
-			bufferRel = heap_open(
-					heap_create_with_catalog(teeState->tee_bufferRelname,
-									  tupType, RELKIND_RELATION, false));
-	}
-	else
-	{
-		sprintf(teeState->tee_bufferRelname,
-				"ttemp_%d",		/* 'ttemp' for 'tee' temporary */
-				newoid());
-		bufferRel = heap_open(
-					heap_create_with_catalog(teeState->tee_bufferRelname,
-									  tupType, RELKIND_RELATION, false));
-	}
-
-	teeState->tee_bufferRel = bufferRel;
-
-	/*
-	 * initialize a memory context for allocating thing like scan
-	 * descriptors
-	 */
-
-	/*
-	 * we do this so that on cleanup of the tee, we can free things. if we
-	 * didn't have our own memory context, we would be in the memory
-	 * context of the portal that we happen to be using at the moment
-	 */
-
-	teeState->tee_mcxt = (MemoryContext) CreateGlobalMemory(teeState->tee_bufferRelname);
-
-	/*
-	 * don't initialize the scan descriptors here because it's not good to
-	 * initialize scan descriptors on empty rels. Wait until the scan
-	 * descriptors are needed before initializing them.
-	 */
-
-	teeState->tee_leftScanDesc = NULL;
-	teeState->tee_rightScanDesc = NULL;
-
-	return TRUE;
-}
-
-int
-ExecCountSlotsTee(Tee * node)
-{
-	/* Tee nodes can't have innerPlans */
-	return ExecCountSlotsNode(outerPlan(node)) + TEE_NSLOTS;
-}
-
-/* ----------------------------------------------------------------
-   initTeeScanDescs
-	  initializes the left and right scandescs on the temporary
-	  relation of a Tee node
-
-	  must open two separate scan descriptors,
-	  because the left and right scans may be at different points
-* ----------------------------------------------------------------
-*/
-static void
-initTeeScanDescs(Tee * node)
-{
-	TeeState   *teeState;
-	Relation	bufferRel;
-	ScanDirection dir;
-	Snapshot	snapshot;
-	MemoryContext orig;
-
-	teeState = node->teestate;
-	if (teeState->tee_leftScanDesc && teeState->tee_rightScanDesc)
-		return;
-
-	orig = CurrentMemoryContext;
-	MemoryContextSwitchTo(teeState->tee_mcxt);
-
-	bufferRel = teeState->tee_bufferRel;
-	dir = ((Plan *) node)->state->es_direction; /* backwards not handled
-												 * yet XXX */
-	snapshot = ((Plan *) node)->state->es_snapshot;
-
-	if (teeState->tee_leftScanDesc == NULL)
-	{
-		teeState->tee_leftScanDesc = heap_beginscan(bufferRel,
-											ScanDirectionIsBackward(dir),
-													snapshot,
-													0,	/* num scan keys */
-													NULL		/* scan keys */
-			);
-	}
-	if (teeState->tee_rightScanDesc == NULL)
-	{
-		teeState->tee_rightScanDesc = heap_beginscan(bufferRel,
-											ScanDirectionIsBackward(dir),
-													 snapshot,
-													 0, /* num scan keys */
-													 NULL		/* scan keys */
-			);
-	}
-
-	MemoryContextSwitchTo(orig);
-}
-
-/* ----------------------------------------------------------------
- *		ExecTee(node)
- *
- *
- *		A Tee serves to connect a subplan to multiple parents.
- *		the subplan is always the outplan of the Tee node.
- *
- *		The Tee gets requests from either leftParent or rightParent,
- *		fetches the result tuple from the child, and then
- *		stored the result into a temporary relation (serving as a queue).
- *		leftPlace and rightPlace keep track of where the left and rightParents
- *		are.
- *		If a parent requests a tuple and that parent is not at the end
- *		of the temporary relation, then the request is satisfied from
- *		the queue instead of by executing the child plan
- *
- * ----------------------------------------------------------------
- */
-
-TupleTableSlot *
-ExecTee(Tee * node, Plan *parent)
-{
-	EState	   *estate;
-	TeeState   *teeState;
-	int			leftPlace,
-				rightPlace,
-				lastPlace;
-	int			branch;
-	TupleTableSlot *result;
-	TupleTableSlot *slot;
-	Plan	   *childNode;
-	ScanDirection dir;
-	HeapTuple	heapTuple;
-	Relation	bufferRel;
-	HeapScanDesc scanDesc;
-
-	estate = ((Plan *) node)->state;
-	teeState = node->teestate;
-	leftPlace = teeState->tee_leftPlace;
-	rightPlace = teeState->tee_rightPlace;
-	lastPlace = teeState->tee_lastPlace;
-	bufferRel = teeState->tee_bufferRel;
-
-	childNode = outerPlan(node);
-
-	dir = estate->es_direction;
-
-	/* XXX doesn't handle backwards direction yet */
-
-	if (parent == node->leftParent)
-		branch = leftPlace;
-	else if ((parent == node->rightParent) || (parent == (Plan *) node))
-
-		/*
-		 * the tee node could be the root node of the plan, in which case,
-		 * we treat it like a right-parent pull
-		 */
-		branch = rightPlace;
-	else
-	{
-		elog(ERROR, "A Tee node can only be executed from its left or right parent\n");
-		return NULL;
-	}
-
-	if (branch == lastPlace)
-	{							/* we're at the end of the queue already,
-								 * - get a new tuple from the child plan,
-								 * - store it in the queue, - increment
-								 * lastPlace, - increment leftPlace or
-								 * rightPlace as appropriate, - and return
-								 * result */
-		slot = ExecProcNode(childNode, (Plan *) node);
-		if (!TupIsNull(slot))
-		{
-			/*
-			 * heap_insert changes something...
-			 */
-			if (slot->ttc_buffer != InvalidBuffer)
-				heapTuple = heap_copytuple(slot->val);
-			else
-				heapTuple = slot->val;
-
-			/* insert into temporary relation */
-			heap_insert(bufferRel, heapTuple);
-
-			if (slot->ttc_buffer != InvalidBuffer)
-				heap_freetuple(heapTuple);
-
-			/*
-			 * once there is data in the temporary relation, ensure that
-			 * the left and right scandescs are initialized
-			 */
-			initTeeScanDescs(node);
-
-			scanDesc = (parent == node->leftParent) ?
-				teeState->tee_leftScanDesc : teeState->tee_rightScanDesc;
-
-			{
-				/*
-				 * move the scandesc forward so we don't re-read this
-				 * tuple later
-				 */
-				HeapTuple	throwAway;
-
-				/* Buffer buffer; */
-				throwAway = heap_getnext(scanDesc, ScanDirectionIsBackward(dir));
-			}
-
-			/*
-			 * set the shouldFree field of the child's slot so that when
-			 * the child's slot is free'd, this tuple isn't free'd also
-			 */
-
-			/*
-			 * does this mean this tuple has to be garbage collected
-			 * later??
-			 */
-			slot->ttc_shouldFree = false;
-
-			teeState->tee_lastPlace = lastPlace + 1;
-		}
-		result = slot;
-	}
-	else
-	{							/* the desired data already exists in the
-								 * temporary relation */
-		scanDesc = (parent == node->leftParent) ?
-			teeState->tee_leftScanDesc : teeState->tee_rightScanDesc;
-
-		heapTuple = heap_getnext(scanDesc, ScanDirectionIsBackward(dir));
-
-		/*
-		 * Increase the pin count on the buffer page, because the tuple
-		 * stored in the slot also points to it (as well as the scan
-		 * descriptor). If we don't, ExecStoreTuple will decrease the pin
-		 * count on the next iteration.
-		 */
-
-		if (scanDesc->rs_cbuf != InvalidBuffer)
-			IncrBufferRefCount(scanDesc->rs_cbuf);
-
-		slot = teeState->cstate.cs_ResultTupleSlot;
-		slot->ttc_tupleDescriptor = RelationGetDescr(bufferRel);
-
-		result = ExecStoreTuple(heapTuple,		/* tuple to store */
-								slot,	/* slot to store in */
-								scanDesc->rs_cbuf,		/* this tuple's buffer */
-								false); /* don't free stuff from
-										 * heap_getnext */
-
-	}
-
-	if (parent == node->leftParent)
-		teeState->tee_leftPlace = leftPlace + 1;
-	else
-		teeState->tee_rightPlace = rightPlace + 1;
-
-	return result;
-}
-
-/* ---------------------------------------------------------------------
- *		ExecEndTee
- *
- *	 End the Tee node, and free up any storage
- * since a Tee node can be downstream of multiple parent nodes,
- * only free when both parents are done
- * --------------------------------------------------------------------
- */
-
-void
-ExecEndTee(Tee * node, Plan *parent)
-{
-	EState	   *estate;
-	TeeState   *teeState;
-	int			leftPlace,
-				rightPlace,
-				lastPlace;
-	Relation	bufferRel;
-	MemoryContext orig;
-
-	estate = ((Plan *) node)->state;
-	teeState = node->teestate;
-	leftPlace = teeState->tee_leftPlace;
-	rightPlace = teeState->tee_rightPlace;
-	lastPlace = teeState->tee_lastPlace;
-
-	if (!node->leftParent || parent == node->leftParent)
-		leftPlace = -1;
-
-	if (!node->rightParent || parent == node->rightParent)
-		rightPlace = -1;
-
-	if (parent == (Plan *) node)
-		rightPlace = leftPlace = -1;
-
-	teeState->tee_leftPlace = leftPlace;
-	teeState->tee_rightPlace = rightPlace;
-	if ((leftPlace == -1) && (rightPlace == -1))
-	{
-		/* remove the temporary relations */
-		/* and close the scan descriptors */
-
-		bufferRel = teeState->tee_bufferRel;
-		if (bufferRel)
-		{
-			heap_drop(bufferRel);
-			teeState->tee_bufferRel = NULL;
-			if (teeState->tee_mcxt)
-			{
-				orig = CurrentMemoryContext;
-				MemoryContextSwitchTo(teeState->tee_mcxt);
-			}
-			else
-				orig = 0;
-
-			if (teeState->tee_leftScanDesc)
-			{
-				heap_endscan(teeState->tee_leftScanDesc);
-				teeState->tee_leftScanDesc = NULL;
-			}
-			if (teeState->tee_rightScanDesc)
-			{
-				heap_endscan(teeState->tee_rightScanDesc);
-				teeState->tee_rightScanDesc = NULL;
-			}
-
-			if (teeState->tee_mcxt)
-			{
-				MemoryContextSwitchTo(orig);
-				teeState->tee_mcxt = NULL;
-			}
-		}
-	}
-
-}
diff --git a/src/backend/optimizer/path/_deadcode/predmig.c b/src/backend/optimizer/path/_deadcode/predmig.c
deleted file mode 100644
index 5ce4083ab56..00000000000
--- a/src/backend/optimizer/path/_deadcode/predmig.c
+++ /dev/null
@@ -1,810 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * predmig.c
- *
- *
- * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/_deadcode/Attic/predmig.c,v 1.15 2002/06/20 20:29:30 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-/*
-** DESCRIPTION
-** Main Routines to handle Predicate Migration (i.e. correct optimization
-** of queries with expensive functions.)
-**
-**	  The reasoning behind some of these algorithms is rather detailed.
-** Have a look at Sequoia Tech Report 92/13 for more info.	Also
-** see Monma and Sidney's paper "Sequencing with Series-Parallel
-** Precedence Constraints", in "Mathematics of Operations Research",
-** volume 4 (1979),  pp. 215-224.
-**
-**	  The main thing that this code does that wasn't handled in xfunc.c is
-** it considers the possibility that two joins in a stream may not
-** be ordered by ascending rank -- in such a scenario, it may be optimal
-** to pullup more restrictions than we did via xfunc_try_pullup.
-**
-**	  This code in some sense generalizes xfunc_try_pullup; if you
-** run postgres -x noprune, you'll turn off xfunc_try_pullup, and this
-** code will do everything that xfunc_try_pullup would have, and maybe
-** more.  However, this results in no pruning, which may slow down the
-** optimizer and/or cause the system to run out of memory.
-**										   -- JMH, 11/13/92
-*/
-
-#include "nodes/pg_list.h"
-#include "nodes/nodes.h"
-#include "nodes/primnodes.h"
-#include "nodes/relation.h"
-#include "optimizer/pathnode.h"
-#include "optimizer/internal.h"
-#include "optimizer/cost.h"
-#include "optimizer/keys.h"
-#include "optimizer/tlist.h"
-
-#define is_clause(node) (get_cinfo(node))		/* a stream node
-												 * represents a clause
-												 * (not a join) iff it has
-												 * a non-NULL cinfo field */
-
-static void xfunc_predmig(JoinPath pathnode, Stream streamroot,
-			  Stream laststream, bool *progressp);
-static bool xfunc_series_llel(Stream stream);
-static bool xfunc_llel_chains(Stream root, Stream bottom);
-static Stream xfunc_complete_stream(Stream stream);
-static bool xfunc_prdmig_pullup(Stream origstream, Stream pullme,
-					JoinPath joinpath);
-static void xfunc_form_groups(Stream root, Stream bottom);
-static void xfunc_free_stream(Stream root);
-static Stream xfunc_add_clauses(Stream current);
-static void xfunc_setup_group(Stream node, Stream bottom);
-static Stream xfunc_streaminsert(RestrictInfo restrictinfo, Stream current,
-				   int clausetype);
-static int	xfunc_num_relids(Stream node);
-static StreamPtr xfunc_get_downjoin(Stream node);
-static StreamPtr xfunc_get_upjoin(Stream node);
-static Stream xfunc_stream_qsort(Stream root, Stream bottom);
-static int	xfunc_stream_compare(void *arg1, void *arg2);
-static bool xfunc_check_stream(Stream node);
-static bool xfunc_in_stream(Stream node, Stream stream);
-
-/* -----------------	 MAIN FUNCTIONS ------------------------ */
-/*
-** xfunc_do_predmig
-**	  wrapper for Predicate Migration.	It calls xfunc_predmig until no
-** more progress is made.
-**	  return value says if any changes were ever made.
-*/
-bool
-xfunc_do_predmig(Path root)
-{
-	bool		progress,
-				changed = false;
-
-	if (is_join(root))
-		do
-		{
-			progress = false;
-			Assert(IsA(root, JoinPath));
-			xfunc_predmig((JoinPath) root, (Stream) NULL, (Stream) NULL,
-						  &progress);
-			if (changed && progress)
-				elog(DEBUG, "Needed to do a second round of predmig!\n");
-			if (progress)
-				changed = true;
-		} while (progress);
-	return changed;
-}
-
-
-/*
- ** xfunc_predmig
- **  The main routine for Predicate Migration.	It traverses a join tree,
- ** and for each root-to-leaf path in the plan tree it constructs a
- ** "Stream", which it passes to xfunc_series_llel for optimization.
- ** Destructively modifies the join tree (via predicate pullup).
- */
-static void
-xfunc_predmig(JoinPath pathnode,	/* root of the join tree */
-			  Stream streamroot,
-			  Stream laststream,/* for recursive calls -- these are the
-								 * root of the stream under construction,
-								 * and the lowest node created so far */
-			  bool *progressp)
-{
-	Stream		newstream;
-
-	/*
-	 * * traverse the join tree dfs-style, constructing a stream as you
-	 * go. * When you hit a scan node, pass the stream off to
-	 * xfunc_series_llel.
-	 */
-
-	/* sanity check */
-	if ((!streamroot && laststream) ||
-		(streamroot && !laststream))
-		elog(ERROR, "called xfunc_predmig with bad inputs");
-	if (streamroot)
-		Assert(xfunc_check_stream(streamroot));
-
-	/* add path node to stream */
-	newstream = RMakeStream();
-	if (!streamroot)
-		streamroot = newstream;
-	set_upstream(newstream, (StreamPtr) laststream);
-	if (laststream)
-		set_downstream(laststream, (StreamPtr) newstream);
-	set_downstream(newstream, (StreamPtr) NULL);
-	set_pathptr(newstream, (pathPtr) pathnode);
-	set_cinfo(newstream, (RestrictInfo) NULL);
-	set_clausetype(newstream, XFUNC_UNKNOWN);
-
-	/* base case: we're at a leaf, call xfunc_series_llel */
-	if (!is_join(pathnode))
-	{
-		/* form a fleshed-out copy of the stream */
-		Stream		fullstream = xfunc_complete_stream(streamroot);
-
-		/* sort it via series-llel */
-		if (xfunc_series_llel(fullstream))
-			*progressp = true;
-
-		/* free up the copy */
-		xfunc_free_stream(fullstream);
-	}
-	else
-	{
-		/* visit left child */
-		xfunc_predmig((JoinPath) get_outerjoinpath(pathnode),
-					  streamroot, newstream, progressp);
-
-		/* visit right child */
-		xfunc_predmig((JoinPath) get_innerjoinpath(pathnode),
-					  streamroot, newstream, progressp);
-	}
-
-	/* remove this node */
-	if (get_upstream(newstream))
-		set_downstream((Stream) get_upstream(newstream), (StreamPtr) NULL);
-	pfree(newstream);
-}
-
-/*
- ** xfunc_series_llel
- **    A flavor of Monma and Sidney's Series-Parallel algorithm.
- ** Traverse stream downwards.	When you find a node with restrictions on it,
- ** call xfunc_llel_chains on the substream from root to that node.
- */
-static bool
-xfunc_series_llel(Stream stream)
-{
-	Stream		temp,
-				next;
-	bool		progress = false;
-
-	for (temp = stream; temp != (Stream) NULL; temp = next)
-	{
-		next = (Stream) xfunc_get_downjoin(temp);
-
-		/*
-		 * * if there are restrictions/secondary join clauses above this *
-		 * node, call xfunc_llel_chains
-		 */
-		if (get_upstream(temp) && is_clause((Stream) get_upstream(temp)))
-			if (xfunc_llel_chains(stream, temp))
-				progress = true;
-	}
-	return progress;
-}
-
-/*
- ** xfunc_llel_chains
- **    A flavor of Monma and Sidney's Parallel Chains algorithm.
- ** Given a stream which has been well-ordered except for its lowermost
- ** restrictions/2-ary joins, pull up the restrictions/2-arys as appropriate.
- ** What that means here is to form groups in the chain above the lowest
- ** join node above bottom inclusive, and then take all the restrictions
- ** following bottom, and try to pull them up as far as possible.
- */
-static bool
-xfunc_llel_chains(Stream root, Stream bottom)
-{
-	bool		progress = false;
-	Stream		origstream;
-	Stream		tmpstream,
-				pathstream;
-	Stream		rootcopy = root;
-
-	Assert(xfunc_check_stream(root));
-
-	/* xfunc_prdmig_pullup will need an unmodified copy of the stream */
-	origstream = (Stream) copyObject((Node) root);
-
-	/* form groups among ill-ordered nodes */
-	xfunc_form_groups(root, bottom);
-
-	/* sort chain by rank */
-	Assert(xfunc_in_stream(bottom, root));
-	rootcopy = xfunc_stream_qsort(root, bottom);
-
-	/*
-	 * * traverse sorted stream -- if any restriction has moved above a
-	 * join, * we must pull it up in the plan.	That is, make plan tree *
-	 * reflect order of sorted stream.
-	 */
-	for (tmpstream = rootcopy,
-		 pathstream = (Stream) xfunc_get_downjoin(rootcopy);
-		 tmpstream != (Stream) NULL && pathstream != (Stream) NULL;
-		 tmpstream = (Stream) get_downstream(tmpstream))
-	{
-		if (is_clause(tmpstream)
-			&& get_pathptr(pathstream) != get_pathptr(tmpstream))
-		{
-			/*
-			 * * If restriction moved above a Join after sort, we pull it *
-			 * up in the join plan. *	 If restriction moved down, we
-			 * ignore it. * This is because Joey's Sequoia paper proves
-			 * that * restrictions should never move down.	If this * one
-			 * were moved down, it would violate "semantic correctness", *
-			 * i.e. it would be lower than the attributes it references.
-			 */
-			Assert(xfunc_num_relids(pathstream) > xfunc_num_relids(tmpstream));
-			progress = xfunc_prdmig_pullup(origstream, tmpstream,
-									 (JoinPath) get_pathptr(pathstream));
-		}
-		if (get_downstream(tmpstream))
-			pathstream = (Stream) xfunc_get_downjoin((Stream) get_downstream(tmpstream));
-	}
-
-	/* free up origstream */
-	xfunc_free_stream(origstream);
-	return progress;
-}
-
-/*
- ** xfunc_complete_stream
- **   Given a stream composed of join nodes only, make a copy containing the
- ** join nodes along with the associated restriction nodes.
- */
-static Stream
-xfunc_complete_stream(Stream stream)
-{
-	Stream		tmpstream,
-				copystream,
-				curstream = (Stream) NULL;
-
-	copystream = (Stream) copyObject((Node) stream);
-	Assert(xfunc_check_stream(copystream));
-
-	curstream = copystream;
-	Assert(!is_clause(curstream));
-
-	/* curstream = (Stream)xfunc_get_downjoin(curstream); */
-
-	while (curstream != (Stream) NULL)
-	{
-		xfunc_add_clauses(curstream);
-		curstream = (Stream) xfunc_get_downjoin(curstream);
-	}
-
-	/* find top of stream and return it */
-	for (tmpstream = copystream; get_upstream(tmpstream) != (StreamPtr) NULL;
-		 tmpstream = (Stream) get_upstream(tmpstream))
-		 /* no body in for loop */ ;
-
-	return tmpstream;
-}
-
-/*
- ** xfunc_prdmig_pullup
- **    pullup a clause in a path above joinpath.  Since the JoinPath tree
- ** doesn't have upward pointers, it's difficult to deal with.	Thus we
- ** require the original stream, which maintains pointers to all the path
- ** nodes.	We use the original stream to find out what joins are
- ** above the clause.
- */
-static bool
-xfunc_prdmig_pullup(Stream origstream, Stream pullme, JoinPath joinpath)
-{
-	RestrictInfo restrictinfo = get_cinfo(pullme);
-	bool		progress = false;
-	Stream		upjoin,
-				orignode,
-				temp;
-	int			whichchild;
-
-	/* find node in origstream that contains clause */
-	for (orignode = origstream;
-		 orignode != (Stream) NULL
-		 && get_cinfo(orignode) != restrictinfo;
-		 orignode = (Stream) get_downstream(orignode))
-		 /* empty body in for loop */ ;
-	if (!orignode)
-		elog(ERROR, "Didn't find matching node in original stream");
-
-
-	/* pull up this node as far as it should go */
-	for (upjoin = (Stream) xfunc_get_upjoin(orignode);
-		 upjoin != (Stream) NULL
-		 && (JoinPath) get_pathptr((Stream) xfunc_get_downjoin(upjoin))
-		 != joinpath;
-		 upjoin = (Stream) xfunc_get_upjoin(upjoin))
-	{
-#ifdef DEBUG
-		elog(DEBUG, "pulling up in xfunc_predmig_pullup!");
-#endif
-		/* move clause up in path */
-		if (get_pathptr((Stream) get_downstream(upjoin))
-		  == (pathPtr) get_outerjoinpath((JoinPath) get_pathptr(upjoin)))
-			whichchild = OUTER;
-		else
-			whichchild = INNER;
-		restrictinfo = xfunc_pullup((Path) get_pathptr((Stream) get_downstream(upjoin)),
-									(JoinPath) get_pathptr(upjoin),
-									restrictinfo,
-									whichchild,
-									get_clausetype(orignode));
-		set_pathptr(pullme, get_pathptr(upjoin));
-		/* pullme has been moved into locrestrictinfo */
-		set_clausetype(pullme, XFUNC_LOCPRD);
-
-		/*
-		 * * xfunc_pullup makes new path nodes for children of *
-		 * get_pathptr(current). We must modify the stream nodes to point *
-		 * to these path nodes
-		 */
-		if (whichchild == OUTER)
-		{
-			for (temp = (Stream) get_downstream(upjoin); is_clause(temp);
-				 temp = (Stream) get_downstream(temp))
-				set_pathptr
-					(temp, (pathPtr)
-					 get_outerjoinpath((JoinPath) get_pathptr(upjoin)));
-			set_pathptr
-				(temp,
-			(pathPtr) get_outerjoinpath((JoinPath) get_pathptr(upjoin)));
-		}
-		else
-		{
-			for (temp = (Stream) get_downstream(upjoin); is_clause(temp);
-				 temp = (Stream) get_downstream(temp))
-				set_pathptr
-					(temp, (pathPtr)
-					 get_innerjoinpath((JoinPath) get_pathptr(upjoin)));
-			set_pathptr
-				(temp, (pathPtr)
-				 get_innerjoinpath((JoinPath) get_pathptr(upjoin)));
-		}
-		progress = true;
-	}
-	if (!progress)
-		elog(DEBUG, "didn't succeed in pulling up in xfunc_prdmig_pullup");
-	return progress;
-}
-
-/*
- ** xfunc_form_groups
- **    A group is a pair of stream nodes a,b such that a is constrained to
- ** precede b (for instance if a and b are both joins), but rank(a) > rank(b).
- ** In such a situation, Monma and Sidney prove that no clauses should end
- ** up between a and b, and therefore we may treat them as a group, with
- ** selectivity equal to the product of their selectivities, and cost
- ** equal to the cost of the first plus the selectivity of the first times the
- ** cost of the second.  We define each node to be in a group by itself,
- ** and then repeatedly find adjacent groups which are ordered by descending
- ** rank, and make larger groups.  You know that two adjacent nodes are in a
- ** group together if the lower has groupup set to true.  They will both have
- ** the same groupcost and groupsel (since they're in the same group!)
- */
-static void
-xfunc_form_groups(Query *queryInfo, Stream root, Stream bottom)
-{
-	Stream		temp,
-				parent;
-	int			lowest = xfunc_num_relids((Stream) xfunc_get_upjoin(bottom));
-	bool		progress;
-	LispValue	primjoin;
-	int			whichchild;
-
-	if (!lowest)
-		return;					/* no joins in stream, so no groups */
-
-	/* initialize groups to be single nodes */
-	for (temp = root;
-		 temp != (Stream) NULL && temp != bottom;
-		 temp = (Stream) get_downstream(temp))
-	{
-		/* if a Join node */
-		if (!is_clause(temp))
-		{
-			if (get_pathptr((Stream) get_downstream(temp))
-			== (pathPtr) get_outerjoinpath((JoinPath) get_pathptr(temp)))
-				whichchild = OUTER;
-			else
-				whichchild = INNER;
-			set_groupcost(temp,
-						  xfunc_join_expense((JoinPath) get_pathptr(temp),
-											 whichchild));
-			if (primjoin = xfunc_primary_join((JoinPath) get_pathptr(temp)))
-			{
-				set_groupsel(temp,
-							 compute_clause_selec(queryInfo,
-												  primjoin, NIL));
-			}
-			else
-				set_groupsel(temp, 1.0);
-		}
-		else
-/* a restriction, or 2-ary join pred */
-		{
-			set_groupcost(temp,
-						  xfunc_expense(queryInfo,
-										get_clause(get_cinfo(temp))));
-			set_groupsel(temp,
-						 compute_clause_selec(queryInfo,
-											  get_clause(get_cinfo(temp)),
-											  NIL));
-		}
-		set_groupup(temp, false);
-	}
-
-	/* make passes upwards, forming groups */
-	do
-	{
-		progress = false;
-		for (temp = (Stream) get_upstream(bottom);
-			 temp != (Stream) NULL;
-			 temp = (Stream) get_upstream(temp))
-		{
-			/* check for grouping with node upstream */
-			if (!get_groupup(temp) &&	/* not already grouped */
-				(parent = (Stream) get_upstream(temp)) != (Stream) NULL &&
-			/* temp is a join or temp is the top of a group */
-				(is_join((Path) get_pathptr(temp)) ||
-				 get_downstream(temp) &&
-				 get_groupup((Stream) get_downstream(temp))) &&
-				get_grouprank(parent) < get_grouprank(temp))
-			{
-				progress = true;	/* we formed a new group */
-				set_groupup(temp, true);
-				set_groupcost(temp,
-							  get_groupcost(temp) +
-							  get_groupsel(temp) * get_groupcost(parent));
-				set_groupsel(temp, get_groupsel(temp) * get_groupsel(parent));
-
-				/* fix costs and sels of all members of group */
-				xfunc_setup_group(temp, bottom);
-			}
-		}
-	} while (progress);
-}
-
-
-/* -------------------									   UTILITY FUNCTIONS	 ------------------------- */
-
-/*
- ** xfunc_free_stream
- **   walk down a stream and pfree it
- */
-static void
-xfunc_free_stream(Stream root)
-{
-	Stream		cur,
-				next;
-
-	Assert(xfunc_check_stream(root));
-
-	if (root != (Stream) NULL)
-		for (cur = root; cur != (Stream) NULL; cur = next)
-		{
-			next = (Stream) get_downstream(cur);
-			pfree(cur);
-		}
-}
-
-/*
- ** xfunc_add<_clauses
- **    find any clauses above current, and insert them into stream as
- ** appropriate.  Return uppermost clause inserted, or current if none.
- */
-static Stream
-xfunc_add_clauses(Stream current)
-{
-	Stream		topnode = current;
-	LispValue	temp;
-	LispValue	primjoin;
-
-	/* first add in the local clauses */
-	foreach(temp, get_loc_restrictinfo((Path) get_pathptr(current)))
-	{
-		topnode = xfunc_streaminsert((RestrictInfo) lfirst(temp), topnode,
-									 XFUNC_LOCPRD);
-	}
-
-	/* and add in the join clauses */
-	if (IsA(get_pathptr(current), JoinPath))
-	{
-		primjoin = xfunc_primary_join((JoinPath) get_pathptr(current));
-		foreach(temp, get_pathrestrictinfo((JoinPath) get_pathptr(current)))
-		{
-			if (!equal(get_clause((RestrictInfo) lfirst(temp)), primjoin))
-				topnode = xfunc_streaminsert((RestrictInfo) lfirst(temp), topnode,
-											 XFUNC_JOINPRD);
-		}
-	}
-	return topnode;
-}
-
-
-/*
- ** xfunc_setup_group
- **   find all elements of stream that are grouped with node and are above
- ** bottom, and set their groupcost and groupsel to be the same as node's.
- */
-static void
-xfunc_setup_group(Stream node, Stream bottom)
-{
-	Stream		temp;
-
-	if (node != bottom)
-		/* traverse downwards */
-		for (temp = (Stream) get_downstream(node);
-			 temp != (Stream) NULL && temp != bottom;
-			 temp = (Stream) get_downstream(temp))
-		{
-			if (!get_groupup(temp))
-				break;
-			else
-			{
-				set_groupcost(temp, get_groupcost(node));
-				set_groupsel(temp, get_groupsel(node));
-			}
-		}
-
-	/* traverse upwards */
-	for (temp = (Stream) get_upstream(node); temp != (Stream) NULL;
-		 temp = (Stream) get_upstream(temp))
-	{
-		if (!get_groupup((Stream) get_downstream(temp)))
-			break;
-		else
-		{
-			set_groupcost(temp, get_groupcost(node));
-			set_groupsel(temp, get_groupsel(node));
-		}
-	}
-}
-
-
-/*
- ** xfunc_streaminsert
- **    Make a new Stream node to hold clause, and insert it above current.
- ** Return new node.
- */
-static Stream
-xfunc_streaminsert(RestrictInfo restrictinfo,
-				   Stream current,
-				   int clausetype)		/* XFUNC_LOCPRD or XFUNC_JOINPRD */
-{
-	Stream		newstream = RMakeStream();
-
-	set_upstream(newstream, get_upstream(current));
-	if (get_upstream(current))
-		set_downstream((Stream) (get_upstream(current)), (StreamPtr) newstream);
-	set_upstream(current, (StreamPtr) newstream);
-	set_downstream(newstream, (StreamPtr) current);
-	set_pathptr(newstream, get_pathptr(current));
-	set_cinfo(newstream, restrictinfo);
-	set_clausetype(newstream, clausetype);
-	return newstream;
-}
-
-/*
- ** Given a Stream node, find the number of relids referenced in the pathnode
- ** associated with the stream node.  The number of relids gives a unique
- ** ordering on the joins in a stream, which we use to compare the height of
- ** join nodes.
- */
-static int
-xfunc_num_relids(Stream node)
-{
-	if (!node || !IsA(get_pathptr(node), JoinPath))
-		return 0;
-	else
-		return (length
-				(get_relids(get_parent((JoinPath) get_pathptr(node)))));
-}
-
-/*
- ** xfunc_get_downjoin
- **    Given a stream node, find the next lowest node which points to a
- ** join predicate or a scan node.
- */
-static StreamPtr
-xfunc_get_downjoin(Stream node)
-{
-	Stream		temp;
-
-	if (!is_clause(node))		/* if this is a join */
-		node = (Stream) get_downstream(node);
-	for (temp = node; temp && is_clause(temp);
-		 temp = (Stream) get_downstream(temp))
-		 /* empty body in for loop */ ;
-
-	return (StreamPtr) temp;
-}
-
-/*
- ** xfunc_get_upjoin
- **   same as above, but upwards.
- */
-static StreamPtr
-xfunc_get_upjoin(Stream node)
-{
-	Stream		temp;
-
-	if (!is_clause(node))		/* if this is a join */
-		node = (Stream) get_upstream(node);
-	for (temp = node; temp && is_clause(temp);
-		 temp = (Stream) get_upstream(temp))
-		 /* empty body in for loop */ ;
-
-	return (StreamPtr) temp;
-}
-
-/*
- ** xfunc_stream_qsort
- **   Given a stream, sort by group rank the elements in the stream from the
- ** node "bottom" up.  DESTRUCTIVELY MODIFIES STREAM!  Returns new root.
- */
-static Stream
-xfunc_stream_qsort(Stream root, Stream bottom)
-{
-	int			i;
-	size_t		num;
-	Stream	   *nodearray,
-				output;
-	Stream		tmp;
-
-	/* find size of list */
-	for (num = 0, tmp = root; tmp != bottom;
-		 tmp = (Stream) get_downstream(tmp))
-		num++;
-	if (num <= 1)
-		return root;
-
-	/* copy elements of the list into an array */
-	nodearray = (Stream *) palloc(num * sizeof(Stream));
-
-	for (tmp = root, i = 0; tmp != bottom;
-		 tmp = (Stream) get_downstream(tmp), i++)
-		nodearray[i] = tmp;
-
-	/* sort the array */
-	qsort(nodearray, num, sizeof(LispValue), xfunc_stream_compare);
-
-	/* paste together the array elements */
-	output = nodearray[num - 1];
-	set_upstream(output, (StreamPtr) NULL);
-	for (i = num - 2; i >= 0; i--)
-	{
-		set_downstream(nodearray[i + 1], (StreamPtr) nodearray[i]);
-		set_upstream(nodearray[i], (StreamPtr) nodearray[i + 1]);
-	}
-	set_downstream(nodearray[0], (StreamPtr) bottom);
-	if (bottom)
-		set_upstream(bottom, (StreamPtr) nodearray[0]);
-
-	Assert(xfunc_check_stream(output));
-	return output;
-}
-
-/*
- ** xfunc_stream_compare
- **    comparison function for xfunc_stream_qsort.
- ** Compare nodes by group rank.  If group ranks are equal, ensure that
- ** join nodes appear in same order as in plan tree.
- */
-static int
-xfunc_stream_compare(void *arg1, void *arg2)
-{
-	Stream		stream1 = *(Stream *) arg1;
-	Stream		stream2 = *(Stream *) arg2;
-	Cost		rank1,
-				rank2;
-
-	rank1 = get_grouprank(stream1);
-	rank2 = get_grouprank(stream2);
-
-	if (rank1 > rank2)
-		return 1;
-	else if (rank1 < rank2)
-		return -1;
-	else
-	{
-		if (is_clause(stream1) && is_clause(stream2))
-			return 0;			/* doesn't matter what order if both are
-								 * restrictions */
-		else if (!is_clause(stream1) && !is_clause(stream2))
-		{
-			if (xfunc_num_relids(stream1) < xfunc_num_relids(stream2))
-				return -1;
-			else
-				return 1;
-		}
-		else if (is_clause(stream1) && !is_clause(stream2))
-		{
-			if (xfunc_num_relids(stream1) == xfunc_num_relids(stream2))
-				/* stream1 is a restriction over stream2 */
-				return 1;
-			else
-				return -1;
-		}
-		else if (!is_clause(stream1) && is_clause(stream2))
-		{
-			/* stream2 is a restriction over stream1: never push down */
-			return -1;
-		}
-	}
-}
-
-/* ------------------  DEBUGGING ROUTINES ---------------------------- */
-
-/*
- ** Make sure all pointers in stream make sense.  Make sure no joins are
- ** out of order.
- */
-static bool
-xfunc_check_stream(Stream node)
-{
-	Stream		temp;
-	int			numrelids,
-				tmp;
-
-	/* set numrelids higher than max */
-	if (!is_clause(node))
-		numrelids = xfunc_num_relids(node) + 1;
-	else if (xfunc_get_downjoin(node))
-		numrelids = xfunc_num_relids((Stream) xfunc_get_downjoin(node)) + 1;
-	else
-		numrelids = 1;
-
-	for (temp = node; get_downstream(temp); temp = (Stream) get_downstream(temp))
-	{
-		if ((Stream) get_upstream((Stream) get_downstream(temp)) != temp)
-		{
-			elog(ERROR, "bad pointers in stream");
-			return false;
-		}
-		if (!is_clause(temp))
-		{
-			if ((tmp = xfunc_num_relids(temp)) >= numrelids)
-			{
-				elog(ERROR, "Joins got reordered!");
-				return false;
-			}
-			numrelids = tmp;
-		}
-	}
-
-	return true;
-}
-
-/*
- ** xfunc_in_stream
- **   check if node is in stream
- */
-static bool
-xfunc_in_stream(Stream node, Stream stream)
-{
-	Stream		temp;
-
-	for (temp = stream; temp; temp = (Stream) get_downstream(temp))
-		if (temp == node)
-			return 1;
-	return 0;
-}
diff --git a/src/backend/optimizer/path/_deadcode/xfunc.c b/src/backend/optimizer/path/_deadcode/xfunc.c
deleted file mode 100644
index 80087652c79..00000000000
--- a/src/backend/optimizer/path/_deadcode/xfunc.c
+++ /dev/null
@@ -1,1479 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * xfunc.c
- *	  Utility routines to handle expensive function optimization.
- *	  Includes xfunc_trypullup(), which attempts early pullup of predicates
- *	  to allow for maximal pruning.
- *
- * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/_deadcode/Attic/xfunc.c,v 1.19 2002/06/20 20:29:30 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-#include <math.h>
-
-#ifdef HAVE_VALUES_H
-#include <values.h>
-#endif
-
-#include "postgres.h"
-
-#include "access/heapam.h"
-#include "access/htup.h"
-#include "catalog/pg_language.h"
-#include "catalog/pg_proc.h"
-#include "catalog/pg_type.h"
-#include "lib/lispsort.h"
-#include "nodes/nodes.h"
-#include "nodes/pg_list.h"
-#include "nodes/primnodes.h"
-#include "nodes/relation.h"
-#include "optimizer/clauses.h"
-#include "optimizer/cost.h"
-#include "optimizer/internal.h"
-#include "optimizer/keys.h"
-#include "optimizer/pathnode.h"
-#include "optimizer/tlist.h"
-#include "storage/buf_internals.h"
-#include "tcop/dest.h"
-#include "utils/syscache.h"
-
-#define ever ; 1 ;
-
-/* local funcs */
-static int xfunc_card_unreferenced(Query *queryInfo,
-						Expr *clause, Relids referenced);
-
-*/
-
-/*
-** xfunc_trypullup
-**	  Preliminary pullup of predicates, to allow for maximal pruning.
-** Given a relation, check each of its paths and see if you can
-** pullup clauses from its inner and outer.
-*/
-
-void
-xfunc_trypullup(RelOptInfo rel)
-{
-	LispValue	y;				/* list ptr */
-	RestrictInfo maxcinfo;		/* The RestrictInfo to pull up, as
-								 * calculated by xfunc_shouldpull() */
-	JoinPath	curpath;		/* current path in list */
-	int			progress;		/* has progress been made this time
-								 * through? */
-	int			clausetype;
-
-	do
-	{
-		progress = false;		/* no progress yet in this iteration */
-		foreach(y, get_pathlist(rel))
-		{
-			curpath = (JoinPath) lfirst(y);
-
-			/*
-			 * * for each operand, attempt to pullup predicates until
-			 * first * failure.
-			 */
-			for (ever)
-			{
-				/* No, the following should NOT be '=='  !! */
-				if (clausetype = xfunc_shouldpull((Path) get_innerjoinpath(curpath),
-											  curpath, INNER, &maxcinfo))
-				{
-
-					xfunc_pullup((Path) get_innerjoinpath(curpath),
-								 curpath, maxcinfo, INNER, clausetype);
-					progress = true;
-				}
-				else
-					break;
-			}
-			for (ever)
-			{
-
-				/* No, the following should NOT be '=='  !! */
-				if (clausetype = xfunc_shouldpull((Path) get_outerjoinpath(curpath),
-											  curpath, OUTER, &maxcinfo))
-				{
-
-					xfunc_pullup((Path) get_outerjoinpath(curpath),
-								 curpath, maxcinfo, OUTER, clausetype);
-					progress = true;
-				}
-				else
-					break;
-			}
-
-			/*
-			 * * make sure the unpruneable flag bubbles up, i.e. * if
-			 * anywhere below us in the path pruneable is false, * then
-			 * pruneable should be false here
-			 */
-			if (get_pruneable(get_parent(curpath)) &&
-				(!get_pruneable(get_parent
-								((Path) get_innerjoinpath(curpath))) ||
-				 !get_pruneable(get_parent((Path)
-										   get_outerjoinpath(curpath)))))
-			{
-
-				set_pruneable(get_parent(curpath), false);
-				progress = true;
-			}
-		}
-	} while (progress);
-}
-
-/*
- ** xfunc_shouldpull
- **    find clause with highest rank, and decide whether to pull it up
- ** from child to parent.  Currently we only pullup secondary join clauses
- ** that are in the pathrestrictinfo.  Secondary hash and sort clauses are
- ** left where they are.
- **    If we find an expensive function but decide *not* to pull it up,
- ** we'd better set the unpruneable flag.  -- JMH, 11/11/92
- **
- ** Returns:  0 if nothing left to pullup
- **			  XFUNC_LOCPRD if a local predicate is to be pulled up
- **			  XFUNC_JOINPRD if a secondary join predicate is to be pulled up
- */
-int
-xfunc_shouldpull(Query *queryInfo,
-				 Path childpath,
-				 JoinPath parentpath,
-				 int whichchild,
-				 RestrictInfo *maxcinfopt)		/* Out: pointer to clause
-												 * to pullup */
-{
-	LispValue	clauselist,
-				tmplist;		/* lists of clauses */
-	RestrictInfo maxcinfo;		/* clause to pullup */
-	LispValue	primjoinclause	/* primary join clause */
-	= xfunc_primary_join(parentpath);
-	Cost		tmprank,
-				maxrank = (-1 * MAXFLOAT);		/* ranks of clauses */
-	Cost		joinselec = 0;	/* selectivity of the join predicate */
-	Cost		joincost = 0;	/* join cost + primjoinclause cost */
-	int			retval = XFUNC_LOCPRD;
-
-	clauselist = get_loc_restrictinfo(childpath);
-
-	if (clauselist != LispNil)
-	{
-		/* find local predicate with maximum rank */
-		for (tmplist = clauselist,
-			 maxcinfo = (RestrictInfo) lfirst(tmplist),
-			 maxrank = xfunc_rank(get_clause(maxcinfo));
-			 tmplist != LispNil;
-			 tmplist = lnext(tmplist))
-		{
-
-			if ((tmprank = xfunc_rank(get_clause((RestrictInfo) lfirst(tmplist))))
-				> maxrank)
-			{
-				maxcinfo = (RestrictInfo) lfirst(tmplist);
-				maxrank = tmprank;
-			}
-		}
-	}
-
-	/*
-	 * * If child is a join path, and there are multiple join clauses, *
-	 * see if any join clause has even higher rank than the highest *
-	 * local predicate
-	 */
-	if (is_join(childpath) && xfunc_num_join_clauses((JoinPath) childpath) > 1)
-		for (tmplist = get_pathrestrictinfo((JoinPath) childpath);
-			 tmplist != LispNil;
-			 tmplist = lnext(tmplist))
-		{
-
-			if (tmplist != LispNil &&
-				(tmprank = xfunc_rank(get_clause((RestrictInfo) lfirst(tmplist))))
-				> maxrank)
-			{
-				maxcinfo = (RestrictInfo) lfirst(tmplist);
-				maxrank = tmprank;
-				retval = XFUNC_JOINPRD;
-			}
-		}
-	if (maxrank == (-1 * MAXFLOAT))		/* no expensive clauses */
-		return 0;
-
-	/*
-	 * * Pullup over join if clause is higher rank than join, or if * join
-	 * is nested loop and current path is inner child (note that *
-	 * restrictions on the inner of a nested loop don't buy you anything
-	 * -- * you still have to scan the entire inner relation each time). *
-	 * Note that the cost of a secondary join clause is only what's *
-	 * calculated by xfunc_expense(), since the actual joining * (i.e. the
-	 * usual path_cost) is paid for by the primary join clause.
-	 */
-	if (primjoinclause != LispNil)
-	{
-		joinselec = compute_clause_selec(queryInfo, primjoinclause, LispNil);
-		joincost = xfunc_join_expense(parentpath, whichchild);
-
-		if (XfuncMode == XFUNC_PULLALL ||
-			(XfuncMode != XFUNC_WAIT &&
-			 ((joincost != 0 &&
-			   (maxrank = xfunc_rank(get_clause(maxcinfo))) >
-			   ((joinselec - 1.0) / joincost))
-			  || (joincost == 0 && joinselec < 1)
-			  || (!is_join(childpath)
-				  && (whichchild == INNER)
-				  && IsA(parentpath, NestPath)
-				  &&!IsA(parentpath, HashPath)
-				  &&!IsA(parentpath, MergePath)))))
-		{
-
-			*maxcinfopt = maxcinfo;
-			return retval;
-
-		}
-		else if (maxrank != -(MAXFLOAT))
-		{
-			/*
-			 * * we've left an expensive restriction below a join.  Since *
-			 * we may pullup this restriction in predmig.c, we'd best *
-			 * set the RelOptInfo of this join to be unpruneable
-			 */
-			set_pruneable(get_parent(parentpath), false);
-			/* and fall through */
-		}
-	}
-	return 0;
-}
-
-
-/*
- ** xfunc_pullup
- **    move clause from child pathnode to parent pathnode.	 This operation
- ** makes the child pathnode produce a larger relation than it used to.
- ** This means that we must construct a new RelOptInfo just for the childpath,
- ** although this RelOptInfo will not be added to the list of Rels to be joined up
- ** in the query; it's merely a parent for the new childpath.
- **    We also have to fix up the path costs of the child and parent.
- **
- ** Now returns a pointer to the new pulled-up RestrictInfo. -- JMH, 11/18/92
- */
-RestrictInfo
-xfunc_pullup(Query *queryInfo,
-			 Path childpath,
-			 JoinPath parentpath,
-			 RestrictInfo cinfo,	/* clause to pull up */
-			 int whichchild,	/* whether child is INNER or OUTER of join */
-			 int clausetype)	/* whether clause to pull is join or local */
-{
-	Path		newkid;
-	RelOptInfo	newrel;
-	Cost		pulled_selec;
-	Cost		cost;
-	RestrictInfo newinfo;
-
-	/* remove clause from childpath */
-	newkid = (Path) copyObject((Node) childpath);
-	if (clausetype == XFUNC_LOCPRD)
-	{
-		set_locrestrictinfo(newkid,
-							xfunc_LispRemove((LispValue) cinfo,
-								   (List) get_loc_restrictinfo(newkid)));
-	}
-	else
-	{
-		set_pathrestrictinfo
-			((JoinPath) newkid,
-			 xfunc_LispRemove((LispValue) cinfo,
-						(List) get_pathrestrictinfo((JoinPath) newkid)));
-	}
-
-	/*
-	 * * give the new child path its own RelOptInfo node that reflects the *
-	 * lack of the pulled-up predicate
-	 */
-	pulled_selec = compute_clause_selec(queryInfo,
-										get_clause(cinfo), LispNil);
-	xfunc_copyrel(get_parent(newkid), &newrel);
-	set_parent(newkid, newrel);
-	set_pathlist(newrel, makeList1(newkid));
-	set_unorderedpath(newrel, (PathPtr) newkid);
-	set_cheapestpath(newrel, (PathPtr) newkid);
-	set_size(newrel,
-		(Count) ((Cost) get_size(get_parent(childpath)) / pulled_selec));
-
-	/*
-	 * * fix up path cost of newkid.  To do this we subtract away all the *
-	 * xfunc_costs of childpath, then recompute the xfunc_costs of newkid
-	 */
-	cost = get_path_cost(newkid) - xfunc_get_path_cost(childpath);
-	Assert(cost >= 0);
-	set_path_cost(newkid, cost);
-	cost = get_path_cost(newkid) + xfunc_get_path_cost(newkid);
-	set_path_cost(newkid, cost);
-
-	/*
-	 * * We copy the cinfo, since it may appear in other plans, and we're
-	 * going * to munge it.  -- JMH, 7/22/92
-	 */
-	newinfo = (RestrictInfo) copyObject((Node) cinfo);
-
-	/*
-	 * * Fix all vars in the clause * to point to the right varno and
-	 * varattno in parentpath
-	 */
-	xfunc_fixvars(get_clause(newinfo), newrel, whichchild);
-
-	/* add clause to parentpath, and fix up its cost. */
-	set_locrestrictinfo(parentpath,
-						lispCons((LispValue) newinfo,
-						  (LispValue) get_loc_restrictinfo(parentpath)));
-	/* put new childpath into the path tree */
-	if (whichchild == INNER)
-		set_innerjoinpath(parentpath, (pathPtr) newkid);
-	else
-		set_outerjoinpath(parentpath, (pathPtr) newkid);
-
-	/*
-	 * * recompute parentpath cost from scratch -- the cost * of the join
-	 * method has changed
-	 */
-	cost = xfunc_total_path_cost(parentpath);
-	set_path_cost(parentpath, cost);
-
-	return newinfo;
-}
-
-/*
- ** calculate (selectivity-1)/cost.
- */
-Cost
-xfunc_rank(Query *queryInfo, LispValue clause)
-{
-	Cost		selec = compute_clause_selec(queryInfo, clause, LispNil);
-	Cost		cost = xfunc_expense(queryInfo, clause);
-
-	if (cost == 0)
-		if (selec > 1)
-			return MAXFLOAT;
-		else
-			return -(MAXFLOAT);
-	return (selec - 1) / cost;
-}
-
-/*
- ** Find the "global" expense of a clause; i.e. the local expense divided
- ** by the cardinalities of all the base relations of the query that are *not*
- ** referenced in the clause.
- */
-Cost
-xfunc_expense(Query *queryInfo, clause)
-LispValue	clause;
-{
-	Cost		cost = xfunc_local_expense(clause);
-
-	if (cost)
-	{
-		Count		card = xfunc_card_unreferenced(queryInfo, clause, LispNil);
-
-		if (card)
-			cost /= card;
-	}
-
-	return cost;
-}
-
-/*
- ** xfunc_join_expense
- **    Find global expense of a join clause
- */
-Cost
-xfunc_join_expense(Query *queryInfo, JoinPath path, int whichchild)
-{
-	LispValue	primjoinclause = xfunc_primary_join(path);
-
-	/*
-	 * * the second argument to xfunc_card_unreferenced reflects all the *
-	 * relations involved in the join clause, i.e. all the relids in the
-	 * RelOptInfo * of the join clause
-	 */
-	Count		card = 0;
-	Cost		cost = xfunc_expense_per_tuple(path, whichchild);
-
-	card = xfunc_card_unreferenced(queryInfo,
-								   primjoinclause,
-								   get_relids(get_parent(path)));
-	if (primjoinclause)
-		cost += xfunc_local_expense(primjoinclause);
-
-	if (card)
-		cost /= card;
-
-	return cost;
-}
-
-/*
- ** Recursively find the per-tuple expense of a clause.  See
- ** xfunc_func_expense for more discussion.
- */
-Cost
-xfunc_local_expense(LispValue clause)
-{
-	Cost		cost = 0;		/* running expense */
-	LispValue	tmpclause;
-
-	/* First handle the base case */
-	if (IsA(clause, Const) ||IsA(clause, Var) ||IsA(clause, Param))
-		return 0;
-	/* now other stuff */
-	else if (IsA(clause, Iter))
-		/* Too low. Should multiply by the expected number of iterations. */
-		return xfunc_local_expense(get_iterexpr((Iter) clause));
-	else if (IsA(clause, ArrayRef))
-		return xfunc_local_expense(get_refexpr((ArrayRef) clause));
-	else if (fast_is_clause(clause))
-		return (xfunc_func_expense((LispValue) get_op(clause),
-								   (LispValue) get_opargs(clause)));
-	else if (fast_is_funcclause(clause))
-		return (xfunc_func_expense((LispValue) get_function(clause),
-								   (LispValue) get_funcargs(clause)));
-	else if (fast_not_clause(clause))
-		return xfunc_local_expense(lsecond(clause));
-	else if (fast_or_clause(clause) || fast_and_clause(clause))
-	{
-		/* find cost of evaluating each disjunct */
-		for (tmpclause = lnext(clause); tmpclause != LispNil;
-			 tmpclause = lnext(tmpclause))
-			cost += xfunc_local_expense(lfirst(tmpclause));
-		return cost;
-	}
-	else
-	{
-		elog(ERROR, "Clause node of undetermined type");
-		return -1;
-	}
-}
-
-/*
- ** xfunc_func_expense
- **    given a Func or Oper and its args, find its expense.
- ** Note: in Stonebraker's SIGMOD '91 paper, he uses a more complicated metric
- ** than the one here.	We can ignore the expected number of tuples for
- ** our calculations; we just need the per-tuple expense.  But he also
- ** proposes components to take into account the costs of accessing disk and
- ** archive.  We didn't adopt that scheme here; eventually the vacuum
- ** cleaner should be able to tell us what percentage of bytes to find on
- ** which storage level, and that should be multiplied in appropriately
- ** in the cost function below.  Right now we don't model the cost of
- ** accessing secondary or tertiary storage, since we don't have sufficient
- ** stats to do it right.
- */
-Cost
-xfunc_func_expense(LispValue node, LispValue args)
-{
-	HeapTuple	tupl;			/* the pg_proc tuple for each function */
-	Form_pg_proc proc;			/* a data structure to hold the pg_proc
-								 * tuple */
-	int			width = 0;		/* byte width of the field referenced by
-								 * each clause */
-	RegProcedure funcid;		/* ID of function associate with node */
-	Cost		cost = 0;		/* running expense */
-	LispValue	tmpclause;
-	LispValue	operand;		/* one operand of an operator */
-
-	if (IsA(node, Oper))
-	{
-		/* don't trust the opid in the Oper node.  Use the opno. */
-		if (!(funcid = get_opcode(get_opno((Oper) node))))
-			elog(ERROR, "Oper's function is undefined");
-	}
-	else
-		funcid = get_funcid((Func) node);
-
-	/* look up tuple in cache */
-	tupl = SearchSysCacheTuple(PROCOID,
-							   ObjectIdGetDatum(funcid),
-							   0, 0, 0);
-	if (!HeapTupleIsValid(tupl))
-		elog(ERROR, "Cache lookup failed for procedure %u", funcid);
-	proc = (Form_pg_proc) GETSTRUCT(tupl);
-
-	/*
-	 * * if it's a Postquel function, its cost is stored in the *
-	 * associated plan.
-	 */
-	if (proc->prolang == SQLlanguageId)
-	{
-		LispValue	tmpplan;
-		List		planlist;
-
-		if (IsA(node, Oper) ||get_func_planlist((Func) node) == LispNil)
-		{
-			Oid		   *argOidVect;		/* vector of argtypes */
-			char	   *pq_src; /* text of PQ function */
-			int			nargs;	/* num args to PQ function */
-			QueryTreeList *queryTree_list;		/* dummy variable */
-
-			/*
-			 * * plan the function, storing it in the Func node for later *
-			 * use by the executor.
-			 */
-			pq_src = (char *) textout(&(proc->prosrc));
-			nargs = proc->pronargs;
-			if (nargs > 0)
-				argOidVect = proc->proargtypes;
-			planlist = (List) pg_parse_and_plan(pq_src, argOidVect, nargs,
-										   &parseTree_list, None, FALSE);
-			if (IsA(node, Func))
-				set_func_planlist((Func) node, planlist);
-
-		}
-		else
-		{						/* plan has been cached inside the Func
-								 * node already */
-			planlist = get_func_planlist((Func) node);
-		}
-
-		/*
-		 * * Return the sum of the costs of the plans (the PQ function *
-		 * may have many queries in its body).
-		 */
-		foreach(tmpplan, planlist)
-			cost += get_cost((Plan) lfirst(tmpplan));
-		return cost;
-	}
-	else
-	{							/* it's a C function */
-
-		/*
-		 * *  find the cost of evaluating the function's arguments *  and
-		 * the width of the operands
-		 */
-		for (tmpclause = args; tmpclause != LispNil;
-			 tmpclause = lnext(tmpclause))
-		{
-
-			if ((operand = lfirst(tmpclause)) != LispNil)
-			{
-				cost += xfunc_local_expense(operand);
-				width += xfunc_width(operand);
-			}
-		}
-
-		/*
-		 * * when stats become available, add in cost of accessing
-		 * secondary * and tertiary storage here.
-		 */
-		return (cost +
-				(Cost) proc->propercall_cpu +
-		(Cost) proc->properbyte_cpu * (Cost) proc->probyte_pct / 100.00 *
-				(Cost) width
-
-		/*
-		 * Pct_of_obj_in_mem DISK_COST * proc->probyte_pct/100.00 * width
-		 * Pct_of_obj_on_disk + ARCH_COST * proc->probyte_pct/100.00 *
-		 * width Pct_of_obj_on_arch
-		 */
-			);
-	}
-}
-
-/*
- ** xfunc_width
- **    recursively find the width of a expression
- */
-
-int
-xfunc_width(LispValue clause)
-{
-	Relation	rd;				/* Relation Descriptor */
-	HeapTuple	tupl;			/* structure to hold a cached tuple */
-	Form_pg_type type;			/* structure to hold a type tuple */
-	int			retval = 0;
-
-	if (IsA(clause, Const))
-	{
-		/* base case: width is the width of this constant */
-		retval = get_constlen((Const) clause);
-		goto exit;
-	}
-	else if (IsA(clause, ArrayRef))
-	{
-		/* base case: width is width of the refelem within the array */
-		retval = get_refelemlength((ArrayRef) clause);
-		goto exit;
-	}
-	else if (IsA(clause, Var))
-	{
-		/* base case: width is width of this attribute */
-		tupl = SearchSysCacheTuple(TYPEOID,
-							 ObjectIdGetDatum(get_vartype((Var) clause)),
-								   0, 0, 0);
-		if (!HeapTupleIsValid(tupl))
-			elog(ERROR, "Cache lookup failed for type %u",
-				 get_vartype((Var) clause));
-		type = (Form_pg_type) GETSTRUCT(tupl);
-		if (get_varattno((Var) clause) == 0)
-		{
-			/* clause is a tuple.  Get its width */
-			rd = heap_open(type->typrelid);
-			retval = xfunc_tuple_width(rd);
-			heap_close(rd);
-		}
-		else
-		{
-			/* attribute is a base type */
-			retval = type->typlen;
-		}
-		goto exit;
-	}
-	else if (IsA(clause, Param))
-	{
-		if (typeidTypeRelids(get_paramtype((Param) clause)))
-		{
-			/* Param node returns a tuple.	Find its width */
-			rd = heap_open(typeidTypeRelids(get_paramtype((Param) clause)));
-			retval = xfunc_tuple_width(rd);
-			heap_close(rd);
-		}
-		else if (get_param_tlist((Param) clause) != LispNil)
-		{
-			/* Param node projects a complex type */
-			Assert(length(get_param_tlist((Param) clause)) == 1);		/* sanity */
-			retval = xfunc_width((LispValue)
-					  get_expr(lfirst(get_param_tlist((Param) clause))));
-		}
-		else
-		{
-			/* Param node returns a base type */
-			retval = typeLen(typeidType(get_paramtype((Param) clause)));
-		}
-		goto exit;
-	}
-	else if (IsA(clause, Iter))
-	{
-		/*
-		 * * An Iter returns a setof things, so return the width of a
-		 * single * thing. * Note:	THIS MAY NOT WORK RIGHT WHEN AGGS GET
-		 * FIXED, * SINCE AGG FUNCTIONS CHEW ON THE WHOLE SETOF THINGS!!!! *
-		 * This whole Iter business is bogus, anyway.
-		 */
-		retval = xfunc_width(get_iterexpr((Iter) clause));
-		goto exit;
-	}
-	else if (fast_is_clause(clause))
-	{
-		/*
-		 * * get function associated with this Oper, and treat this as * a
-		 * Func
-		 */
-		tupl = SearchSysCacheTuple(OPEROID,
-					   ObjectIdGetDatum(get_opno((Oper) get_op(clause))),
-								   0, 0, 0);
-		if (!HeapTupleIsValid(tupl))
-			elog(ERROR, "Cache lookup failed for procedure %u",
-				 get_opno((Oper) get_op(clause)));
-		return (xfunc_func_width
-		((RegProcedure) (((Form_pg_operator) (GETSTRUCT(tupl)))->oprcode),
-		 (LispValue) get_opargs(clause)));
-	}
-	else if (fast_is_funcclause(clause))
-	{
-		Func		func = (Func) get_function(clause);
-
-		if (get_func_tlist(func) != LispNil)
-		{
-			/*
-			 * this function has a projection on it.  Get the length of
-			 * the projected attribute
-			 */
-			Assert(length(get_func_tlist(func)) == 1);	/* sanity */
-			retval = xfunc_width((LispValue)
-								 get_expr(lfirst(get_func_tlist(func))));
-			goto exit;
-		}
-		else
-		{
-			return (xfunc_func_width((RegProcedure) get_funcid(func),
-									 (LispValue) get_funcargs(clause)));
-		}
-	}
-	else
-	{
-		elog(ERROR, "Clause node of undetermined type");
-		return -1;
-	}
-
-exit:
-	if (retval == -1)
-		retval = VARLEN_DEFAULT;
-	return retval;
-}
-
-/*
- ** xfunc_card_unreferenced:
- **   find all relations not referenced in clause, and multiply their
- ** cardinalities.	Ignore relation of cardinality 0.
- ** User may pass in referenced list, if they know it (useful
- ** for joins).
- */
-static Count
-xfunc_card_unreferenced(Query *queryInfo,
-						LispValue clause, Relids referenced)
-{
-	Relids		unreferenced,
-				allrelids = LispNil;
-	LispValue	temp;
-
-	/* find all relids of base relations referenced in query */
-	foreach(temp, queryInfo->base_rel_list)
-	{
-		Assert(lnext(get_relids((RelOptInfo) lfirst(temp))) == LispNil);
-		allrelids = lappend(allrelids,
-						  lfirst(get_relids((RelOptInfo) lfirst(temp))));
-	}
-
-	/* find all relids referenced in query but not in clause */
-	if (!referenced)
-		referenced = xfunc_find_references(clause);
-	unreferenced = set_difference(allrelids, referenced);
-
-	return xfunc_card_product(unreferenced);
-}
-
-/*
- ** xfunc_card_product
- **   multiple together cardinalities of a list relations.
- */
-Count
-xfunc_card_product(Query *queryInfo, Relids relids)
-{
-	LispValue	cinfonode;
-	LispValue	temp;
-	RelOptInfo	currel;
-	Cost		tuples;
-	Count		retval = 0;
-
-	foreach(temp, relids)
-	{
-		currel = get_rel(lfirst(temp));
-		tuples = get_tuples(currel);
-
-		if (tuples)
-		{						/* not of cardinality 0 */
-			/* factor in the selectivity of all zero-cost clauses */
-			foreach(cinfonode, get_restrictinfo(currel))
-			{
-				if (!xfunc_expense(queryInfo, get_clause((RestrictInfo) lfirst(cinfonode))))
-					tuples *= compute_clause_selec(queryInfo,
-							get_clause((RestrictInfo) lfirst(cinfonode)),
-												   LispNil);
-			}
-
-			if (retval == 0)
-				retval = tuples;
-			else
-				retval *= tuples;
-		}
-	}
-	if (retval == 0)
-		retval = 1;				/* saves caller from dividing by zero */
-	return retval;
-}
-
-
-/*
- ** xfunc_find_references:
- **   Traverse a clause and find all relids referenced in the clause.
- */
-List
-xfunc_find_references(LispValue clause)
-{
-	List		retval = (List) LispNil;
-	LispValue	tmpclause;
-
-	/* Base cases */
-	if (IsA(clause, Var))
-		return lispCons(lfirst(get_varid((Var) clause)), LispNil);
-	else if (IsA(clause, Const) ||IsA(clause, Param))
-		return (List) LispNil;
-
-	/* recursion */
-	else if (IsA(clause, Iter))
-
-		/*
-		 * Too low. Should multiply by the expected number of iterations.
-		 * maybe
-		 */
-		return xfunc_find_references(get_iterexpr((Iter) clause));
-	else if (IsA(clause, ArrayRef))
-		return xfunc_find_references(get_refexpr((ArrayRef) clause));
-	else if (fast_is_clause(clause))
-	{
-		/* string together result of all operands of Oper */
-		for (tmpclause = (LispValue) get_opargs(clause); tmpclause != LispNil;
-			 tmpclause = lnext(tmpclause))
-			retval = nconc(retval, xfunc_find_references(lfirst(tmpclause)));
-		return retval;
-	}
-	else if (fast_is_funcclause(clause))
-	{
-		/* string together result of all args of Func */
-		for (tmpclause = (LispValue) get_funcargs(clause);
-			 tmpclause != LispNil;
-			 tmpclause = lnext(tmpclause))
-			retval = nconc(retval, xfunc_find_references(lfirst(tmpclause)));
-		return retval;
-	}
-	else if (fast_not_clause(clause))
-		return xfunc_find_references(lsecond(clause));
-	else if (fast_or_clause(clause) || fast_and_clause(clause))
-	{
-		/* string together result of all operands of OR */
-		for (tmpclause = lnext(clause); tmpclause != LispNil;
-			 tmpclause = lnext(tmpclause))
-			retval = nconc(retval, xfunc_find_references(lfirst(tmpclause)));
-		return retval;
-	}
-	else
-	{
-		elog(ERROR, "Clause node of undetermined type");
-		return (List) LispNil;
-	}
-}
-
-/*
- ** xfunc_primary_join:
- **   Find the primary join clause: for Hash and Merge Joins, this is the
- ** min rank Hash or Merge clause, while for Nested Loop it's the
- ** min rank pathclause
- */
-LispValue
-xfunc_primary_join(JoinPath pathnode)
-{
-	LispValue	joinclauselist = get_pathrestrictinfo(pathnode);
-	RestrictInfo mincinfo;
-	LispValue	tmplist;
-	LispValue	minclause = LispNil;
-	Cost		minrank,
-				tmprank;
-
-	if (IsA(pathnode, MergePath))
-	{
-		for (tmplist = get_path_mergeclauses((MergePath) pathnode),
-			 minclause = lfirst(tmplist),
-			 minrank = xfunc_rank(minclause);
-			 tmplist != LispNil;
-			 tmplist = lnext(tmplist))
-			if ((tmprank = xfunc_rank(lfirst(tmplist)))
-				< minrank)
-			{
-				minrank = tmprank;
-				minclause = lfirst(tmplist);
-			}
-		return minclause;
-	}
-	else if (IsA(pathnode, HashPath))
-	{
-		for (tmplist = get_path_hashclauses((HashPath) pathnode),
-			 minclause = lfirst(tmplist),
-			 minrank = xfunc_rank(minclause);
-			 tmplist != LispNil;
-			 tmplist = lnext(tmplist))
-			if ((tmprank = xfunc_rank(lfirst(tmplist)))
-				< minrank)
-			{
-				minrank = tmprank;
-				minclause = lfirst(tmplist);
-			}
-		return minclause;
-	}
-
-	/* if we drop through, it's nested loop join */
-	if (joinclauselist == LispNil)
-		return LispNil;
-
-	for (tmplist = joinclauselist, mincinfo = (RestrictInfo) lfirst(joinclauselist),
-		 minrank = xfunc_rank(get_clause((RestrictInfo) lfirst(tmplist)));
-		 tmplist != LispNil;
-		 tmplist = lnext(tmplist))
-		if ((tmprank = xfunc_rank(get_clause((RestrictInfo) lfirst(tmplist))))
-			< minrank)
-		{
-			minrank = tmprank;
-			mincinfo = (RestrictInfo) lfirst(tmplist);
-		}
-	return (LispValue) get_clause(mincinfo);
-}
-
-/*
- ** xfunc_get_path_cost
- **   get the expensive function costs of the path
- */
-Cost
-xfunc_get_path_cost(Query *queryInfo, Path pathnode)
-{
-	Cost		cost = 0;
-	LispValue	tmplist;
-	Cost		selec = 1.0;
-
-	/*
-	 * * first add in the expensive local function costs. * We ensure that
-	 * the clauses are sorted by rank, so that we * know (via
-	 * selectivities) the number of tuples that will be checked * by each
-	 * function.  If we're not doing any optimization of expensive *
-	 * functions, we don't sort.
-	 */
-	if (XfuncMode != XFUNC_OFF)
-		set_locrestrictinfo(pathnode, lisp_qsort(get_loc_restrictinfo(pathnode),
-												 xfunc_cinfo_compare));
-	for (tmplist = get_loc_restrictinfo(pathnode), selec = 1.0;
-		 tmplist != LispNil;
-		 tmplist = lnext(tmplist))
-	{
-		cost += (Cost) (xfunc_local_expense(get_clause((RestrictInfo) lfirst(tmplist)))
-					  * (Cost) get_tuples(get_parent(pathnode)) * selec);
-		selec *= compute_clause_selec(queryInfo,
-							  get_clause((RestrictInfo) lfirst(tmplist)),
-									  LispNil);
-	}
-
-	/*
-	 * * Now add in any node-specific expensive function costs. * Again,
-	 * we must ensure that the clauses are sorted by rank.
-	 */
-	if (IsA(pathnode, JoinPath))
-	{
-		if (XfuncMode != XFUNC_OFF)
-			set_pathrestrictinfo((JoinPath) pathnode, lisp_qsort
-							  (get_pathrestrictinfo((JoinPath) pathnode),
-							   xfunc_cinfo_compare));
-		for (tmplist = get_pathrestrictinfo((JoinPath) pathnode), selec = 1.0;
-			 tmplist != LispNil;
-			 tmplist = lnext(tmplist))
-		{
-			cost += (Cost) (xfunc_local_expense(get_clause((RestrictInfo) lfirst(tmplist)))
-					  * (Cost) get_tuples(get_parent(pathnode)) * selec);
-			selec *= compute_clause_selec(queryInfo,
-							  get_clause((RestrictInfo) lfirst(tmplist)),
-										  LispNil);
-		}
-	}
-	if (IsA(pathnode, HashPath))
-	{
-		if (XfuncMode != XFUNC_OFF)
-			set_path_hashclauses
-				((HashPath) pathnode,
-				 lisp_qsort(get_path_hashclauses((HashPath) pathnode),
-							xfunc_clause_compare));
-		for (tmplist = get_path_hashclauses((HashPath) pathnode), selec = 1.0;
-			 tmplist != LispNil;
-			 tmplist = lnext(tmplist))
-		{
-			cost += (Cost) (xfunc_local_expense(lfirst(tmplist))
-					  * (Cost) get_tuples(get_parent(pathnode)) * selec);
-			selec *= compute_clause_selec(queryInfo,
-										  lfirst(tmplist), LispNil);
-		}
-	}
-	if (IsA(pathnode, MergePath))
-	{
-		if (XfuncMode != XFUNC_OFF)
-			set_path_mergeclauses
-				((MergePath) pathnode,
-				 lisp_qsort(get_path_mergeclauses((MergePath) pathnode),
-							xfunc_clause_compare));
-		for (tmplist = get_path_mergeclauses((MergePath) pathnode), selec = 1.0;
-			 tmplist != LispNil;
-			 tmplist = lnext(tmplist))
-		{
-			cost += (Cost) (xfunc_local_expense(lfirst(tmplist))
-					  * (Cost) get_tuples(get_parent(pathnode)) * selec);
-			selec *= compute_clause_selec(queryInfo,
-										  lfirst(tmplist), LispNil);
-		}
-	}
-	Assert(cost >= 0);
-	return cost;
-}
-
-/*
- ** Recalculate the cost of a path node.  This includes the basic cost of the
- ** node, as well as the cost of its expensive functions.
- ** We need to do this to the parent after pulling a clause from a child into a
- ** parent.  Thus we should only be calling this function on JoinPaths.
- */
-Cost
-xfunc_total_path_cost(JoinPath pathnode)
-{
-	Cost		cost = xfunc_get_path_cost((Path) pathnode);
-
-	Assert(IsA(pathnode, JoinPath));
-	if (IsA(pathnode, MergePath))
-	{
-		MergePath	mrgnode = (MergePath) pathnode;
-
-		cost += cost_mergejoin(get_path_cost((Path) get_outerjoinpath(mrgnode)),
-						get_path_cost((Path) get_innerjoinpath(mrgnode)),
-							   get_outersortkeys(mrgnode),
-							   get_innersortkeys(mrgnode),
-						   get_tuples(get_parent((Path) get_outerjoinpath
-												 (mrgnode))),
-						   get_tuples(get_parent((Path) get_innerjoinpath
-												 (mrgnode))),
-							get_width(get_parent((Path) get_outerjoinpath
-												 (mrgnode))),
-							get_width(get_parent((Path) get_innerjoinpath
-												 (mrgnode))));
-		Assert(cost >= 0);
-		return cost;
-	}
-	else if (IsA(pathnode, HashPath))
-	{
-		HashPath hashnode = (HashPath) pathnode;
-
-		cost += cost_hashjoin(get_path_cost((Path) get_outerjoinpath(hashnode)),
-					   get_path_cost((Path) get_innerjoinpath(hashnode)),
-							  get_outerhashkeys(hashnode),
-							  get_innerhashkeys(hashnode),
-						   get_tuples(get_parent((Path) get_outerjoinpath
-												 (hashnode))),
-						   get_tuples(get_parent((Path) get_innerjoinpath
-												 (hashnode))),
-							get_width(get_parent((Path) get_outerjoinpath
-												 (hashnode))),
-							get_width(get_parent((Path) get_innerjoinpath
-												 (hashnode))));
-		Assert(cost >= 0);
-		return cost;
-	}
-	else
-/* Nested Loop Join */
-	{
-		cost += cost_nestloop(get_path_cost((Path) get_outerjoinpath(pathnode)),
-					   get_path_cost((Path) get_innerjoinpath(pathnode)),
-						   get_tuples(get_parent((Path) get_outerjoinpath
-												 (pathnode))),
-						   get_tuples(get_parent((Path) get_innerjoinpath
-												 (pathnode))),
-							get_pages(get_parent((Path) get_outerjoinpath
-												 (pathnode))),
-							IsA(get_innerjoinpath(pathnode), IndexPath));
-		Assert(cost >= 0);
-		return cost;
-	}
-}
-
-
-/*
- ** xfunc_expense_per_tuple
- **    return the expense of the join *per-tuple* of the input relation.
- ** The cost model here is that a join costs
- **		k*card(outer)*card(inner) + l*card(outer) + m*card(inner) + n
- **
- ** We treat the l and m terms by considering them to be like restrictions
- ** constrained to be right under the join.  Thus the cost per inner and
- ** cost per outer of the join is different, reflecting these virtual nodes.
- **
- ** The cost per tuple of outer is k + l/referenced(inner).  Cost per tuple
- ** of inner is k + m/referenced(outer).
- ** The constants k, l, m and n depend on the join method.	Measures here are
- ** based on the costs in costsize.c, with fudging for HashJoin and Sorts to
- ** make it fit our model (the 'q' in HashJoin results in a
- ** card(outer)/card(inner) term, and sorting results in a log term.
-
- */
-Cost
-xfunc_expense_per_tuple(JoinPath joinnode, int whichchild)
-{
-	RelOptInfo	outerrel = get_parent((Path) get_outerjoinpath(joinnode));
-	RelOptInfo	innerrel = get_parent((Path) get_innerjoinpath(joinnode));
-	Count		outerwidth = get_width(outerrel);
-	Count		outers_per_page = ceil(BLCKSZ / (outerwidth + MinTupleSize));
-
-	if (IsA(joinnode, HashPath))
-	{
-		if (whichchild == INNER)
-			return (1 + cpu_page_weight) * outers_per_page / NBuffers;
-		else
-			return (((1 + cpu_page_weight) * outers_per_page / NBuffers)
-					+ cpu_page_weight
-					/ xfunc_card_product(get_relids(innerrel)));
-	}
-	else if (IsA(joinnode, MergePath))
-	{
-		/* assumes sort exists, and costs one (I/O + CPU) per tuple */
-		if (whichchild == INNER)
-			return ((2 * cpu_page_weight + 1)
-					/ xfunc_card_product(get_relids(outerrel)));
-		else
-			return ((2 * cpu_page_weight + 1)
-					/ xfunc_card_product(get_relids(innerrel)));
-	}
-	else
-/* nestloop */
-	{
-		Assert(IsA(joinnode, JoinPath));
-		return cpu_page_weight;
-	}
-}
-
-/*
- ** xfunc_fixvars
- ** After pulling up a clause, we must walk its expression tree, fixing Var
- ** nodes to point to the correct varno (either INNER or OUTER, depending
- ** on which child the clause was pulled from), and the right varattno in the
- ** target list of the child's former relation.  If the target list of the
- ** child RelOptInfo does not contain the attribute we need, we add it.
- */
-void
-xfunc_fixvars(LispValue clause, /* clause being pulled up */
-			  RelOptInfo rel,	/* rel it's being pulled from */
-			  int varno)		/* whether rel is INNER or OUTER of join */
-{
-	LispValue	tmpclause;		/* temporary variable */
-	TargetEntry *tle;			/* tlist member corresponding to var */
-
-
-	if (IsA(clause, Const) ||IsA(clause, Param))
-		return;
-	else if (IsA(clause, Var))
-	{
-		/* here's the meat */
-		tle = tlistentry_member((Var) clause, get_targetlist(rel));
-		if (tle == LispNil)
-		{
-			/*
-			 * * The attribute we need is not in the target list, * so we
-			 * have to add it. *
-			 *
-			 */
-			add_var_to_tlist(rel, (Var) clause);
-			tle = tlistentry_member((Var) clause, get_targetlist(rel));
-		}
-		set_varno(((Var) clause), varno);
-		set_varattno(((Var) clause), get_resno(get_resdom(get_entry(tle))));
-	}
-	else if (IsA(clause, Iter))
-		xfunc_fixvars(get_iterexpr((Iter) clause), rel, varno);
-	else if (fast_is_clause(clause))
-	{
-		xfunc_fixvars(lfirst(lnext(clause)), rel, varno);
-		xfunc_fixvars(lfirst(lnext(lnext(clause))), rel, varno);
-	}
-	else if (fast_is_funcclause(clause))
-		for (tmpclause = lnext(clause); tmpclause != LispNil;
-			 tmpclause = lnext(tmpclause))
-			xfunc_fixvars(lfirst(tmpclause), rel, varno);
-	else if (fast_not_clause(clause))
-		xfunc_fixvars(lsecond(clause), rel, varno);
-	else if (fast_or_clause(clause) || fast_and_clause(clause))
-		for (tmpclause = lnext(clause); tmpclause != LispNil;
-			 tmpclause = lnext(tmpclause))
-			xfunc_fixvars(lfirst(tmpclause), rel, varno);
-	else
-		elog(ERROR, "Clause node of undetermined type");
-}
-
-
-/*
- ** Comparison function for lisp_qsort() on a list of RestrictInfo's.
- ** arg1 and arg2 should really be of type (RestrictInfo *).
- */
-int
-xfunc_cinfo_compare(void *arg1, void *arg2)
-{
-	RestrictInfo info1 = *(RestrictInfo *) arg1;
-	RestrictInfo info2 = *(RestrictInfo *) arg2;
-
-	LispValue	clause1 = (LispValue) get_clause(info1),
-				clause2 = (LispValue) get_clause(info2);
-
-	return xfunc_clause_compare((void *) &clause1, (void *) &clause2);
-}
-
-/*
- ** xfunc_clause_compare: comparison function for lisp_qsort() that compares two
- ** clauses based on expense/(1 - selectivity)
- ** arg1 and arg2 are really pointers to clauses.
- */
-int
-xfunc_clause_compare(void *arg1, void *arg2)
-{
-	LispValue	clause1 = *(LispValue *) arg1;
-	LispValue	clause2 = *(LispValue *) arg2;
-	Cost		rank1,			/* total xfunc rank of clause1 */
-				rank2;			/* total xfunc rank of clause2 */
-
-	rank1 = xfunc_rank(clause1);
-	rank2 = xfunc_rank(clause2);
-
-	if (rank1 < rank2)
-		return -1;
-	else if (rank1 == rank2)
-		return 0;
-	else
-		return 1;
-}
-
-/*
- ** xfunc_disjunct_sort
- **   given a list of clauses, for each clause sort the disjuncts by cost
- **   (this assumes the predicates have been converted to Conjunctive NF)
- **   Modifies the clause list!
- */
-void
-xfunc_disjunct_sort(LispValue clause_list)
-{
-	LispValue	temp;
-
-	foreach(temp, clause_list)
-		if (or_clause(lfirst(temp)))
-		lnext(lfirst(temp)) = lisp_qsort(lnext(lfirst(temp)), xfunc_disjunct_compare);
-}
-
-
-/*
- ** xfunc_disjunct_compare: comparison function for qsort() that compares two
- ** disjuncts based on cost/selec.
- ** arg1 and arg2 are really pointers to disjuncts
- */
-int
-xfunc_disjunct_compare(Query *queryInfo, void *arg1, void *arg2)
-{
-	LispValue	disjunct1 = *(LispValue *) arg1;
-	LispValue	disjunct2 = *(LispValue *) arg2;
-	Cost		cost1,			/* total cost of disjunct1 */
-				cost2,			/* total cost of disjunct2 */
-				selec1,
-				selec2;
-	Cost		rank1,
-				rank2;
-
-	cost1 = xfunc_expense(queryInfo, disjunct1);
-	cost2 = xfunc_expense(queryInfo, disjunct2);
-	selec1 = compute_clause_selec(queryInfo,
-								  disjunct1, LispNil);
-	selec2 = compute_clause_selec(queryInfo,
-								  disjunct2, LispNil);
-
-	if (selec1 == 0)
-		rank1 = MAXFLOAT;
-	else if (cost1 == 0)
-		rank1 = 0;
-	else
-		rank1 = cost1 / selec1;
-
-	if (selec2 == 0)
-		rank2 = MAXFLOAT;
-	else if (cost2 == 0)
-		rank2 = 0;
-	else
-		rank2 = cost2 / selec2;
-
-	if (rank1 < rank2)
-		return -1;
-	else if (rank1 == rank2)
-		return 0;
-	else
-		return 1;
-}
-
-/* ------------------------ UTILITY FUNCTIONS ------------------------------- */
-/*
- ** xfunc_func_width
- **    Given a function OID and operands, find the width of the return value.
- */
-int
-xfunc_func_width(RegProcedure funcid, LispValue args)
-{
-	Relation	rd;				/* Relation Descriptor */
-	HeapTuple	tupl;			/* structure to hold a cached tuple */
-	Form_pg_proc proc;			/* structure to hold the pg_proc tuple */
-	Form_pg_type type;			/* structure to hold the pg_type tuple */
-	LispValue	tmpclause;
-	int			retval;
-
-	/* lookup function and find its return type */
-	Assert(RegProcedureIsValid(funcid));
-	tupl = SearchSysCacheTuple(PROCOID,
-							   ObjectIdGetDatum(funcid),
-							   0, 0, 0);
-	if (!HeapTupleIsValid(tupl))
-		elog(ERROR, "Cache lookup failed for procedure %u", funcid);
-	proc = (Form_pg_proc) GETSTRUCT(tupl);
-
-	/* if function returns a tuple, get the width of that */
-	if (typeidTypeRelids(proc->prorettype))
-	{
-		rd = heap_open(typeidTypeRelids(proc->prorettype));
-		retval = xfunc_tuple_width(rd);
-		heap_close(rd);
-		goto exit;
-	}
-	else
-/* function returns a base type */
-	{
-		tupl = SearchSysCacheTuple(TYPEOID,
-								   ObjectIdGetDatum(proc->prorettype),
-								   0, 0, 0);
-		if (!HeapTupleIsValid(tupl))
-			elog(ERROR, "Cache lookup failed for type %u", proc->prorettype);
-		type = (Form_pg_type) GETSTRUCT(tupl);
-		/* if the type length is known, return that */
-		if (type->typlen != -1)
-		{
-			retval = type->typlen;
-			goto exit;
-		}
-		else
-/* estimate the return size */
-		{
-			/* find width of the function's arguments */
-			for (tmpclause = args; tmpclause != LispNil;
-				 tmpclause = lnext(tmpclause))
-				retval += xfunc_width(lfirst(tmpclause));
-			/* multiply by outin_ratio */
-			retval = (int) (proc->prooutin_ratio / 100.0 * retval);
-			goto exit;
-		}
-	}
-exit:
-	return retval;
-}
-
-/*
- ** xfunc_tuple_width
- **		Return the sum of the lengths of all the attributes of a given relation
- */
-int
-xfunc_tuple_width(Relation rd)
-{
-	int			i;
-	int			retval = 0;
-	TupleDesc	tdesc = RelationGetDescr(rd);
-
-	for (i = 0; i < tdesc->natts; i++)
-	{
-		if (tdesc->attrs[i]->attlen != -1)
-			retval += tdesc->attrs[i]->attlen;
-		else
-			retval += VARLEN_DEFAULT;
-	}
-
-	return retval;
-}
-
-/*
- ** xfunc_num_join_clauses
- **   Find the number of join clauses associated with this join path
- */
-int
-xfunc_num_join_clauses(JoinPath path)
-{
-	int			num = length(get_pathrestrictinfo(path));
-
-	if (IsA(path, MergePath))
-		return num + length(get_path_mergeclauses((MergePath) path));
-	else if (IsA(path, HashPath))
-		return num + length(get_path_hashclauses((HashPath) path));
-	else
-		return num;
-}
-
-/*
- ** xfunc_LispRemove
- **   Just like LispRemove, but it whines if the item to be removed ain't there
- */
-LispValue
-xfunc_LispRemove(LispValue foo, List bar)
-{
-	LispValue	temp = LispNil;
-	LispValue	result = LispNil;
-	int			sanity = false;
-
-	for (temp = bar; !null(temp); temp = lnext(temp))
-		if (!equal((Node) (foo), (Node) (lfirst(temp))))
-			result = lappend(result, lfirst(temp));
-		else
-			sanity = true;		/* found a matching item to remove! */
-
-	if (!sanity)
-		elog(ERROR, "xfunc_LispRemove: didn't find a match!");
-
-	return result;
-}
-
-#define Node_Copy(a, b, c, d) \
-do { \
-	if (NodeCopy((Node)((a)->d), (Node*)&((b)->d), c) != true) \
-	{ \
-		return false; \
-	} \
-} while(0)
-
-/*
- ** xfunc_copyrel
- **   Just like _copyRel, but doesn't copy the paths
- */
-bool
-xfunc_copyrel(RelOptInfo from, RelOptInfo *to)
-{
-	RelOptInfo	newnode;
-
-	Pointer		(*alloc) () = palloc;
-
-	/* COPY_CHECKARGS() */
-	if (to == NULL)
-		return false;
-
-	/* COPY_CHECKNULL() */
-	if (from == NULL)
-	{
-		(*to) = NULL;
-		return true;
-	}
-
-	/* COPY_NEW(c) */
-	newnode = (RelOptInfo) (*alloc) (classSize(RelOptInfo));
-	if (newnode == NULL)
-		return false;
-
-	/*
-	 * copy node superclass fields
-	 */
-	CopyNodeFields((Node) from, (Node) newnode, alloc);
-
-	/*
-	 * copy remainder of node
-	 */
-	Node_Copy(from, newnode, alloc, relids);
-
-	newnode->indexed = from->indexed;
-	newnode->pages = from->pages;
-	newnode->tuples = from->tuples;
-	newnode->size = from->size;
-	newnode->width = from->width;
-
-	Node_Copy(from, newnode, alloc, targetlist);
-
-	/*
-	 * No!!!!	 Node_Copy(from, newnode, alloc, pathlist);
-	 * Node_Copy(from, newnode, alloc, unorderedpath); Node_Copy(from,
-	 * newnode, alloc, cheapestpath);
-	 */
-#if 0							/* can't use Node_copy now. 2/95 -ay */
-	Node_Copy(from, newnode, alloc, classlist);
-	Node_Copy(from, newnode, alloc, indexkeys);
-	Node_Copy(from, newnode, alloc, ordering);
-#endif
-	Node_Copy(from, newnode, alloc, restrictinfo);
-	Node_Copy(from, newnode, alloc, joininfo);
-	Node_Copy(from, newnode, alloc, innerjoin);
-
-	(*to) = newnode;
-	return true;
-}
diff --git a/src/include/optimizer/_deadcode/xfunc.h b/src/include/optimizer/_deadcode/xfunc.h
deleted file mode 100644
index 3bd5645f1aa..00000000000
--- a/src/include/optimizer/_deadcode/xfunc.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * xfunc.h
- *	  prototypes for xfunc.c and predmig.c.
- *
- *
- * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * $Id: xfunc.h,v 1.9 2002/06/20 20:29:51 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-#ifndef XFUNC_H
-#define XFUNC_H
-
-#include "nodes/relation.h"
-#include "utils/rel.h"
-
-/* command line arg flags */
-#define XFUNC_OFF -1			/* do no optimization of expensive preds */
-#define XFUNC_NOR 2				/* do no optimization of OR clauses */
-#define XFUNC_NOPULL 4			/* never pull restrictions above joins */
-#define XFUNC_NOPM 8			/* don't do predicate migration */
-#define XFUNC_WAIT 16			/* don't do pullup until predicate
-								 * migration */
-#define XFUNC_PULLALL 32		/* pull all expensive restrictions up,
-								 * always */
-
-/* constants for local and join predicates */
-#define XFUNC_LOCPRD 1
-#define XFUNC_JOINPRD 2
-#define XFUNC_UNKNOWN 0
-
-extern int	XfuncMode;			/* defined in tcop/postgres.c */
-
-/* default width assumed for variable length attributes */
-#define VARLEN_DEFAULT 128;
-
-/* Macro to get group rank out of group cost and group sel */
-#define get_grouprank(a) ((get_groupsel(a) - 1) / get_groupcost(a))
-
-/* Macro to see if a path node is actually a Join */
-#define is_join(pathnode) (length(get_relids(get_parent(pathnode))) > 1 ? 1 : 0)
-
-/* function prototypes from planner/path/xfunc.c */
-extern void xfunc_trypullup(RelOptInfo *rel);
-extern int xfunc_shouldpull(Path *childpath, JoinPath *parentpath,
-				 int whichchild, RestrictInfo *maxcinfopt);
-extern RestrictInfo *xfunc_pullup(Path *childpath, JoinPath *parentpath, RestrictInfo *cinfo,
-			 int whichchild, int clausetype);
-extern Cost xfunc_rank(Expr *clause);
-extern Cost xfunc_expense(Query *queryInfo, Expr *clause);
-extern Cost xfunc_join_expense(JoinPath *path, int whichchild);
-extern Cost xfunc_local_expense(Expr *clause);
-extern Cost xfunc_func_expense(Expr *node, List *args);
-extern int	xfunc_width(Expr *clause);
-
-/* static, moved to xfunc.c */
-/* extern int xfunc_card_unreferenced(Expr *clause, Relids referenced); */
-extern int	xfunc_card_product(Relids relids);
-extern List *xfunc_find_references(List *clause);
-extern List *xfunc_primary_join(JoinPath *pathnode);
-extern Cost xfunc_get_path_cost(Path *pathnode);
-extern Cost xfunc_total_path_cost(JoinPath *pathnode);
-extern Cost xfunc_expense_per_tuple(JoinPath *joinnode, int whichchild);
-extern void xfunc_fixvars(Expr *clause, RelOptInfo *rel, int varno);
-extern int	xfunc_cinfo_compare(void *arg1, void *arg2);
-extern int	xfunc_clause_compare(void *arg1, void *arg2);
-extern void xfunc_disjunct_sort(List *clause_list);
-extern int	xfunc_disjunct_compare(void *arg1, void *arg2);
-extern int	xfunc_func_width(RegProcedure funcid, List *args);
-extern int	xfunc_tuple_width(Relation rd);
-extern int	xfunc_num_join_clauses(JoinPath *path);
-extern List *xfunc_LispRemove(List *foo, List *bar);
-extern bool xfunc_copyrel(RelOptInfo *from, RelOptInfo **to);
-
-/*
- * function prototypes for path/predmig.c
- */
-extern bool xfunc_do_predmig(Path root);
-
-#endif   /* XFUNC_H */
-- 
GitLab