Remove _deadcode.
authorPeter Eisentraut
Wed, 24 Jul 2002 19:16:43 +0000 (19:16 +0000)
committerPeter Eisentraut
Wed, 24 Jul 2002 19:16:43 +0000 (19:16 +0000)
src/backend/commands/_deadcode/recipe.c [deleted file]
src/backend/commands/_deadcode/version.c [deleted file]
src/backend/executor/_deadcode/nodeTee.c [deleted file]
src/backend/optimizer/path/_deadcode/predmig.c [deleted file]
src/backend/optimizer/path/_deadcode/xfunc.c [deleted file]
src/include/optimizer/_deadcode/xfunc.h [deleted file]

diff --git a/src/backend/commands/_deadcode/recipe.c b/src/backend/commands/_deadcode/recipe.c
deleted file mode 100644 (file)
index f1b3d84..0000000
+++ /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 (file)
index a88247e..0000000
+++ /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
- * _added and _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
- * _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 _added relation.
- *     2. Retrieve all tuples in the base relation which are not in
- *        the _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 _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 _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 _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 _del relation.
- *        2.2  A copy of the tuple is appended to the _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 (file)
index e02f8cb..0000000
+++ /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 
-#include 
-#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 (file)
index 5ce4083..0000000
+++ /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 (file)
index 8008765..0000000
+++ /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 
-
-#ifdef HAVE_VALUES_H
-#include 
-#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 (file)
index 3bd5645..0000000
+++ /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 */