OSDN Git Service

Remove _deadcode.
authorPeter Eisentraut <peter_e@gmx.net>
Wed, 24 Jul 2002 19:16:43 +0000 (19:16 +0000)
committerPeter Eisentraut <peter_e@gmx.net>
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
- *     <vname>_added and <vname>_deleted.
- *
- *     In addition, 4 rules are defined which govern the semantics of
- *     versions w.r.t retrieves, appends, replaces and deletes.
- *
- *-------------------------------------------------------------------------
- */
-
-#include "postgres.h"
-
-
-#define MAX_QUERY_LEN 1024
-
-char           rule_buf[MAX_QUERY_LEN];
-
-/*
- * problem: the version system assumes that the rules it declares will
- *                     be fired in the order of declaration, it also assumes
- *                     goh's silly instead semantics.  Unfortunately, it is a pain
- *                     to make the version system work with the new semantics.
- *                     However the whole problem can be solved, and some nice
- *                     functionality can be achieved if we get multiple action rules
- *                     to work.  So thats what I did                                           -- glass
- *
- * Well, at least they've been working for about 20 minutes.
- *
- * So any comments in this code about 1 rule per transction are false...:)
- *
- */
-
-/*
- *     This is needed because the rule system only allows
- *     *1* rule to be defined per transaction.
- *
- * NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
- * OOOOOOOOOOOOOOOOOOO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- *
- * DONT DO THAT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- *
- * If you commit the current Xact all the palloced memory GOES AWAY
- * and could be re-palloced in the new Xact and the whole hell breaks
- * loose and poor people like me spend 2 hours of their live chassing
- * a strange memory bug instead of watching the "Get Smart" marathon
- * in NICK !
- * DO NOT COMMIT THE XACT, just increase the Cid counter!
- *                                                                                                             _sp.
- */
-#ifdef NOT_USED
-static void
-eval_as_new_xact(char *query)
-{
-
-       /*------
-        * WARNING! do not uncomment the following lines WARNING!
-        *
-        *      CommitTransactionCommand();
-        *      StartTransactionCommand();
-        *------
-        */
-       CommandCounterIncrement();
-       pg_exec_query(query);
-}
-#endif
-/*
- *     Define a version.
- */
-#ifdef NOT_USED
-void
-DefineVersion(char *name, char *fromRelname, char *date)
-{
-       char       *bname;
-       static char saved_basename[512];
-       static char saved_snapshot[512];
-
-       if (date == NULL)
-       {
-               /* no time ranges */
-               bname = fromRelname;
-               strcpy(saved_basename, (char *) bname);
-               *saved_snapshot = (char) NULL;
-       }
-       else
-       {
-               /* version is a snapshot */
-               bname = fromRelname;
-               strcpy(saved_basename, (char *) bname);
-               sprintf(saved_snapshot, "['%s']", date);
-       }
-
-
-       /*
-        * Calls the routine ``GetAttrList'' get the list of attributes from
-        * the base relation. Code is put here so that we only need to look up
-        * the attribute once for both appends and replaces.
-        */
-       setAttrList(bname);
-
-       VersionCreate(name, saved_basename);
-       VersionAppend(name, saved_basename);
-       VersionDelete(name, saved_basename, saved_snapshot);
-       VersionReplace(name, saved_basename, saved_snapshot);
-       VersionRetrieve(name, saved_basename, saved_snapshot);
-}
-#endif
-
-/*
- *     Creates the deltas.
- */
-#ifdef NOT_USED
-void
-VersionCreate(char *vname, char *bname)
-{
-       static char query_buf[MAX_QUERY_LEN];
-
-       /*
-        * Creating the dummy version relation for triggering rules.
-        */
-       sprintf(query_buf, "SELECT * INTO TABLE %s from %s where 1 =2",
-                       vname, bname);
-
-       pg_exec_query(query_buf);
-
-       /*
-        * Creating the ``v_added'' relation
-        */
-       sprintf(query_buf, "SELECT * INTO TABLE %s_added from %s where 1 = 2",
-                       vname, bname);
-       eval_as_new_xact(query_buf);
-
-       /*
-        * Creating the ``v_deleted'' relation.
-        */
-       sprintf(query_buf, "CREATE TABLE %s_del (DOID oid)", vname);
-       eval_as_new_xact(query_buf);
-}
-#endif
-
-
-/*
- * Given the relation name, does a catalog lookup for that relation and
- * sets the global variable 'attr_list' with the list of attributes (names)
- * for that relation.
- */
-#ifdef NOT_USED
-static void
-setAttrList(char *bname)
-{
-       Relation        rel;
-       int                     i = 0;
-       int                     maxattrs = 0;
-       char       *attrname;
-       char            temp_buf[512];
-       int                     notfirst = 0;
-
-       rel = heap_openr(bname);
-       if (rel == NULL)
-       {
-               elog(ERROR, "Unable to expand all -- amopenr failed ");
-               return;
-       }
-       maxattrs = RelationGetNumberOfAttributes(rel);
-
-       attr_list[0] = '\0';
-
-       for (i = maxattrs - 1; i > -1; --i)
-       {
-               attrname = NameStr(rel->rd_att->attrs[i]->attname);
-
-               if (notfirst == 1)
-                       sprintf(temp_buf, ", %s = new.%s", attrname, attrname);
-               else
-               {
-                       sprintf(temp_buf, "%s = new.%s", attrname, attrname);
-                       notfirst = 1;
-               }
-               strcat(attr_list, temp_buf);
-       }
-
-       heap_close(rel);
-
-       return;
-}
-#endif
-
-/*
- * This routine defines the rule governing the append semantics of
- * versions.  All tuples appended to a version gets appended to the
- * <vname>_added relation.
- */
-#ifdef NOT_USED
-static void
-VersionAppend(char *vname, char *bname)
-{
-       sprintf(rule_buf,
-                       "define rewrite rule %s_append is on INSERT to %s do instead append %s_added(%s)",
-                       vname, vname, vname, attr_list);
-
-       eval_as_new_xact(rule_buf);
-}
-#endif
-
-/*
- * This routine defines the rule governing the retrieval semantics of
- * versions.  To retrieve tuples from a version , we need to:
- *
- *             1. Retrieve all tuples in the <vname>_added relation.
- *             2. Retrieve all tuples in the base relation which are not in
- *                the <vname>_del relation.
- */
-#ifdef NOT_USED
-void
-VersionRetrieve(char *vname, char *bname, char *snapshot)
-{
-
-       sprintf(rule_buf,
-                       "define rewrite rule %s_retrieve is on SELECT to %s do instead\n\
-SELECT %s_1.oid, %s_1.* from _%s in %s%s, %s_1 in (%s_added | _%s) \
-where _%s.oid !!= '%s_del.DOID'",
-                       vname, vname, vname, vname, bname,
-                       bname, snapshot,
-                       vname, vname, bname, bname, vname);
-
-       eval_as_new_xact(rule_buf);
-
-       /* printf("%s\n",rule_buf); */
-
-}
-#endif
-
-/*
- * This routine defines the rules that govern the delete semantics of
- * versions. Two things happens when we delete a tuple from a version:
- *
- *        1. If the tuple to be deleted was added to the version *after*
- *               the version was created, then we simply delete the tuple
- *               from the <vname>_added relation.
- *        2. If the tuple to be deleted is actually in the base relation,
- *               then we have to mark that tuple as being deleted by adding
- *               it to the <vname>_del relation.
- */
-#ifdef NOT_USED
-void
-VersionDelete(char *vname, char *bname, char *snapshot)
-{
-
-       sprintf(rule_buf,
-                       "define rewrite rule %s_delete1 is on delete to %s do instead\n \
-[delete %s_added where current.oid = %s_added.oid\n \
- append %s_del(DOID = current.oid) from _%s in %s%s \
- where current.oid = _%s.oid] \n",
-                       vname, vname, vname, vname, vname,
-                       bname, bname, snapshot, bname);
-
-       eval_as_new_xact(rule_buf);
-#ifdef OLD_REWRITE
-       sprintf(rule_buf,
-                       "define rewrite rule %s_delete2 is on delete to %s do instead \n \
-    append %s_del(DOID = current.oid) from _%s in %s%s \
-    where current.oid = _%s.oid \n",
-                       vname, vname, vname, bname, bname, snapshot, bname);
-
-       eval_as_new_xact(rule_buf);
-#endif   /* OLD_REWRITE */
-}
-#endif
-
-/*
- *     This routine defines the rules that govern the update semantics
- *     of versions. To update a tuple in a version:
- *
- *             1. If the tuple is in <vname>_added, we simply ``replace''
- *                the tuple (as per postgres style).
- *             2. if the tuple is in the base relation, then two things have to
- *                happen:
- *                2.1  The tuple is marked ``deleted'' from the base relation by
- *                             adding the tuple to the <vname>_del relation.
- *                2.2  A copy of the tuple is appended to the <vname>_added relation
- */
-#ifdef NOT_USED
-void
-VersionReplace(char *vname, char *bname, char *snapshot)
-{
-       sprintf(rule_buf,
-                       "define rewrite rule %s_replace1 is on replace to %s do instead \n\
-[replace %s_added(%s) where current.oid = %s_added.oid \n\
- append %s_del(DOID = current.oid) from _%s in %s%s \
- where current.oid = _%s.oid\n\
- append %s_added(%s) from _%s in %s%s \
- where current.oid !!= '%s_added.oid' and current.oid = _%s.oid]\n",
-                       vname, vname, vname, attr_list, vname,
-                       vname, bname, bname, snapshot, bname,
-                       vname, attr_list, bname, bname, snapshot, vname, bname);
-
-       eval_as_new_xact(rule_buf);
-
-/*     printf("%s\n",rule_buf); */
-#ifdef OLD_REWRITE
-       sprintf(rule_buf,
-                       "define rewrite rule %s_replace2 is on replace to %s do \n\
-    append %s_del(DOID = current.oid) from _%s in %s%s \
-    where current.oid = _%s.oid\n",
-                       vname, vname, vname, bname, bname, snapshot, bname);
-
-       eval_as_new_xact(rule_buf);
-
-       sprintf(rule_buf,
-                       "define rewrite rule %s_replace3 is on replace to %s do instead\n\
-    append %s_added(%s) from _%s in %s%s \
-    where current.oid !!= '%s_added.oid' and current.oid = \
-    _%s.oid\n",
-       vname, vname, vname, attr_list, bname, bname, snapshot, vname, bname);
-
-       eval_as_new_xact(rule_buf);
-#endif   /* OLD_REWRITE */
-/*     printf("%s\n",rule_buf); */
-
-}
-
-#endif
diff --git a/src/backend/executor/_deadcode/nodeTee.c b/src/backend/executor/_deadcode/nodeTee.c
deleted file mode 100644 (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 <sys/types.h>
-#include <sys/file.h>
-#include "postgres.h"
-
-#include "access/heapam.h"
-#include "catalog/catalog.h"
-#include "catalog/heap.h"
-#include "executor/executor.h"
-#include "executor/nodeTee.h"
-#include "optimizer/internal.h"
-#include "storage/bufmgr.h"
-#include "storage/smgr.h"
-#include "tcop/pquery.h"
-#include "utils/relcache.h"
-
-/* ------------------------------------------------------------------
- *             ExecInitTee
- *
- *             Create tee state
- *
- * ------------------------------------------------------------------
- */
-bool
-ExecInitTee(Tee * node, EState *currentEstate, Plan *parent)
-{
-       TeeState   *teeState;
-       Plan       *outerPlan;
-       int                     len;
-       Relation        bufferRel;
-       TupleDesc       tupType;
-       EState     *estate;
-
-       /*
-        * it is possible that the Tee has already been initialized since it
-        * can be reached by multiple parents. If it is already initialized,
-        * simply return and do not initialize the children nodes again
-        */
-       if (node->plan.state)
-               return TRUE;
-
-       /*
-        * assign the node's execution state
-        */
-
-       /*
-        * make a new executor state, because we have a different
-        * es_range_table
-        */
-
-/*        node->plan.state = estate;*/
-
-       estate = CreateExecutorState();
-       estate->es_direction = currentEstate->es_direction;
-       estate->es_BaseId = currentEstate->es_BaseId;
-       estate->es_BaseId = currentEstate->es_BaseId;
-       estate->es_tupleTable = currentEstate->es_tupleTable;
-       estate->es_refcount = currentEstate->es_refcount;
-       estate->es_junkFilter = currentEstate->es_junkFilter;
-       estate->es_snapshot = currentEstate->es_snapshot;
-
-       /*
-        * use the range table for Tee subplan since the range tables for the
-        * two parents may be different
-        */
-       if (node->rtentries)
-               estate->es_range_table = node->rtentries;
-       else
-               estate->es_range_table = currentEstate->es_range_table;
-
-       node->plan.state = estate;
-
-
-       /*
-        * create teeState structure
-        */
-       teeState = makeNode(TeeState);
-       teeState->tee_leftPlace = 0;
-       teeState->tee_rightPlace = 0;
-       teeState->tee_lastPlace = 0;
-       teeState->tee_bufferRel = NULL;
-       teeState->tee_leftScanDesc = NULL;
-       teeState->tee_rightScanDesc = NULL;
-
-
-       node->teestate = teeState;
-
-       /* ----------------
-        *      Miscellanious initialization
-        *
-        *               +      assign node's base_id
-        *               +      assign debugging hooks and
-        *               +      create expression context for node
-        * ----------------
-        */
-       ExecAssignNodeBaseInfo(estate, &(teeState->cstate), parent);
-       ExecAssignExprContext(estate, &(teeState->cstate));
-
-#define TEE_NSLOTS 2
-
-       /*
-        * initialize tuple slots
-        */
-       ExecInitResultTupleSlot(estate, &(teeState->cstate));
-
-       /* initialize child nodes */
-       outerPlan = outerPlan((Plan *) node);
-       ExecInitNode(outerPlan, estate, (Plan *) node);
-
-       /*
-        * the tuple type info is from the outer plan of this node the result
-        * type is also the same as the outerplan
-        */
-       ExecAssignResultTypeFromOuterPlan((Plan *) node, &(teeState->cstate));
-       ExecAssignProjectionInfo((Plan *) node, &teeState->cstate);
-
-       /*
-        * initialize temporary relation to buffer tuples
-        */
-       tupType = ExecGetResultType(&(teeState->cstate));
-       len = ExecTargetListLength(((Plan *) node)->targetlist);
-
-       /*
-        * create a catalogued relation even though this is a temporary
-        * relation
-        */
-       /* cleanup of catalogued relations is easier to do */
-
-       if (node->teeTableName[0] != '\0')
-       {
-               Relation        r;
-
-               teeState->tee_bufferRelname = pstrdup(node->teeTableName);
-
-               /*
-                * we are given an tee table name, if a relation by that name
-                * exists, then we open it, else we create it and then open it
-                */
-               r = RelationNameGetRelation(teeState->tee_bufferRelname);
-
-               if (RelationIsValid(r))
-                       bufferRel = heap_openr(teeState->tee_bufferRelname);
-               else
-                       bufferRel = heap_open(
-                                       heap_create_with_catalog(teeState->tee_bufferRelname,
-                                                                         tupType, RELKIND_RELATION, false));
-       }
-       else
-       {
-               sprintf(teeState->tee_bufferRelname,
-                               "ttemp_%d",             /* 'ttemp' for 'tee' temporary */
-                               newoid());
-               bufferRel = heap_open(
-                                       heap_create_with_catalog(teeState->tee_bufferRelname,
-                                                                         tupType, RELKIND_RELATION, false));
-       }
-
-       teeState->tee_bufferRel = bufferRel;
-
-       /*
-        * initialize a memory context for allocating thing like scan
-        * descriptors
-        */
-
-       /*
-        * we do this so that on cleanup of the tee, we can free things. if we
-        * didn't have our own memory context, we would be in the memory
-        * context of the portal that we happen to be using at the moment
-        */
-
-       teeState->tee_mcxt = (MemoryContext) CreateGlobalMemory(teeState->tee_bufferRelname);
-
-       /*
-        * don't initialize the scan descriptors here because it's not good to
-        * initialize scan descriptors on empty rels. Wait until the scan
-        * descriptors are needed before initializing them.
-        */
-
-       teeState->tee_leftScanDesc = NULL;
-       teeState->tee_rightScanDesc = NULL;
-
-       return TRUE;
-}
-
-int
-ExecCountSlotsTee(Tee * node)
-{
-       /* Tee nodes can't have innerPlans */
-       return ExecCountSlotsNode(outerPlan(node)) + TEE_NSLOTS;
-}
-
-/* ----------------------------------------------------------------
-   initTeeScanDescs
-         initializes the left and right scandescs on the temporary
-         relation of a Tee node
-
-         must open two separate scan descriptors,
-         because the left and right scans may be at different points
-* ----------------------------------------------------------------
-*/
-static void
-initTeeScanDescs(Tee * node)
-{
-       TeeState   *teeState;
-       Relation        bufferRel;
-       ScanDirection dir;
-       Snapshot        snapshot;
-       MemoryContext orig;
-
-       teeState = node->teestate;
-       if (teeState->tee_leftScanDesc && teeState->tee_rightScanDesc)
-               return;
-
-       orig = CurrentMemoryContext;
-       MemoryContextSwitchTo(teeState->tee_mcxt);
-
-       bufferRel = teeState->tee_bufferRel;
-       dir = ((Plan *) node)->state->es_direction; /* backwards not handled
-                                                                                                * yet XXX */
-       snapshot = ((Plan *) node)->state->es_snapshot;
-
-       if (teeState->tee_leftScanDesc == NULL)
-       {
-               teeState->tee_leftScanDesc = heap_beginscan(bufferRel,
-                                                                                       ScanDirectionIsBackward(dir),
-                                                                                                       snapshot,
-                                                                                                       0,      /* num scan keys */
-                                                                                                       NULL            /* scan keys */
-                       );
-       }
-       if (teeState->tee_rightScanDesc == NULL)
-       {
-               teeState->tee_rightScanDesc = heap_beginscan(bufferRel,
-                                                                                       ScanDirectionIsBackward(dir),
-                                                                                                        snapshot,
-                                                                                                        0, /* num scan keys */
-                                                                                                        NULL           /* scan keys */
-                       );
-       }
-
-       MemoryContextSwitchTo(orig);
-}
-
-/* ----------------------------------------------------------------
- *             ExecTee(node)
- *
- *
- *             A Tee serves to connect a subplan to multiple parents.
- *             the subplan is always the outplan of the Tee node.
- *
- *             The Tee gets requests from either leftParent or rightParent,
- *             fetches the result tuple from the child, and then
- *             stored the result into a temporary relation (serving as a queue).
- *             leftPlace and rightPlace keep track of where the left and rightParents
- *             are.
- *             If a parent requests a tuple and that parent is not at the end
- *             of the temporary relation, then the request is satisfied from
- *             the queue instead of by executing the child plan
- *
- * ----------------------------------------------------------------
- */
-
-TupleTableSlot *
-ExecTee(Tee * node, Plan *parent)
-{
-       EState     *estate;
-       TeeState   *teeState;
-       int                     leftPlace,
-                               rightPlace,
-                               lastPlace;
-       int                     branch;
-       TupleTableSlot *result;
-       TupleTableSlot *slot;
-       Plan       *childNode;
-       ScanDirection dir;
-       HeapTuple       heapTuple;
-       Relation        bufferRel;
-       HeapScanDesc scanDesc;
-
-       estate = ((Plan *) node)->state;
-       teeState = node->teestate;
-       leftPlace = teeState->tee_leftPlace;
-       rightPlace = teeState->tee_rightPlace;
-       lastPlace = teeState->tee_lastPlace;
-       bufferRel = teeState->tee_bufferRel;
-
-       childNode = outerPlan(node);
-
-       dir = estate->es_direction;
-
-       /* XXX doesn't handle backwards direction yet */
-
-       if (parent == node->leftParent)
-               branch = leftPlace;
-       else if ((parent == node->rightParent) || (parent == (Plan *) node))
-
-               /*
-                * the tee node could be the root node of the plan, in which case,
-                * we treat it like a right-parent pull
-                */
-               branch = rightPlace;
-       else
-       {
-               elog(ERROR, "A Tee node can only be executed from its left or right parent\n");
-               return NULL;
-       }
-
-       if (branch == lastPlace)
-       {                                                       /* we're at the end of the queue already,
-                                                                * - get a new tuple from the child plan,
-                                                                * - store it in the queue, - increment
-                                                                * lastPlace, - increment leftPlace or
-                                                                * rightPlace as appropriate, - and return
-                                                                * result */
-               slot = ExecProcNode(childNode, (Plan *) node);
-               if (!TupIsNull(slot))
-               {
-                       /*
-                        * heap_insert changes something...
-                        */
-                       if (slot->ttc_buffer != InvalidBuffer)
-                               heapTuple = heap_copytuple(slot->val);
-                       else
-                               heapTuple = slot->val;
-
-                       /* insert into temporary relation */
-                       heap_insert(bufferRel, heapTuple);
-
-                       if (slot->ttc_buffer != InvalidBuffer)
-                               heap_freetuple(heapTuple);
-
-                       /*
-                        * once there is data in the temporary relation, ensure that
-                        * the left and right scandescs are initialized
-                        */
-                       initTeeScanDescs(node);
-
-                       scanDesc = (parent == node->leftParent) ?
-                               teeState->tee_leftScanDesc : teeState->tee_rightScanDesc;
-
-                       {
-                               /*
-                                * move the scandesc forward so we don't re-read this
-                                * tuple later
-                                */
-                               HeapTuple       throwAway;
-
-                               /* Buffer buffer; */
-                               throwAway = heap_getnext(scanDesc, ScanDirectionIsBackward(dir));
-                       }
-
-                       /*
-                        * set the shouldFree field of the child's slot so that when
-                        * the child's slot is free'd, this tuple isn't free'd also
-                        */
-
-                       /*
-                        * does this mean this tuple has to be garbage collected
-                        * later??
-                        */
-                       slot->ttc_shouldFree = false;
-
-                       teeState->tee_lastPlace = lastPlace + 1;
-               }
-               result = slot;
-       }
-       else
-       {                                                       /* the desired data already exists in the
-                                                                * temporary relation */
-               scanDesc = (parent == node->leftParent) ?
-                       teeState->tee_leftScanDesc : teeState->tee_rightScanDesc;
-
-               heapTuple = heap_getnext(scanDesc, ScanDirectionIsBackward(dir));
-
-               /*
-                * Increase the pin count on the buffer page, because the tuple
-                * stored in the slot also points to it (as well as the scan
-                * descriptor). If we don't, ExecStoreTuple will decrease the pin
-                * count on the next iteration.
-                */
-
-               if (scanDesc->rs_cbuf != InvalidBuffer)
-                       IncrBufferRefCount(scanDesc->rs_cbuf);
-
-               slot = teeState->cstate.cs_ResultTupleSlot;
-               slot->ttc_tupleDescriptor = RelationGetDescr(bufferRel);
-
-               result = ExecStoreTuple(heapTuple,              /* tuple to store */
-                                                               slot,   /* slot to store in */
-                                                               scanDesc->rs_cbuf,              /* this tuple's buffer */
-                                                               false); /* don't free stuff from
-                                                                                * heap_getnext */
-
-       }
-
-       if (parent == node->leftParent)
-               teeState->tee_leftPlace = leftPlace + 1;
-       else
-               teeState->tee_rightPlace = rightPlace + 1;
-
-       return result;
-}
-
-/* ---------------------------------------------------------------------
- *             ExecEndTee
- *
- *      End the Tee node, and free up any storage
- * since a Tee node can be downstream of multiple parent nodes,
- * only free when both parents are done
- * --------------------------------------------------------------------
- */
-
-void
-ExecEndTee(Tee * node, Plan *parent)
-{
-       EState     *estate;
-       TeeState   *teeState;
-       int                     leftPlace,
-                               rightPlace,
-                               lastPlace;
-       Relation        bufferRel;
-       MemoryContext orig;
-
-       estate = ((Plan *) node)->state;
-       teeState = node->teestate;
-       leftPlace = teeState->tee_leftPlace;
-       rightPlace = teeState->tee_rightPlace;
-       lastPlace = teeState->tee_lastPlace;
-
-       if (!node->leftParent || parent == node->leftParent)
-               leftPlace = -1;
-
-       if (!node->rightParent || parent == node->rightParent)
-               rightPlace = -1;
-
-       if (parent == (Plan *) node)
-               rightPlace = leftPlace = -1;
-
-       teeState->tee_leftPlace = leftPlace;
-       teeState->tee_rightPlace = rightPlace;
-       if ((leftPlace == -1) && (rightPlace == -1))
-       {
-               /* remove the temporary relations */
-               /* and close the scan descriptors */
-
-               bufferRel = teeState->tee_bufferRel;
-               if (bufferRel)
-               {
-                       heap_drop(bufferRel);
-                       teeState->tee_bufferRel = NULL;
-                       if (teeState->tee_mcxt)
-                       {
-                               orig = CurrentMemoryContext;
-                               MemoryContextSwitchTo(teeState->tee_mcxt);
-                       }
-                       else
-                               orig = 0;
-
-                       if (teeState->tee_leftScanDesc)
-                       {
-                               heap_endscan(teeState->tee_leftScanDesc);
-                               teeState->tee_leftScanDesc = NULL;
-                       }
-                       if (teeState->tee_rightScanDesc)
-                       {
-                               heap_endscan(teeState->tee_rightScanDesc);
-                               teeState->tee_rightScanDesc = NULL;
-                       }
-
-                       if (teeState->tee_mcxt)
-                       {
-                               MemoryContextSwitchTo(orig);
-                               teeState->tee_mcxt = NULL;
-                       }
-               }
-       }
-
-}
diff --git a/src/backend/optimizer/path/_deadcode/predmig.c b/src/backend/optimizer/path/_deadcode/predmig.c
deleted file mode 100644 (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 <math.h>
-
-#ifdef HAVE_VALUES_H
-#include <values.h>
-#endif
-
-#include "postgres.h"
-
-#include "access/heapam.h"
-#include "access/htup.h"
-#include "catalog/pg_language.h"
-#include "catalog/pg_proc.h"
-#include "catalog/pg_type.h"
-#include "lib/lispsort.h"
-#include "nodes/nodes.h"
-#include "nodes/pg_list.h"
-#include "nodes/primnodes.h"
-#include "nodes/relation.h"
-#include "optimizer/clauses.h"
-#include "optimizer/cost.h"
-#include "optimizer/internal.h"
-#include "optimizer/keys.h"
-#include "optimizer/pathnode.h"
-#include "optimizer/tlist.h"
-#include "storage/buf_internals.h"
-#include "tcop/dest.h"
-#include "utils/syscache.h"
-
-#define ever ; 1 ;
-
-/* local funcs */
-static int xfunc_card_unreferenced(Query *queryInfo,
-                                               Expr *clause, Relids referenced);
-
-*/
-
-/*
-** xfunc_trypullup
-**       Preliminary pullup of predicates, to allow for maximal pruning.
-** Given a relation, check each of its paths and see if you can
-** pullup clauses from its inner and outer.
-*/
-
-void
-xfunc_trypullup(RelOptInfo rel)
-{
-       LispValue       y;                              /* list ptr */
-       RestrictInfo maxcinfo;          /* The RestrictInfo to pull up, as
-                                                                * calculated by xfunc_shouldpull() */
-       JoinPath        curpath;                /* current path in list */
-       int                     progress;               /* has progress been made this time
-                                                                * through? */
-       int                     clausetype;
-
-       do
-       {
-               progress = false;               /* no progress yet in this iteration */
-               foreach(y, get_pathlist(rel))
-               {
-                       curpath = (JoinPath) lfirst(y);
-
-                       /*
-                        * * for each operand, attempt to pullup predicates until
-                        * first * failure.
-                        */
-                       for (ever)
-                       {
-                               /* No, the following should NOT be '=='  !! */
-                               if (clausetype = xfunc_shouldpull((Path) get_innerjoinpath(curpath),
-                                                                                         curpath, INNER, &maxcinfo))
-                               {
-
-                                       xfunc_pullup((Path) get_innerjoinpath(curpath),
-                                                                curpath, maxcinfo, INNER, clausetype);
-                                       progress = true;
-                               }
-                               else
-                                       break;
-                       }
-                       for (ever)
-                       {
-
-                               /* No, the following should NOT be '=='  !! */
-                               if (clausetype = xfunc_shouldpull((Path) get_outerjoinpath(curpath),
-                                                                                         curpath, OUTER, &maxcinfo))
-                               {
-
-                                       xfunc_pullup((Path) get_outerjoinpath(curpath),
-                                                                curpath, maxcinfo, OUTER, clausetype);
-                                       progress = true;
-                               }
-                               else
-                                       break;
-                       }
-
-                       /*
-                        * * make sure the unpruneable flag bubbles up, i.e. * if
-                        * anywhere below us in the path pruneable is false, * then
-                        * pruneable should be false here
-                        */
-                       if (get_pruneable(get_parent(curpath)) &&
-                               (!get_pruneable(get_parent
-                                                               ((Path) get_innerjoinpath(curpath))) ||
-                                !get_pruneable(get_parent((Path)
-                                                                                  get_outerjoinpath(curpath)))))
-                       {
-
-                               set_pruneable(get_parent(curpath), false);
-                               progress = true;
-                       }
-               }
-       } while (progress);
-}
-
-/*
- ** xfunc_shouldpull
- **    find clause with highest rank, and decide whether to pull it up
- ** from child to parent.  Currently we only pullup secondary join clauses
- ** that are in the pathrestrictinfo.  Secondary hash and sort clauses are
- ** left where they are.
- **    If we find an expensive function but decide *not* to pull it up,
- ** we'd better set the unpruneable flag.  -- JMH, 11/11/92
- **
- ** Returns:  0 if nothing left to pullup
- **                      XFUNC_LOCPRD if a local predicate is to be pulled up
- **                      XFUNC_JOINPRD if a secondary join predicate is to be pulled up
- */
-int
-xfunc_shouldpull(Query *queryInfo,
-                                Path childpath,
-                                JoinPath parentpath,
-                                int whichchild,
-                                RestrictInfo *maxcinfopt)              /* Out: pointer to clause
-                                                                                                * to pullup */
-{
-       LispValue       clauselist,
-                               tmplist;                /* lists of clauses */
-       RestrictInfo maxcinfo;          /* clause to pullup */
-       LispValue       primjoinclause  /* primary join clause */
-       = xfunc_primary_join(parentpath);
-       Cost            tmprank,
-                               maxrank = (-1 * MAXFLOAT);              /* ranks of clauses */
-       Cost            joinselec = 0;  /* selectivity of the join predicate */
-       Cost            joincost = 0;   /* join cost + primjoinclause cost */
-       int                     retval = XFUNC_LOCPRD;
-
-       clauselist = get_loc_restrictinfo(childpath);
-
-       if (clauselist != LispNil)
-       {
-               /* find local predicate with maximum rank */
-               for (tmplist = clauselist,
-                        maxcinfo = (RestrictInfo) lfirst(tmplist),
-                        maxrank = xfunc_rank(get_clause(maxcinfo));
-                        tmplist != LispNil;
-                        tmplist = lnext(tmplist))
-               {
-
-                       if ((tmprank = xfunc_rank(get_clause((RestrictInfo) lfirst(tmplist))))
-                               > maxrank)
-                       {
-                               maxcinfo = (RestrictInfo) lfirst(tmplist);
-                               maxrank = tmprank;
-                       }
-               }
-       }
-
-       /*
-        * * If child is a join path, and there are multiple join clauses, *
-        * see if any join clause has even higher rank than the highest *
-        * local predicate
-        */
-       if (is_join(childpath) && xfunc_num_join_clauses((JoinPath) childpath) > 1)
-               for (tmplist = get_pathrestrictinfo((JoinPath) childpath);
-                        tmplist != LispNil;
-                        tmplist = lnext(tmplist))
-               {
-
-                       if (tmplist != LispNil &&
-                               (tmprank = xfunc_rank(get_clause((RestrictInfo) lfirst(tmplist))))
-                               > maxrank)
-                       {
-                               maxcinfo = (RestrictInfo) lfirst(tmplist);
-                               maxrank = tmprank;
-                               retval = XFUNC_JOINPRD;
-                       }
-               }
-       if (maxrank == (-1 * MAXFLOAT))         /* no expensive clauses */
-               return 0;
-
-       /*
-        * * Pullup over join if clause is higher rank than join, or if * join
-        * is nested loop and current path is inner child (note that *
-        * restrictions on the inner of a nested loop don't buy you anything
-        * -- * you still have to scan the entire inner relation each time). *
-        * Note that the cost of a secondary join clause is only what's *
-        * calculated by xfunc_expense(), since the actual joining * (i.e. the
-        * usual path_cost) is paid for by the primary join clause.
-        */
-       if (primjoinclause != LispNil)
-       {
-               joinselec = compute_clause_selec(queryInfo, primjoinclause, LispNil);
-               joincost = xfunc_join_expense(parentpath, whichchild);
-
-               if (XfuncMode == XFUNC_PULLALL ||
-                       (XfuncMode != XFUNC_WAIT &&
-                        ((joincost != 0 &&
-                          (maxrank = xfunc_rank(get_clause(maxcinfo))) >
-                          ((joinselec - 1.0) / joincost))
-                         || (joincost == 0 && joinselec < 1)
-                         || (!is_join(childpath)
-                                 && (whichchild == INNER)
-                                 && IsA(parentpath, NestPath)
-                                 &&!IsA(parentpath, HashPath)
-                                 &&!IsA(parentpath, MergePath)))))
-               {
-
-                       *maxcinfopt = maxcinfo;
-                       return retval;
-
-               }
-               else if (maxrank != -(MAXFLOAT))
-               {
-                       /*
-                        * * we've left an expensive restriction below a join.  Since *
-                        * we may pullup this restriction in predmig.c, we'd best *
-                        * set the RelOptInfo of this join to be unpruneable
-                        */
-                       set_pruneable(get_parent(parentpath), false);
-                       /* and fall through */
-               }
-       }
-       return 0;
-}
-
-
-/*
- ** xfunc_pullup
- **    move clause from child pathnode to parent pathnode.      This operation
- ** makes the child pathnode produce a larger relation than it used to.
- ** This means that we must construct a new RelOptInfo just for the childpath,
- ** although this RelOptInfo will not be added to the list of Rels to be joined up
- ** in the query; it's merely a parent for the new childpath.
- **    We also have to fix up the path costs of the child and parent.
- **
- ** Now returns a pointer to the new pulled-up RestrictInfo. -- JMH, 11/18/92
- */
-RestrictInfo
-xfunc_pullup(Query *queryInfo,
-                        Path childpath,
-                        JoinPath parentpath,
-                        RestrictInfo cinfo,    /* clause to pull up */
-                        int whichchild,        /* whether child is INNER or OUTER of join */
-                        int clausetype)        /* whether clause to pull is join or local */
-{
-       Path            newkid;
-       RelOptInfo      newrel;
-       Cost            pulled_selec;
-       Cost            cost;
-       RestrictInfo newinfo;
-
-       /* remove clause from childpath */
-       newkid = (Path) copyObject((Node) childpath);
-       if (clausetype == XFUNC_LOCPRD)
-       {
-               set_locrestrictinfo(newkid,
-                                                       xfunc_LispRemove((LispValue) cinfo,
-                                                                  (List) get_loc_restrictinfo(newkid)));
-       }
-       else
-       {
-               set_pathrestrictinfo
-                       ((JoinPath) newkid,
-                        xfunc_LispRemove((LispValue) cinfo,
-                                               (List) get_pathrestrictinfo((JoinPath) newkid)));
-       }
-
-       /*
-        * * give the new child path its own RelOptInfo node that reflects the *
-        * lack of the pulled-up predicate
-        */
-       pulled_selec = compute_clause_selec(queryInfo,
-                                                                               get_clause(cinfo), LispNil);
-       xfunc_copyrel(get_parent(newkid), &newrel);
-       set_parent(newkid, newrel);
-       set_pathlist(newrel, makeList1(newkid));
-       set_unorderedpath(newrel, (PathPtr) newkid);
-       set_cheapestpath(newrel, (PathPtr) newkid);
-       set_size(newrel,
-               (Count) ((Cost) get_size(get_parent(childpath)) / pulled_selec));
-
-       /*
-        * * fix up path cost of newkid.  To do this we subtract away all the *
-        * xfunc_costs of childpath, then recompute the xfunc_costs of newkid
-        */
-       cost = get_path_cost(newkid) - xfunc_get_path_cost(childpath);
-       Assert(cost >= 0);
-       set_path_cost(newkid, cost);
-       cost = get_path_cost(newkid) + xfunc_get_path_cost(newkid);
-       set_path_cost(newkid, cost);
-
-       /*
-        * * We copy the cinfo, since it may appear in other plans, and we're
-        * going * to munge it.  -- JMH, 7/22/92
-        */
-       newinfo = (RestrictInfo) copyObject((Node) cinfo);
-
-       /*
-        * * Fix all vars in the clause * to point to the right varno and
-        * varattno in parentpath
-        */
-       xfunc_fixvars(get_clause(newinfo), newrel, whichchild);
-
-       /* add clause to parentpath, and fix up its cost. */
-       set_locrestrictinfo(parentpath,
-                                               lispCons((LispValue) newinfo,
-                                                 (LispValue) get_loc_restrictinfo(parentpath)));
-       /* put new childpath into the path tree */
-       if (whichchild == INNER)
-               set_innerjoinpath(parentpath, (pathPtr) newkid);
-       else
-               set_outerjoinpath(parentpath, (pathPtr) newkid);
-
-       /*
-        * * recompute parentpath cost from scratch -- the cost * of the join
-        * method has changed
-        */
-       cost = xfunc_total_path_cost(parentpath);
-       set_path_cost(parentpath, cost);
-
-       return newinfo;
-}
-
-/*
- ** calculate (selectivity-1)/cost.
- */
-Cost
-xfunc_rank(Query *queryInfo, LispValue clause)
-{
-       Cost            selec = compute_clause_selec(queryInfo, clause, LispNil);
-       Cost            cost = xfunc_expense(queryInfo, clause);
-
-       if (cost == 0)
-               if (selec > 1)
-                       return MAXFLOAT;
-               else
-                       return -(MAXFLOAT);
-       return (selec - 1) / cost;
-}
-
-/*
- ** Find the "global" expense of a clause; i.e. the local expense divided
- ** by the cardinalities of all the base relations of the query that are *not*
- ** referenced in the clause.
- */
-Cost
-xfunc_expense(Query *queryInfo, clause)
-LispValue      clause;
-{
-       Cost            cost = xfunc_local_expense(clause);
-
-       if (cost)
-       {
-               Count           card = xfunc_card_unreferenced(queryInfo, clause, LispNil);
-
-               if (card)
-                       cost /= card;
-       }
-
-       return cost;
-}
-
-/*
- ** xfunc_join_expense
- **    Find global expense of a join clause
- */
-Cost
-xfunc_join_expense(Query *queryInfo, JoinPath path, int whichchild)
-{
-       LispValue       primjoinclause = xfunc_primary_join(path);
-
-       /*
-        * * the second argument to xfunc_card_unreferenced reflects all the *
-        * relations involved in the join clause, i.e. all the relids in the
-        * RelOptInfo * of the join clause
-        */
-       Count           card = 0;
-       Cost            cost = xfunc_expense_per_tuple(path, whichchild);
-
-       card = xfunc_card_unreferenced(queryInfo,
-                                                                  primjoinclause,
-                                                                  get_relids(get_parent(path)));
-       if (primjoinclause)
-               cost += xfunc_local_expense(primjoinclause);
-
-       if (card)
-               cost /= card;
-
-       return cost;
-}
-
-/*
- ** Recursively find the per-tuple expense of a clause.  See
- ** xfunc_func_expense for more discussion.
- */
-Cost
-xfunc_local_expense(LispValue clause)
-{
-       Cost            cost = 0;               /* running expense */
-       LispValue       tmpclause;
-
-       /* First handle the base case */
-       if (IsA(clause, Const) ||IsA(clause, Var) ||IsA(clause, Param))
-               return 0;
-       /* now other stuff */
-       else if (IsA(clause, Iter))
-               /* Too low. Should multiply by the expected number of iterations. */
-               return xfunc_local_expense(get_iterexpr((Iter) clause));
-       else if (IsA(clause, ArrayRef))
-               return xfunc_local_expense(get_refexpr((ArrayRef) clause));
-       else if (fast_is_clause(clause))
-               return (xfunc_func_expense((LispValue) get_op(clause),
-                                                                  (LispValue) get_opargs(clause)));
-       else if (fast_is_funcclause(clause))
-               return (xfunc_func_expense((LispValue) get_function(clause),
-                                                                  (LispValue) get_funcargs(clause)));
-       else if (fast_not_clause(clause))
-               return xfunc_local_expense(lsecond(clause));
-       else if (fast_or_clause(clause) || fast_and_clause(clause))
-       {
-               /* find cost of evaluating each disjunct */
-               for (tmpclause = lnext(clause); tmpclause != LispNil;
-                        tmpclause = lnext(tmpclause))
-                       cost += xfunc_local_expense(lfirst(tmpclause));
-               return cost;
-       }
-       else
-       {
-               elog(ERROR, "Clause node of undetermined type");
-               return -1;
-       }
-}
-
-/*
- ** xfunc_func_expense
- **    given a Func or Oper and its args, find its expense.
- ** Note: in Stonebraker's SIGMOD '91 paper, he uses a more complicated metric
- ** than the one here. We can ignore the expected number of tuples for
- ** our calculations; we just need the per-tuple expense.  But he also
- ** proposes components to take into account the costs of accessing disk and
- ** archive.  We didn't adopt that scheme here; eventually the vacuum
- ** cleaner should be able to tell us what percentage of bytes to find on
- ** which storage level, and that should be multiplied in appropriately
- ** in the cost function below.  Right now we don't model the cost of
- ** accessing secondary or tertiary storage, since we don't have sufficient
- ** stats to do it right.
- */
-Cost
-xfunc_func_expense(LispValue node, LispValue args)
-{
-       HeapTuple       tupl;                   /* the pg_proc tuple for each function */
-       Form_pg_proc proc;                      /* a data structure to hold the pg_proc
-                                                                * tuple */
-       int                     width = 0;              /* byte width of the field referenced by
-                                                                * each clause */
-       RegProcedure funcid;            /* ID of function associate with node */
-       Cost            cost = 0;               /* running expense */
-       LispValue       tmpclause;
-       LispValue       operand;                /* one operand of an operator */
-
-       if (IsA(node, Oper))
-       {
-               /* don't trust the opid in the Oper node.  Use the opno. */
-               if (!(funcid = get_opcode(get_opno((Oper) node))))
-                       elog(ERROR, "Oper's function is undefined");
-       }
-       else
-               funcid = get_funcid((Func) node);
-
-       /* look up tuple in cache */
-       tupl = SearchSysCacheTuple(PROCOID,
-                                                          ObjectIdGetDatum(funcid),
-                                                          0, 0, 0);
-       if (!HeapTupleIsValid(tupl))
-               elog(ERROR, "Cache lookup failed for procedure %u", funcid);
-       proc = (Form_pg_proc) GETSTRUCT(tupl);
-
-       /*
-        * * if it's a Postquel function, its cost is stored in the *
-        * associated plan.
-        */
-       if (proc->prolang == SQLlanguageId)
-       {
-               LispValue       tmpplan;
-               List            planlist;
-
-               if (IsA(node, Oper) ||get_func_planlist((Func) node) == LispNil)
-               {
-                       Oid                *argOidVect;         /* vector of argtypes */
-                       char       *pq_src; /* text of PQ function */
-                       int                     nargs;  /* num args to PQ function */
-                       QueryTreeList *queryTree_list;          /* dummy variable */
-
-                       /*
-                        * * plan the function, storing it in the Func node for later *
-                        * use by the executor.
-                        */
-                       pq_src = (char *) textout(&(proc->prosrc));
-                       nargs = proc->pronargs;
-                       if (nargs > 0)
-                               argOidVect = proc->proargtypes;
-                       planlist = (List) pg_parse_and_plan(pq_src, argOidVect, nargs,
-                                                                                  &parseTree_list, None, FALSE);
-                       if (IsA(node, Func))
-                               set_func_planlist((Func) node, planlist);
-
-               }
-               else
-               {                                               /* plan has been cached inside the Func
-                                                                * node already */
-                       planlist = get_func_planlist((Func) node);
-               }
-
-               /*
-                * * Return the sum of the costs of the plans (the PQ function *
-                * may have many queries in its body).
-                */
-               foreach(tmpplan, planlist)
-                       cost += get_cost((Plan) lfirst(tmpplan));
-               return cost;
-       }
-       else
-       {                                                       /* it's a C function */
-
-               /*
-                * *  find the cost of evaluating the function's arguments *  and
-                * the width of the operands
-                */
-               for (tmpclause = args; tmpclause != LispNil;
-                        tmpclause = lnext(tmpclause))
-               {
-
-                       if ((operand = lfirst(tmpclause)) != LispNil)
-                       {
-                               cost += xfunc_local_expense(operand);
-                               width += xfunc_width(operand);
-                       }
-               }
-
-               /*
-                * * when stats become available, add in cost of accessing
-                * secondary * and tertiary storage here.
-                */
-               return (cost +
-                               (Cost) proc->propercall_cpu +
-               (Cost) proc->properbyte_cpu * (Cost) proc->probyte_pct / 100.00 *
-                               (Cost) width
-
-               /*
-                * Pct_of_obj_in_mem DISK_COST * proc->probyte_pct/100.00 * width
-                * Pct_of_obj_on_disk + ARCH_COST * proc->probyte_pct/100.00 *
-                * width Pct_of_obj_on_arch
-                */
-                       );
-       }
-}
-
-/*
- ** xfunc_width
- **    recursively find the width of a expression
- */
-
-int
-xfunc_width(LispValue clause)
-{
-       Relation        rd;                             /* Relation Descriptor */
-       HeapTuple       tupl;                   /* structure to hold a cached tuple */
-       Form_pg_type type;                      /* structure to hold a type tuple */
-       int                     retval = 0;
-
-       if (IsA(clause, Const))
-       {
-               /* base case: width is the width of this constant */
-               retval = get_constlen((Const) clause);
-               goto exit;
-       }
-       else if (IsA(clause, ArrayRef))
-       {
-               /* base case: width is width of the refelem within the array */
-               retval = get_refelemlength((ArrayRef) clause);
-               goto exit;
-       }
-       else if (IsA(clause, Var))
-       {
-               /* base case: width is width of this attribute */
-               tupl = SearchSysCacheTuple(TYPEOID,
-                                                        ObjectIdGetDatum(get_vartype((Var) clause)),
-                                                                  0, 0, 0);
-               if (!HeapTupleIsValid(tupl))
-                       elog(ERROR, "Cache lookup failed for type %u",
-                                get_vartype((Var) clause));
-               type = (Form_pg_type) GETSTRUCT(tupl);
-               if (get_varattno((Var) clause) == 0)
-               {
-                       /* clause is a tuple.  Get its width */
-                       rd = heap_open(type->typrelid);
-                       retval = xfunc_tuple_width(rd);
-                       heap_close(rd);
-               }
-               else
-               {
-                       /* attribute is a base type */
-                       retval = type->typlen;
-               }
-               goto exit;
-       }
-       else if (IsA(clause, Param))
-       {
-               if (typeidTypeRelids(get_paramtype((Param) clause)))
-               {
-                       /* Param node returns a tuple.  Find its width */
-                       rd = heap_open(typeidTypeRelids(get_paramtype((Param) clause)));
-                       retval = xfunc_tuple_width(rd);
-                       heap_close(rd);
-               }
-               else if (get_param_tlist((Param) clause) != LispNil)
-               {
-                       /* Param node projects a complex type */
-                       Assert(length(get_param_tlist((Param) clause)) == 1);           /* sanity */
-                       retval = xfunc_width((LispValue)
-                                         get_expr(lfirst(get_param_tlist((Param) clause))));
-               }
-               else
-               {
-                       /* Param node returns a base type */
-                       retval = typeLen(typeidType(get_paramtype((Param) clause)));
-               }
-               goto exit;
-       }
-       else if (IsA(clause, Iter))
-       {
-               /*
-                * * An Iter returns a setof things, so return the width of a
-                * single * thing. * Note:      THIS MAY NOT WORK RIGHT WHEN AGGS GET
-                * FIXED, * SINCE AGG FUNCTIONS CHEW ON THE WHOLE SETOF THINGS!!!! *
-                * This whole Iter business is bogus, anyway.
-                */
-               retval = xfunc_width(get_iterexpr((Iter) clause));
-               goto exit;
-       }
-       else if (fast_is_clause(clause))
-       {
-               /*
-                * * get function associated with this Oper, and treat this as * a
-                * Func
-                */
-               tupl = SearchSysCacheTuple(OPEROID,
-                                          ObjectIdGetDatum(get_opno((Oper) get_op(clause))),
-                                                                  0, 0, 0);
-               if (!HeapTupleIsValid(tupl))
-                       elog(ERROR, "Cache lookup failed for procedure %u",
-                                get_opno((Oper) get_op(clause)));
-               return (xfunc_func_width
-               ((RegProcedure) (((Form_pg_operator) (GETSTRUCT(tupl)))->oprcode),
-                (LispValue) get_opargs(clause)));
-       }
-       else if (fast_is_funcclause(clause))
-       {
-               Func            func = (Func) get_function(clause);
-
-               if (get_func_tlist(func) != LispNil)
-               {
-                       /*
-                        * this function has a projection on it.  Get the length of
-                        * the projected attribute
-                        */
-                       Assert(length(get_func_tlist(func)) == 1);      /* sanity */
-                       retval = xfunc_width((LispValue)
-                                                                get_expr(lfirst(get_func_tlist(func))));
-                       goto exit;
-               }
-               else
-               {
-                       return (xfunc_func_width((RegProcedure) get_funcid(func),
-                                                                        (LispValue) get_funcargs(clause)));
-               }
-       }
-       else
-       {
-               elog(ERROR, "Clause node of undetermined type");
-               return -1;
-       }
-
-exit:
-       if (retval == -1)
-               retval = VARLEN_DEFAULT;
-       return retval;
-}
-
-/*
- ** xfunc_card_unreferenced:
- **   find all relations not referenced in clause, and multiply their
- ** cardinalities.     Ignore relation of cardinality 0.
- ** User may pass in referenced list, if they know it (useful
- ** for joins).
- */
-static Count
-xfunc_card_unreferenced(Query *queryInfo,
-                                               LispValue clause, Relids referenced)
-{
-       Relids          unreferenced,
-                               allrelids = LispNil;
-       LispValue       temp;
-
-       /* find all relids of base relations referenced in query */
-       foreach(temp, queryInfo->base_rel_list)
-       {
-               Assert(lnext(get_relids((RelOptInfo) lfirst(temp))) == LispNil);
-               allrelids = lappend(allrelids,
-                                                 lfirst(get_relids((RelOptInfo) lfirst(temp))));
-       }
-
-       /* find all relids referenced in query but not in clause */
-       if (!referenced)
-               referenced = xfunc_find_references(clause);
-       unreferenced = set_difference(allrelids, referenced);
-
-       return xfunc_card_product(unreferenced);
-}
-
-/*
- ** xfunc_card_product
- **   multiple together cardinalities of a list relations.
- */
-Count
-xfunc_card_product(Query *queryInfo, Relids relids)
-{
-       LispValue       cinfonode;
-       LispValue       temp;
-       RelOptInfo      currel;
-       Cost            tuples;
-       Count           retval = 0;
-
-       foreach(temp, relids)
-       {
-               currel = get_rel(lfirst(temp));
-               tuples = get_tuples(currel);
-
-               if (tuples)
-               {                                               /* not of cardinality 0 */
-                       /* factor in the selectivity of all zero-cost clauses */
-                       foreach(cinfonode, get_restrictinfo(currel))
-                       {
-                               if (!xfunc_expense(queryInfo, get_clause((RestrictInfo) lfirst(cinfonode))))
-                                       tuples *= compute_clause_selec(queryInfo,
-                                                       get_clause((RestrictInfo) lfirst(cinfonode)),
-                                                                                                  LispNil);
-                       }
-
-                       if (retval == 0)
-                               retval = tuples;
-                       else
-                               retval *= tuples;
-               }
-       }
-       if (retval == 0)
-               retval = 1;                             /* saves caller from dividing by zero */
-       return retval;
-}
-
-
-/*
- ** xfunc_find_references:
- **   Traverse a clause and find all relids referenced in the clause.
- */
-List
-xfunc_find_references(LispValue clause)
-{
-       List            retval = (List) LispNil;
-       LispValue       tmpclause;
-
-       /* Base cases */
-       if (IsA(clause, Var))
-               return lispCons(lfirst(get_varid((Var) clause)), LispNil);
-       else if (IsA(clause, Const) ||IsA(clause, Param))
-               return (List) LispNil;
-
-       /* recursion */
-       else if (IsA(clause, Iter))
-
-               /*
-                * Too low. Should multiply by the expected number of iterations.
-                * maybe
-                */
-               return xfunc_find_references(get_iterexpr((Iter) clause));
-       else if (IsA(clause, ArrayRef))
-               return xfunc_find_references(get_refexpr((ArrayRef) clause));
-       else if (fast_is_clause(clause))
-       {
-               /* string together result of all operands of Oper */
-               for (tmpclause = (LispValue) get_opargs(clause); tmpclause != LispNil;
-                        tmpclause = lnext(tmpclause))
-                       retval = nconc(retval, xfunc_find_references(lfirst(tmpclause)));
-               return retval;
-       }
-       else if (fast_is_funcclause(clause))
-       {
-               /* string together result of all args of Func */
-               for (tmpclause = (LispValue) get_funcargs(clause);
-                        tmpclause != LispNil;
-                        tmpclause = lnext(tmpclause))
-                       retval = nconc(retval, xfunc_find_references(lfirst(tmpclause)));
-               return retval;
-       }
-       else if (fast_not_clause(clause))
-               return xfunc_find_references(lsecond(clause));
-       else if (fast_or_clause(clause) || fast_and_clause(clause))
-       {
-               /* string together result of all operands of OR */
-               for (tmpclause = lnext(clause); tmpclause != LispNil;
-                        tmpclause = lnext(tmpclause))
-                       retval = nconc(retval, xfunc_find_references(lfirst(tmpclause)));
-               return retval;
-       }
-       else
-       {
-               elog(ERROR, "Clause node of undetermined type");
-               return (List) LispNil;
-       }
-}
-
-/*
- ** xfunc_primary_join:
- **   Find the primary join clause: for Hash and Merge Joins, this is the
- ** min rank Hash or Merge clause, while for Nested Loop it's the
- ** min rank pathclause
- */
-LispValue
-xfunc_primary_join(JoinPath pathnode)
-{
-       LispValue       joinclauselist = get_pathrestrictinfo(pathnode);
-       RestrictInfo mincinfo;
-       LispValue       tmplist;
-       LispValue       minclause = LispNil;
-       Cost            minrank,
-                               tmprank;
-
-       if (IsA(pathnode, MergePath))
-       {
-               for (tmplist = get_path_mergeclauses((MergePath) pathnode),
-                        minclause = lfirst(tmplist),
-                        minrank = xfunc_rank(minclause);
-                        tmplist != LispNil;
-                        tmplist = lnext(tmplist))
-                       if ((tmprank = xfunc_rank(lfirst(tmplist)))
-                               < minrank)
-                       {
-                               minrank = tmprank;
-                               minclause = lfirst(tmplist);
-                       }
-               return minclause;
-       }
-       else if (IsA(pathnode, HashPath))
-       {
-               for (tmplist = get_path_hashclauses((HashPath) pathnode),
-                        minclause = lfirst(tmplist),
-                        minrank = xfunc_rank(minclause);
-                        tmplist != LispNil;
-                        tmplist = lnext(tmplist))
-                       if ((tmprank = xfunc_rank(lfirst(tmplist)))
-                               < minrank)
-                       {
-                               minrank = tmprank;
-                               minclause = lfirst(tmplist);
-                       }
-               return minclause;
-       }
-
-       /* if we drop through, it's nested loop join */
-       if (joinclauselist == LispNil)
-               return LispNil;
-
-       for (tmplist = joinclauselist, mincinfo = (RestrictInfo) lfirst(joinclauselist),
-                minrank = xfunc_rank(get_clause((RestrictInfo) lfirst(tmplist)));
-                tmplist != LispNil;
-                tmplist = lnext(tmplist))
-               if ((tmprank = xfunc_rank(get_clause((RestrictInfo) lfirst(tmplist))))
-                       < minrank)
-               {
-                       minrank = tmprank;
-                       mincinfo = (RestrictInfo) lfirst(tmplist);
-               }
-       return (LispValue) get_clause(mincinfo);
-}
-
-/*
- ** xfunc_get_path_cost
- **   get the expensive function costs of the path
- */
-Cost
-xfunc_get_path_cost(Query *queryInfo, Path pathnode)
-{
-       Cost            cost = 0;
-       LispValue       tmplist;
-       Cost            selec = 1.0;
-
-       /*
-        * * first add in the expensive local function costs. * We ensure that
-        * the clauses are sorted by rank, so that we * know (via
-        * selectivities) the number of tuples that will be checked * by each
-        * function.  If we're not doing any optimization of expensive *
-        * functions, we don't sort.
-        */
-       if (XfuncMode != XFUNC_OFF)
-               set_locrestrictinfo(pathnode, lisp_qsort(get_loc_restrictinfo(pathnode),
-                                                                                                xfunc_cinfo_compare));
-       for (tmplist = get_loc_restrictinfo(pathnode), selec = 1.0;
-                tmplist != LispNil;
-                tmplist = lnext(tmplist))
-       {
-               cost += (Cost) (xfunc_local_expense(get_clause((RestrictInfo) lfirst(tmplist)))
-                                         * (Cost) get_tuples(get_parent(pathnode)) * selec);
-               selec *= compute_clause_selec(queryInfo,
-                                                         get_clause((RestrictInfo) lfirst(tmplist)),
-                                                                         LispNil);
-       }
-
-       /*
-        * * Now add in any node-specific expensive function costs. * Again,
-        * we must ensure that the clauses are sorted by rank.
-        */
-       if (IsA(pathnode, JoinPath))
-       {
-               if (XfuncMode != XFUNC_OFF)
-                       set_pathrestrictinfo((JoinPath) pathnode, lisp_qsort
-                                                         (get_pathrestrictinfo((JoinPath) pathnode),
-                                                          xfunc_cinfo_compare));
-               for (tmplist = get_pathrestrictinfo((JoinPath) pathnode), selec = 1.0;
-                        tmplist != LispNil;
-                        tmplist = lnext(tmplist))
-               {
-                       cost += (Cost) (xfunc_local_expense(get_clause((RestrictInfo) lfirst(tmplist)))
-                                         * (Cost) get_tuples(get_parent(pathnode)) * selec);
-                       selec *= compute_clause_selec(queryInfo,
-                                                         get_clause((RestrictInfo) lfirst(tmplist)),
-                                                                                 LispNil);
-               }
-       }
-       if (IsA(pathnode, HashPath))
-       {
-               if (XfuncMode != XFUNC_OFF)
-                       set_path_hashclauses
-                               ((HashPath) pathnode,
-                                lisp_qsort(get_path_hashclauses((HashPath) pathnode),
-                                                       xfunc_clause_compare));
-               for (tmplist = get_path_hashclauses((HashPath) pathnode), selec = 1.0;
-                        tmplist != LispNil;
-                        tmplist = lnext(tmplist))
-               {
-                       cost += (Cost) (xfunc_local_expense(lfirst(tmplist))
-                                         * (Cost) get_tuples(get_parent(pathnode)) * selec);
-                       selec *= compute_clause_selec(queryInfo,
-                                                                                 lfirst(tmplist), LispNil);
-               }
-       }
-       if (IsA(pathnode, MergePath))
-       {
-               if (XfuncMode != XFUNC_OFF)
-                       set_path_mergeclauses
-                               ((MergePath) pathnode,
-                                lisp_qsort(get_path_mergeclauses((MergePath) pathnode),
-                                                       xfunc_clause_compare));
-               for (tmplist = get_path_mergeclauses((MergePath) pathnode), selec = 1.0;
-                        tmplist != LispNil;
-                        tmplist = lnext(tmplist))
-               {
-                       cost += (Cost) (xfunc_local_expense(lfirst(tmplist))
-                                         * (Cost) get_tuples(get_parent(pathnode)) * selec);
-                       selec *= compute_clause_selec(queryInfo,
-                                                                                 lfirst(tmplist), LispNil);
-               }
-       }
-       Assert(cost >= 0);
-       return cost;
-}
-
-/*
- ** Recalculate the cost of a path node.  This includes the basic cost of the
- ** node, as well as the cost of its expensive functions.
- ** We need to do this to the parent after pulling a clause from a child into a
- ** parent.  Thus we should only be calling this function on JoinPaths.
- */
-Cost
-xfunc_total_path_cost(JoinPath pathnode)
-{
-       Cost            cost = xfunc_get_path_cost((Path) pathnode);
-
-       Assert(IsA(pathnode, JoinPath));
-       if (IsA(pathnode, MergePath))
-       {
-               MergePath       mrgnode = (MergePath) pathnode;
-
-               cost += cost_mergejoin(get_path_cost((Path) get_outerjoinpath(mrgnode)),
-                                               get_path_cost((Path) get_innerjoinpath(mrgnode)),
-                                                          get_outersortkeys(mrgnode),
-                                                          get_innersortkeys(mrgnode),
-                                                  get_tuples(get_parent((Path) get_outerjoinpath
-                                                                                                (mrgnode))),
-                                                  get_tuples(get_parent((Path) get_innerjoinpath
-                                                                                                (mrgnode))),
-                                                       get_width(get_parent((Path) get_outerjoinpath
-                                                                                                (mrgnode))),
-                                                       get_width(get_parent((Path) get_innerjoinpath
-                                                                                                (mrgnode))));
-               Assert(cost >= 0);
-               return cost;
-       }
-       else if (IsA(pathnode, HashPath))
-       {
-               HashPath hashnode = (HashPath) pathnode;
-
-               cost += cost_hashjoin(get_path_cost((Path) get_outerjoinpath(hashnode)),
-                                          get_path_cost((Path) get_innerjoinpath(hashnode)),
-                                                         get_outerhashkeys(hashnode),
-                                                         get_innerhashkeys(hashnode),
-                                                  get_tuples(get_parent((Path) get_outerjoinpath
-                                                                                                (hashnode))),
-                                                  get_tuples(get_parent((Path) get_innerjoinpath
-                                                                                                (hashnode))),
-                                                       get_width(get_parent((Path) get_outerjoinpath
-                                                                                                (hashnode))),
-                                                       get_width(get_parent((Path) get_innerjoinpath
-                                                                                                (hashnode))));
-               Assert(cost >= 0);
-               return cost;
-       }
-       else
-/* Nested Loop Join */
-       {
-               cost += cost_nestloop(get_path_cost((Path) get_outerjoinpath(pathnode)),
-                                          get_path_cost((Path) get_innerjoinpath(pathnode)),
-                                                  get_tuples(get_parent((Path) get_outerjoinpath
-                                                                                                (pathnode))),
-                                                  get_tuples(get_parent((Path) get_innerjoinpath
-                                                                                                (pathnode))),
-                                                       get_pages(get_parent((Path) get_outerjoinpath
-                                                                                                (pathnode))),
-                                                       IsA(get_innerjoinpath(pathnode), IndexPath));
-               Assert(cost >= 0);
-               return cost;
-       }
-}
-
-
-/*
- ** xfunc_expense_per_tuple
- **    return the expense of the join *per-tuple* of the input relation.
- ** The cost model here is that a join costs
- **            k*card(outer)*card(inner) + l*card(outer) + m*card(inner) + n
- **
- ** We treat the l and m terms by considering them to be like restrictions
- ** constrained to be right under the join.  Thus the cost per inner and
- ** cost per outer of the join is different, reflecting these virtual nodes.
- **
- ** The cost per tuple of outer is k + l/referenced(inner).  Cost per tuple
- ** of inner is k + m/referenced(outer).
- ** The constants k, l, m and n depend on the join method.     Measures here are
- ** based on the costs in costsize.c, with fudging for HashJoin and Sorts to
- ** make it fit our model (the 'q' in HashJoin results in a
- ** card(outer)/card(inner) term, and sorting results in a log term.
-
- */
-Cost
-xfunc_expense_per_tuple(JoinPath joinnode, int whichchild)
-{
-       RelOptInfo      outerrel = get_parent((Path) get_outerjoinpath(joinnode));
-       RelOptInfo      innerrel = get_parent((Path) get_innerjoinpath(joinnode));
-       Count           outerwidth = get_width(outerrel);
-       Count           outers_per_page = ceil(BLCKSZ / (outerwidth + MinTupleSize));
-
-       if (IsA(joinnode, HashPath))
-       {
-               if (whichchild == INNER)
-                       return (1 + cpu_page_weight) * outers_per_page / NBuffers;
-               else
-                       return (((1 + cpu_page_weight) * outers_per_page / NBuffers)
-                                       + cpu_page_weight
-                                       / xfunc_card_product(get_relids(innerrel)));
-       }
-       else if (IsA(joinnode, MergePath))
-       {
-               /* assumes sort exists, and costs one (I/O + CPU) per tuple */
-               if (whichchild == INNER)
-                       return ((2 * cpu_page_weight + 1)
-                                       / xfunc_card_product(get_relids(outerrel)));
-               else
-                       return ((2 * cpu_page_weight + 1)
-                                       / xfunc_card_product(get_relids(innerrel)));
-       }
-       else
-/* nestloop */
-       {
-               Assert(IsA(joinnode, JoinPath));
-               return cpu_page_weight;
-       }
-}
-
-/*
- ** xfunc_fixvars
- ** After pulling up a clause, we must walk its expression tree, fixing Var
- ** nodes to point to the correct varno (either INNER or OUTER, depending
- ** on which child the clause was pulled from), and the right varattno in the
- ** target list of the child's former relation.  If the target list of the
- ** child RelOptInfo does not contain the attribute we need, we add it.
- */
-void
-xfunc_fixvars(LispValue clause, /* clause being pulled up */
-                         RelOptInfo rel,       /* rel it's being pulled from */
-                         int varno)            /* whether rel is INNER or OUTER of join */
-{
-       LispValue       tmpclause;              /* temporary variable */
-       TargetEntry *tle;                       /* tlist member corresponding to var */
-
-
-       if (IsA(clause, Const) ||IsA(clause, Param))
-               return;
-       else if (IsA(clause, Var))
-       {
-               /* here's the meat */
-               tle = tlistentry_member((Var) clause, get_targetlist(rel));
-               if (tle == LispNil)
-               {
-                       /*
-                        * * The attribute we need is not in the target list, * so we
-                        * have to add it. *
-                        *
-                        */
-                       add_var_to_tlist(rel, (Var) clause);
-                       tle = tlistentry_member((Var) clause, get_targetlist(rel));
-               }
-               set_varno(((Var) clause), varno);
-               set_varattno(((Var) clause), get_resno(get_resdom(get_entry(tle))));
-       }
-       else if (IsA(clause, Iter))
-               xfunc_fixvars(get_iterexpr((Iter) clause), rel, varno);
-       else if (fast_is_clause(clause))
-       {
-               xfunc_fixvars(lfirst(lnext(clause)), rel, varno);
-               xfunc_fixvars(lfirst(lnext(lnext(clause))), rel, varno);
-       }
-       else if (fast_is_funcclause(clause))
-               for (tmpclause = lnext(clause); tmpclause != LispNil;
-                        tmpclause = lnext(tmpclause))
-                       xfunc_fixvars(lfirst(tmpclause), rel, varno);
-       else if (fast_not_clause(clause))
-               xfunc_fixvars(lsecond(clause), rel, varno);
-       else if (fast_or_clause(clause) || fast_and_clause(clause))
-               for (tmpclause = lnext(clause); tmpclause != LispNil;
-                        tmpclause = lnext(tmpclause))
-                       xfunc_fixvars(lfirst(tmpclause), rel, varno);
-       else
-               elog(ERROR, "Clause node of undetermined type");
-}
-
-
-/*
- ** Comparison function for lisp_qsort() on a list of RestrictInfo's.
- ** arg1 and arg2 should really be of type (RestrictInfo *).
- */
-int
-xfunc_cinfo_compare(void *arg1, void *arg2)
-{
-       RestrictInfo info1 = *(RestrictInfo *) arg1;
-       RestrictInfo info2 = *(RestrictInfo *) arg2;
-
-       LispValue       clause1 = (LispValue) get_clause(info1),
-                               clause2 = (LispValue) get_clause(info2);
-
-       return xfunc_clause_compare((void *) &clause1, (void *) &clause2);
-}
-
-/*
- ** xfunc_clause_compare: comparison function for lisp_qsort() that compares two
- ** clauses based on expense/(1 - selectivity)
- ** arg1 and arg2 are really pointers to clauses.
- */
-int
-xfunc_clause_compare(void *arg1, void *arg2)
-{
-       LispValue       clause1 = *(LispValue *) arg1;
-       LispValue       clause2 = *(LispValue *) arg2;
-       Cost            rank1,                  /* total xfunc rank of clause1 */
-                               rank2;                  /* total xfunc rank of clause2 */
-
-       rank1 = xfunc_rank(clause1);
-       rank2 = xfunc_rank(clause2);
-
-       if (rank1 < rank2)
-               return -1;
-       else if (rank1 == rank2)
-               return 0;
-       else
-               return 1;
-}
-
-/*
- ** xfunc_disjunct_sort
- **   given a list of clauses, for each clause sort the disjuncts by cost
- **   (this assumes the predicates have been converted to Conjunctive NF)
- **   Modifies the clause list!
- */
-void
-xfunc_disjunct_sort(LispValue clause_list)
-{
-       LispValue       temp;
-
-       foreach(temp, clause_list)
-               if (or_clause(lfirst(temp)))
-               lnext(lfirst(temp)) = lisp_qsort(lnext(lfirst(temp)), xfunc_disjunct_compare);
-}
-
-
-/*
- ** xfunc_disjunct_compare: comparison function for qsort() that compares two
- ** disjuncts based on cost/selec.
- ** arg1 and arg2 are really pointers to disjuncts
- */
-int
-xfunc_disjunct_compare(Query *queryInfo, void *arg1, void *arg2)
-{
-       LispValue       disjunct1 = *(LispValue *) arg1;
-       LispValue       disjunct2 = *(LispValue *) arg2;
-       Cost            cost1,                  /* total cost of disjunct1 */
-                               cost2,                  /* total cost of disjunct2 */
-                               selec1,
-                               selec2;
-       Cost            rank1,
-                               rank2;
-
-       cost1 = xfunc_expense(queryInfo, disjunct1);
-       cost2 = xfunc_expense(queryInfo, disjunct2);
-       selec1 = compute_clause_selec(queryInfo,
-                                                                 disjunct1, LispNil);
-       selec2 = compute_clause_selec(queryInfo,
-                                                                 disjunct2, LispNil);
-
-       if (selec1 == 0)
-               rank1 = MAXFLOAT;
-       else if (cost1 == 0)
-               rank1 = 0;
-       else
-               rank1 = cost1 / selec1;
-
-       if (selec2 == 0)
-               rank2 = MAXFLOAT;
-       else if (cost2 == 0)
-               rank2 = 0;
-       else
-               rank2 = cost2 / selec2;
-
-       if (rank1 < rank2)
-               return -1;
-       else if (rank1 == rank2)
-               return 0;
-       else
-               return 1;
-}
-
-/* ------------------------ UTILITY FUNCTIONS ------------------------------- */
-/*
- ** xfunc_func_width
- **    Given a function OID and operands, find the width of the return value.
- */
-int
-xfunc_func_width(RegProcedure funcid, LispValue args)
-{
-       Relation        rd;                             /* Relation Descriptor */
-       HeapTuple       tupl;                   /* structure to hold a cached tuple */
-       Form_pg_proc proc;                      /* structure to hold the pg_proc tuple */
-       Form_pg_type type;                      /* structure to hold the pg_type tuple */
-       LispValue       tmpclause;
-       int                     retval;
-
-       /* lookup function and find its return type */
-       Assert(RegProcedureIsValid(funcid));
-       tupl = SearchSysCacheTuple(PROCOID,
-                                                          ObjectIdGetDatum(funcid),
-                                                          0, 0, 0);
-       if (!HeapTupleIsValid(tupl))
-               elog(ERROR, "Cache lookup failed for procedure %u", funcid);
-       proc = (Form_pg_proc) GETSTRUCT(tupl);
-
-       /* if function returns a tuple, get the width of that */
-       if (typeidTypeRelids(proc->prorettype))
-       {
-               rd = heap_open(typeidTypeRelids(proc->prorettype));
-               retval = xfunc_tuple_width(rd);
-               heap_close(rd);
-               goto exit;
-       }
-       else
-/* function returns a base type */
-       {
-               tupl = SearchSysCacheTuple(TYPEOID,
-                                                                  ObjectIdGetDatum(proc->prorettype),
-                                                                  0, 0, 0);
-               if (!HeapTupleIsValid(tupl))
-                       elog(ERROR, "Cache lookup failed for type %u", proc->prorettype);
-               type = (Form_pg_type) GETSTRUCT(tupl);
-               /* if the type length is known, return that */
-               if (type->typlen != -1)
-               {
-                       retval = type->typlen;
-                       goto exit;
-               }
-               else
-/* estimate the return size */
-               {
-                       /* find width of the function's arguments */
-                       for (tmpclause = args; tmpclause != LispNil;
-                                tmpclause = lnext(tmpclause))
-                               retval += xfunc_width(lfirst(tmpclause));
-                       /* multiply by outin_ratio */
-                       retval = (int) (proc->prooutin_ratio / 100.0 * retval);
-                       goto exit;
-               }
-       }
-exit:
-       return retval;
-}
-
-/*
- ** xfunc_tuple_width
- **            Return the sum of the lengths of all the attributes of a given relation
- */
-int
-xfunc_tuple_width(Relation rd)
-{
-       int                     i;
-       int                     retval = 0;
-       TupleDesc       tdesc = RelationGetDescr(rd);
-
-       for (i = 0; i < tdesc->natts; i++)
-       {
-               if (tdesc->attrs[i]->attlen != -1)
-                       retval += tdesc->attrs[i]->attlen;
-               else
-                       retval += VARLEN_DEFAULT;
-       }
-
-       return retval;
-}
-
-/*
- ** xfunc_num_join_clauses
- **   Find the number of join clauses associated with this join path
- */
-int
-xfunc_num_join_clauses(JoinPath path)
-{
-       int                     num = length(get_pathrestrictinfo(path));
-
-       if (IsA(path, MergePath))
-               return num + length(get_path_mergeclauses((MergePath) path));
-       else if (IsA(path, HashPath))
-               return num + length(get_path_hashclauses((HashPath) path));
-       else
-               return num;
-}
-
-/*
- ** xfunc_LispRemove
- **   Just like LispRemove, but it whines if the item to be removed ain't there
- */
-LispValue
-xfunc_LispRemove(LispValue foo, List bar)
-{
-       LispValue       temp = LispNil;
-       LispValue       result = LispNil;
-       int                     sanity = false;
-
-       for (temp = bar; !null(temp); temp = lnext(temp))
-               if (!equal((Node) (foo), (Node) (lfirst(temp))))
-                       result = lappend(result, lfirst(temp));
-               else
-                       sanity = true;          /* found a matching item to remove! */
-
-       if (!sanity)
-               elog(ERROR, "xfunc_LispRemove: didn't find a match!");
-
-       return result;
-}
-
-#define Node_Copy(a, b, c, d) \
-do { \
-       if (NodeCopy((Node)((a)->d), (Node*)&((b)->d), c) != true) \
-       { \
-               return false; \
-       } \
-} while(0)
-
-/*
- ** xfunc_copyrel
- **   Just like _copyRel, but doesn't copy the paths
- */
-bool
-xfunc_copyrel(RelOptInfo from, RelOptInfo *to)
-{
-       RelOptInfo      newnode;
-
-       Pointer         (*alloc) () = palloc;
-
-       /* COPY_CHECKARGS() */
-       if (to == NULL)
-               return false;
-
-       /* COPY_CHECKNULL() */
-       if (from == NULL)
-       {
-               (*to) = NULL;
-               return true;
-       }
-
-       /* COPY_NEW(c) */
-       newnode = (RelOptInfo) (*alloc) (classSize(RelOptInfo));
-       if (newnode == NULL)
-               return false;
-
-       /*
-        * copy node superclass fields
-        */
-       CopyNodeFields((Node) from, (Node) newnode, alloc);
-
-       /*
-        * copy remainder of node
-        */
-       Node_Copy(from, newnode, alloc, relids);
-
-       newnode->indexed = from->indexed;
-       newnode->pages = from->pages;
-       newnode->tuples = from->tuples;
-       newnode->size = from->size;
-       newnode->width = from->width;
-
-       Node_Copy(from, newnode, alloc, targetlist);
-
-       /*
-        * No!!!!        Node_Copy(from, newnode, alloc, pathlist);
-        * Node_Copy(from, newnode, alloc, unorderedpath); Node_Copy(from,
-        * newnode, alloc, cheapestpath);
-        */
-#if 0                                                  /* can't use Node_copy now. 2/95 -ay */
-       Node_Copy(from, newnode, alloc, classlist);
-       Node_Copy(from, newnode, alloc, indexkeys);
-       Node_Copy(from, newnode, alloc, ordering);
-#endif
-       Node_Copy(from, newnode, alloc, restrictinfo);
-       Node_Copy(from, newnode, alloc, joininfo);
-       Node_Copy(from, newnode, alloc, innerjoin);
-
-       (*to) = newnode;
-       return true;
-}
diff --git a/src/include/optimizer/_deadcode/xfunc.h b/src/include/optimizer/_deadcode/xfunc.h
deleted file mode 100644 (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 */