diff options
author | Peter Eisentraut <peter_e@gmx.net> | 2002-07-24 19:16:43 +0000 |
---|---|---|
committer | Peter Eisentraut <peter_e@gmx.net> | 2002-07-24 19:16:43 +0000 |
commit | 43515ba3f8523e492143e2a1a1159022b5424431 (patch) | |
tree | 869ce476017bc4bfd40b781717f7846bc79c1f05 /src/backend/commands | |
parent | 739adf32eecfe129aea09f543370d886045c7c01 (diff) | |
download | postgresql-43515ba3f8523e492143e2a1a1159022b5424431.tar.gz postgresql-43515ba3f8523e492143e2a1a1159022b5424431.zip |
Remove _deadcode.
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/_deadcode/recipe.c | 1318 | ||||
-rw-r--r-- | src/backend/commands/_deadcode/version.c | 346 |
2 files changed, 0 insertions, 1664 deletions
diff --git a/src/backend/commands/_deadcode/recipe.c b/src/backend/commands/_deadcode/recipe.c deleted file mode 100644 index f1b3d84ab48..00000000000 --- a/src/backend/commands/_deadcode/recipe.c +++ /dev/null @@ -1,1318 +0,0 @@ -/*------------------------------------------------------------------------- - * - * recipe.c - * routines for handling execution of Tioga recipes - * - * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/_deadcode/Attic/recipe.c,v 1.17 2002/06/20 20:29:27 momjian Exp $ - * - *------------------------------------------------------------------------- - */ -#include "postgres.h" - -#include "catalog/pg_type.h" -#include "commands/recipe.h" -#include "executor/executor.h" -#include "libpq/libpq-be.h" -#include "nodes/execnodes.h" -#include "nodes/makefuncs.h" -#include "nodes/parsenodes.h" -#include "nodes/plannodes.h" -#include "optimizer/planner.h" -#include "parser/parse_node.h" -#include "rewrite/rewriteHandler.h" -#include "rewrite/rewriteManip.h" -#include "tcop/dest.h" -#include "tcop/pquery.h" -#include "utils/builtins.h" -#include "utils/relcache.h" - -/* from tcop/postgres.c */ -extern CommandDest whereToSendOutput; - -#ifndef TIOGA - -void -beginRecipe(RecipeStmt *stmt) -{ - elog(WARNING, "You must compile with TIOGA defined in order to use recipes\n"); -} - -#else - -#include "tioga/tgRecipe.h" - -#define DEBUG_RECIPE 1 - -/* structure to keep track of the tee node plans */ -typedef struct _teePlanInfo -{ - char *tpi_relName; - Query *tpi_parsetree; - Plan *tpi_plan; -} TeePlanInfo; - -typedef struct _teeInfo -{ - int num; - TeePlanInfo *val; -} TeeInfo; - -QueryTreeList *appendQlist(QueryTreeList * q1, QueryTreeList * q2); -void OffsetVarAttno(Node *node, int varno, int offset); - -static void appendTeeQuery(TeeInfo * teeInfo, - QueryTreeList * q, - char *teeNodeName); - -static Plan *replaceTeeScans(Plan *plan, - Query *parsetree, - TeeInfo * teeInfo); -static void replaceSeqScan(Plan *plan, - Plan *parent, - int rt_ind, - Plan *tplan); - -static void tg_rewriteQuery(TgRecipe * r, TgNode * n, - QueryTreeList * q, - QueryTreeList * inputQlist); -static Node *tg_replaceNumberedParam(Node *expression, - int pnum, - int rt_ind, - char *teeRelName); -static Node *tg_rewriteParamsInExpr(Node *expression, - QueryTreeList * inputQlist); -static QueryTreeList *tg_parseSubQuery(TgRecipe * r, - TgNode * n, - TeeInfo * teeInfo); -static QueryTreeList *tg_parseTeeNode(TgRecipe * r, - TgNode * n, - int i, - QueryTreeList * qList, - TeeInfo * teeInfo); - - -/* - The Tioga recipe rewrite algorithm: - - To parse a Tioga recipe, we start from an eye node and go backwards through - its input nodes. To rewrite a Tioga node, we do the following: - - 1) parse the node we're at in the standard way (calling parser() ) - 2) rewrite its input nodes recursively using Tioga rewrite - 3) now, with the rewritten input parse trees and the original parse tree - of the node, we rewrite the the node. - To do the rewrite, we use the target lists, range tables, and - qualifications of the input parse trees -*/ - -/* - * beginRecipe: - * this is the main function to recipe execution - * this function is invoked for EXECUTE RECIPE ... statements - * - * takes in a RecipeStmt structure from the parser - * and returns a list of cursor names - */ - -void -beginRecipe(RecipeStmt *stmt) -{ - TgRecipe *r; - int i, - numTees; - QueryTreeList *qList; - char portalName[1024]; - - Plan *plan; - TupleDesc attinfo; - QueryDesc *queryDesc; - Query *parsetree; - - TeeInfo *teeInfo; - - /* - * retrieveRecipe() reads the recipe from the database and returns a - * TgRecipe* structure we can work with - */ - - r = retrieveRecipe(stmt->recipeName); - - if (r == NULL) - return; - - /* find the number of tees in the recipe */ - numTees = r->tees->num; - - if (numTees > 0) - { - /* allocate a teePlan structure */ - teeInfo = (TeeInfo *) malloc(sizeof(TeeInfo)); - teeInfo->num = numTees; - teeInfo->val = (TeePlanInfo *) malloc(numTees * sizeof(TeePlanInfo)); - for (i = 0; i < numTees; i++) - { - teeInfo->val[i].tpi_relName = r->tees->val[i]->nodeName; - teeInfo->val[i].tpi_parsetree = NULL; - teeInfo->val[i].tpi_plan = NULL; - } - } - else - teeInfo = NULL; - - /* - * for each viewer in the recipe, go backwards from each viewer input - * and generate a plan. Attach the plan to cursors. - */ - for (i = 0; i < r->eyes->num; i++) - { - TgNodePtr e; - - e = r->eyes->val[i]; - if (e->inNodes->num > 1) - { - elog(WARNING, - "beginRecipe: Currently eyes cannot have more than one input"); - } - if (e->inNodes->num == 0) - { - /* no input to this eye, skip it */ - continue; - } - -#ifdef DEBUG_RECIPE - elog(WARNING, "beginRecipe: eyes[%d] = %s\n", i, e->nodeName); -#endif /* DEBUG_RECIPE */ - - qList = tg_parseSubQuery(r, e->inNodes->val[0], teeInfo); - - if (qList == NULL) - { - /* eye is directly connected to a tee node */ - /* XXX TODO: handle this case */ - } - - /* now, plan the queries */ - - /* - * should really do everything pg_plan() does, but for now, we - * skip the rule rewrite and time qual stuff - */ - - /* - * 1) plan the main query, everything from an eye node back to a - * Tee - */ - parsetree = qList->qtrees[0]; - - /* - * before we plan, we want to see all the changes we did, during - * the rewrite phase, such as creating the tee tables, - * CommandCounterIncrement() allows us to see the changes - */ - CommandCounterIncrement(); - - plan = planner(parsetree); - - /* - * 2) plan the tee queries, (subgraphs rooted from a Tee) by the - * time the eye is processed, all tees that contribute to that eye - * will have been included in the teeInfo list - */ - if (teeInfo) - { - int t; - Plan *tplan; - Tee *newplan; - - for (t = 0; t < teeInfo->num; t++) - { - if (teeInfo->val[t].tpi_plan == NULL) - { - /* plan it in the usual fashion */ - tplan = planner(teeInfo->val[t].tpi_parsetree); - - /* now add a tee node to the root of the plan */ - elog(WARNING, "adding tee plan node to the root of the %s\n", - teeInfo->val[t].tpi_relName); - newplan = (Tee *) makeNode(Tee); - newplan->plan.targetlist = tplan->targetlist; - newplan->plan.qual = NULL; /* tplan->qual; */ - newplan->plan.lefttree = tplan; - newplan->plan.righttree = NULL; - newplan->leftParent = NULL; - newplan->rightParent = NULL; - - /* - * the range table of the tee is the range table of - * the tplan - */ - newplan->rtentries = teeInfo->val[t].tpi_parsetree->rtable; - strcpy(newplan->teeTableName, - teeInfo->val[t].tpi_relName); - teeInfo->val[t].tpi_plan = (Plan *) newplan; - } - } - - /* - * 3) replace the tee table scans in the main plan with actual - * tee plannodes - */ - - plan = replaceTeeScans(plan, parsetree, teeInfo); - - } /* if (teeInfo) */ - - /* define a portal for this viewer input */ - /* for now, eyes can only have one input */ - snprintf(portalName, 1024, "%s%d", e->nodeName, 0); - - queryDesc = CreateQueryDesc(parsetree, - plan, - whereToSendOutput); - - /* - * call ExecStart to prepare the plan for execution - */ - attinfo = ExecutorStart(queryDesc, NULL); - - ProcessPortal(portalName, - parsetree, - plan, - attinfo, - whereToSendOutput); - elog(WARNING, "beginRecipe: cursor named %s is now available", portalName); - } - -} - - - -/* - * tg_rewriteQuery - - * r - the recipe being rewritten - * n - the node that we're current at - * q - a QueryTree List containing the parse tree of the node - * inputQlist - the parsetrees of its input nodes, - * the size of inputQlist must be the same as the - * number of input nodes. Some elements in the inpuQlist - * may be null if the inputs to those nodes are unconnected - * - * this is the main routine for rewriting the recipe queries - * the original query tree 'q' is modified - */ - -static void -tg_rewriteQuery(TgRecipe * r, - TgNode * n, - QueryTreeList * q, - QueryTreeList * inputQlist) -{ - Query *orig; - Query *inputQ; - int i; - List *rtable; - List *input_rtable; - int rt_length; - - /* orig is the original parse tree of the node */ - orig = q->qtrees[0]; - - - /* - * step 1: - * - * form a combined range table from all the range tables in the original - * query as well as the input nodes - * - * form a combined qualification from the qual in the original plus the - * quals of the input nodes - */ - - /* start with the original range table */ - rtable = orig->rtable; - rt_length = length(rtable); - - for (i = 0; i < n->inNodes->num; i++) - { - if (n->inNodes->val[i] != NULL && - n->inNodes->val[i]->nodeType != TG_TEE_NODE) - { - inputQ = inputQlist->qtrees[i]; - input_rtable = inputQ->rtable; - - /* - * need to offset the var nodes in the qual and targetlist - * because they are indexed off the original rtable - */ - OffsetVarNodes((Node *) inputQ->qual, rt_length, 0); - OffsetVarNodes((Node *) inputQ->targetList, rt_length, 0); - - /* append the range tables from the children nodes */ - rtable = nconc(rtable, input_rtable); - - /* - * append the qualifications of the child node into the - * original qual list - */ - AddQual(orig, inputQ->qual); - } - } - orig->rtable = rtable; - - /* - * step 2: rewrite the target list of the original parse tree if there - * are any references to params, replace them with the appropriate - * target list entry of the children node - */ - if (orig->targetList != NIL) - { - List *tl; - TargetEntry *tle; - - foreach(tl, orig->targetList) - { - tle = lfirst(tl); - if (tle->resdom != NULL) - tle->expr = tg_rewriteParamsInExpr(tle->expr, inputQlist); - } - } - - /* - * step 3: rewrite the qual of the original parse tree if there are - * any references to params, replace them with the appropriate target - * list entry of the children node - */ - if (orig->qual) - { - if (nodeTag(orig->qual) == T_List) - elog(ERROR, "tg_rewriteQuery: Whoa! why is my qual a List???"); - orig->qual = tg_rewriteParamsInExpr(orig->qual, inputQlist); - } - - /* - * at this point, we're done with the rewrite, the querytreelist q has - * been modified - */ - -} - - -/* tg_replaceNumberedParam: - - this procedure replaces the specified numbered param with a - reference to a range table - - this procedure recursively calls itself - - it returns a (possibly modified) Node*. - -*/ -static Node * -tg_replaceNumberedParam(Node *expression, - int pnum, /* the number of the parameter */ - int rt_ind, /* the range table index */ - char *teeRelName) /* the relname of the tee - * table */ -{ - TargetEntry *param_tle; - Param *p; - Var *newVar, - *oldVar; - - if (expression == NULL) - return NULL; - - switch (nodeTag(expression)) - { - case T_Param: - { - /* - * the node is a parameter, substitute the entry from the - * target list of the child that corresponds to the - * parameter number - */ - p = (Param *) expression; - - /* we only deal with the case of numbered parameters */ - if (p->paramkind == PARAM_NUM && p->paramid == pnum) - { - - if (p->param_tlist) - { - /* - * we have a parameter with an attribute like - * $N.foo so replace it with a new var node - */ - - /* param tlist can only have one entry in them! */ - param_tle = (TargetEntry *) (lfirst(p->param_tlist)); - oldVar = (Var *) param_tle->expr; - oldVar->varno = rt_ind; - oldVar->varnoold = rt_ind; - return (Node *) oldVar; - } - else - { - /* we have $N without the .foo */ - bool defined; - bool isRel; - - /* - * TODO here, we need to check to see whether the - * type of the tee is a complex type (relation) or - * a simple type - */ - - /* - * if it is a simple type, then we need to get the - * "result" attribute from the tee relation - */ - - isRel = (typeidTypeRelid(p->paramtype) != 0); - if (isRel) - { - newVar = makeVar(rt_ind, - 0, /* the whole tuple */ - TypeGet(teeRelName, &defined), - -1, - 0, - rt_ind, - 0); - return (Node *) newVar; - } - else - newVar = makeVar(rt_ind, - 1, /* just the first field, - * which is 'result' */ - TypeGet(teeRelName, &defined), - -1, - 0, - rt_ind, - 0); - return (Node *) newVar; - - } - } - else - elog(WARNING, "tg_replaceNumberedParam: unexpected paramkind value of %d", p->paramkind); - } - break; - case T_Expr: - { - /* - * the node is an expression, we need to recursively call - * ourselves until we find parameter nodes - */ - List *l; - Expr *expr = (Expr *) expression; - List *newArgs; - - /* - * we have to make a new args lists because Params can be - * replaced by Var nodes in tg_replaceNumberedParam() - */ - newArgs = NIL; - - /* - * we only care about argument to expressions, it doesn't - * matter when the opType is - */ - /* recursively rewrite the arguments of this expression */ - foreach(l, expr->args) - { - newArgs = lappend(newArgs, - tg_replaceNumberedParam(lfirst(l), - pnum, - rt_ind, - teeRelName)); - } - /* change the arguments of the expression */ - expr->args = newArgs; - } - break; - default: - { - /* ignore other expr types */ - } - } - - return expression; -} - - - - - -/* tg_rewriteParamsInExpr: - - rewrite the params in expressions by using the targetlist entries - from the input parsetrees - - this procedure recursively calls itself - - it returns a (possibly modified) Node*. - -*/ -static Node * -tg_rewriteParamsInExpr(Node *expression, QueryTreeList * inputQlist) -{ - List *tl; - TargetEntry *param_tle, - *tle; - Param *p; - int childno; - char *resname; - - if (expression == NULL) - return NULL; - - switch (nodeTag(expression)) - { - case T_Param: - { - /* - * the node is a parameter, substitute the entry from the - * target list of the child that corresponds to the - * parameter number - */ - p = (Param *) expression; - - /* we only deal with the case of numbered parameters */ - if (p->paramkind == PARAM_NUM) - { - /* paramid's start from 1 */ - childno = p->paramid - 1; - - if (p->param_tlist) - { - /* - * we have a parameter with an attribute like - * $N.foo so match the resname "foo" against the - * target list of the (N-1)th inputQlist - */ - - /* param tlist can only have one entry in them! */ - param_tle = (TargetEntry *) (lfirst(p->param_tlist)); - resname = param_tle->resdom->resname; - - if (inputQlist->qtrees[childno]) - { - foreach(tl, inputQlist->qtrees[childno]->targetList) - { - tle = lfirst(tl); - if (strcmp(resname, tle->resdom->resname) == 0) - return tle->expr; - } - } - else - elog(ERROR, "tg_rewriteParamsInExpr:can't substitute for parameter %d when that input is unconnected", p->paramid); - - } - else - { - /* we have $N without the .foo */ - /* use the first resdom in the targetlist of the */ - /* appropriate child query */ - tl = inputQlist->qtrees[childno]->targetList; - tle = lfirst(tl); - return tle->expr; - } - } - else - elog(WARNING, "tg_rewriteParamsInExpr: unexpected paramkind value of %d", p->paramkind); - } - break; - case T_Expr: - { - /* - * the node is an expression, we need to recursively call - * ourselves until we find parameter nodes - */ - List *l; - Expr *expr = (Expr *) expression; - List *newArgs; - - /* - * we have to make a new args lists because Params can be - * replaced by Var nodes in tg_rewriteParamsInExpr() - */ - newArgs = NIL; - - /* - * we only care about argument to expressions, it doesn't - * matter when the opType is - */ - /* recursively rewrite the arguments of this expression */ - foreach(l, expr->args) - { - newArgs = lappend(newArgs, - tg_rewriteParamsInExpr(lfirst(l), inputQlist)); - } - /* change the arguments of the expression */ - expr->args = newArgs; - } - break; - default: - { - /* ignore other expr types */ - } - } - - return expression; -} - - - -/* - getParamTypes: - given an element, finds its parameter types. - the typev array argument is set to the parameter types. - the parameterCount is returned - - this code is very similar to ProcedureDefine() in pg_proc.c -*/ -static int -getParamTypes(TgElement * elem, Oid *typev) -{ - /* this code is similar to ProcedureDefine() */ - int16 parameterCount; - bool defined; - Oid toid; - char *t; - int i, - j; - - parameterCount = 0; - for (i = 0; i < FUNC_MAX_ARGS; i++) - typev[i] = 0; - for (j = 0; j < elem->inTypes->num; j++) - { - if (parameterCount == FUNC_MAX_ARGS) - { - elog(ERROR, - "getParamTypes: Ingredients cannot take > %d arguments", FUNC_MAX_ARGS); - } - t = elem->inTypes->val[j]; - if (strcmp(t, "opaque") == 0) - { - elog(ERROR, - "getParamTypes: Ingredient functions cannot take type 'opaque'"); - } - else - { - toid = TypeGet(elem->inTypes->val[j], &defined); - if (!OidIsValid(toid)) - elog(ERROR, "getParamTypes: arg type '%s' is not defined", t); - if (!defined) - elog(WARNING, "getParamTypes: arg type '%s' is only a shell", t); - } - typev[parameterCount++] = toid; - } - - return parameterCount; -} - - -/* - * tg_parseTeeNode - * - * handles the parsing of the tee node - * - * - */ - -static QueryTreeList * -tg_parseTeeNode(TgRecipe * r, - TgNode * n, /* the tee node */ - int i, /* which input this node is to its parent */ - QueryTreeList * qList, - TeeInfo * teeInfo) - -{ - QueryTreeList *q; - char *tt; - int rt_ind; - Query *orig; - - /* - * the input Node is a tee node, so we need to do the following: we - * need to parse the child of the tee node, we add that to our query - * tree list we need the name of the tee node table the tee node table - * is the table into which the tee node may materialize results. Call - * it TT we add a range table to our existing query with TT in it we - * need to replace the parameter $i with TT (otherwise the optimizer - * won't know to use the table on expression containining $i) After - * that rewrite, the optimizer will generate sequential scans of TT - * - * Later, in the glue phase, we replace all instances of TT sequential - * scans with the actual Tee node - */ - q = tg_parseSubQuery(r, n, teeInfo); - - /* tt is the name of the tee node table */ - tt = n->nodeName; - - if (q) - appendTeeQuery(teeInfo, q, tt); - - orig = qList->qtrees[0]; - rt_ind = RangeTablePosn(orig->rtable, tt); - - /* - * check to see that this table is not part of the range table - * already. This usually only happens if multiple inputs are - * connected to the same Tee. - */ - if (rt_ind == 0) - { - orig->rtable = lappend(orig->rtable, - addRangeTableEntry(NULL, - tt, - tt, - FALSE, - FALSE)); - rt_ind = length(orig->rtable); - } - - orig->qual = tg_replaceNumberedParam(orig->qual, - i + 1, /* params start at 1 */ - rt_ind, - tt); - return qList; -} - - -/* - * tg_parseSubQuery: - * go backwards from a node and parse the query - * - * the result parse tree is passed back - * - * could return NULL if trying to parse a teeNode - * that's already been processed by another parent - * - */ - -static QueryTreeList * -tg_parseSubQuery(TgRecipe * r, TgNode * n, TeeInfo * teeInfo) -{ - TgElement *elem; - char *funcName; - Oid typev[FUNC_MAX_ARGS], /* eight arguments maximum */ - relid; - int i, - parameterCount; - - QueryTreeList *qList; /* the parse tree of the nodeElement */ - QueryTreeList *inputQlist; /* the list of parse trees for the inputs - * to this node */ - QueryTreeList *q; - TgNode *child; - Relation rel; - unsigned int len; - TupleDesc tupdesc; - - qList = NULL; - - if (n->nodeType == TG_INGRED_NODE) - { - /* parse each ingredient node in turn */ - - elem = n->nodeElem; - switch (elem->srcLang) - { - case TG_SQL: - { - /* - * for SQL ingredients, the SQL query is contained in - * the 'src' field - */ - -#ifdef DEBUG_RECIPE - elog(WARNING, "calling parser with %s", elem->src); -#endif /* DEBUG_RECIPE */ - - parameterCount = getParamTypes(elem, typev); - - qList = parser(elem->src, typev, parameterCount); - - if (qList->len > 1) - { - elog(WARNING, - "tg_parseSubQuery: parser produced > 1 query tree"); - } - } - break; - case TG_C: - { - /* C ingredients are registered functions in postgres */ - - /* - * we create a new query string by using the function - * name (found in the 'src' field) and adding - * parameters to it so if the function was FOOBAR and - * took in two arguments, we would create a string - * select FOOBAR($1,$2) - */ - char newquery[1000]; - - funcName = elem->src; - parameterCount = getParamTypes(elem, typev); - - if (parameterCount > 0) - { - int i; - - snprintf(newquery, 1000, "select %s($1", funcName); - for (i = 1; i < parameterCount; i++) - snprintf(newquery, 1000, "%s,$%d", pstrdup(newquery), i); - snprintf(newquery, 1000, "%s)", pstrdup(newquery)); - } - else - snprintf(newquery, 1000, "select %s()", funcName); - -#ifdef DEBUG_RECIPE - elog(WARNING, "calling parser with %s", newquery); -#endif /* DEBUG_RECIPE */ - - qList = parser(newquery, typev, parameterCount); - if (qList->len > 1) - { - elog(WARNING, - "tg_parseSubQuery: parser produced > 1 query tree"); - } - } - break; - case TG_RECIPE_GRAPH: - elog(WARNING, "tg_parseSubQuery: can't parse recipe graph ingredients yet!"); - break; - case TG_COMPILED: - elog(WARNING, "tg_parseSubQuery: can't parse compiled ingredients yet!"); - break; - default: - elog(WARNING, "tg_parseSubQuery: unknown srcLang: %d", elem->srcLang); - } - - /* parse each of the subrecipes that are input to this node */ - - if (n->inNodes->num > 0) - { - inputQlist = malloc(sizeof(QueryTreeList)); - inputQlist->len = n->inNodes->num + 1; - inputQlist->qtrees = (Query **) malloc(inputQlist->len * sizeof(Query *)); - for (i = 0; i < n->inNodes->num; i++) - { - - inputQlist->qtrees[i] = NULL; - if (n->inNodes->val[i]) - { - if (n->inNodes->val[i]->nodeType == TG_TEE_NODE) - { - qList = tg_parseTeeNode(r, n->inNodes->val[i], - i, qList, teeInfo); - } - else - { /* input node is not a Tee */ - q = tg_parseSubQuery(r, n->inNodes->val[i], - teeInfo); - Assert(q->len == 1); - inputQlist->qtrees[i] = q->qtrees[0]; - } - } - } - - /* now, we have all the query trees from our input nodes */ - /* transform the original parse tree appropriately */ - tg_rewriteQuery(r, n, qList, inputQlist); - } - } - else if (n->nodeType == TG_EYE_NODE) - { - /* - * if we hit an eye, we need to stop and make what we have into a - * subrecipe query block - */ - elog(WARNING, "tg_parseSubQuery: can't handle eye nodes yet"); - } - else if (n->nodeType == TG_TEE_NODE) - { - /* - * if we hit a tee, check to see if the parsing has been done for - * this tee already by the other parent - */ - - rel = RelationNameGetRelation(n->nodeName); - if (RelationIsValid(rel)) - { - /* - * this tee has already been visited, no need to do any - * further processing - */ - return NULL; - } - else - { - /* we need to process the child of the tee first, */ - child = n->inNodes->val[0]; - - if (child->nodeType == TG_TEE_NODE) - { - /* nested Tee nodes */ - qList = tg_parseTeeNode(r, child, 0, qList, teeInfo); - return qList; - } - - Assert(child != NULL); - - /* parse the input node */ - q = tg_parseSubQuery(r, child, teeInfo); - Assert(q->len == 1); - - /* add the parsed query to the main list of queries */ - qList = appendQlist(qList, q); - - /* need to create the tee table here */ - - /* - * the tee table created is used both for materializing the - * values at the tee node, and for parsing and optimization. - * The optimization needs to have a real table before it will - * consider scans on it - */ - - /* - * first, find the type of the tuples being produced by the - * tee. The type is the same as the output type of the child - * node. - * - * NOTE: we are assuming that the child node only has a single - * output here! - */ - getParamTypes(child->nodeElem, typev); - - /* - * the output type is either a complex type, (and is thus a - * relation) or is a simple type - */ - - rel = RelationNameGetRelation(child->nodeElem->outTypes->val[0]); - - if (RelationIsValid(rel)) - { - /* - * for complex types, create new relation with the same - * tuple descriptor as the output table type - */ - len = length(q->qtrees[0]->targetList); - tupdesc = rel->rd_att; - - relid = heap_create_with_catalog( - child->nodeElem->outTypes->val[0], - tupdesc, RELKIND_RELATION, false); - } - else - { - /* - * we have to create a relation with one attribute of the - * simple base type. That attribute will have an attr - * name of "result" - */ - /* NOTE: ignore array types for the time being */ - - len = 1; - tupdesc = CreateTemplateTupleDesc(len); - - if (!TupleDescInitEntry(tupdesc, 1, - "result", - InvalidOid, - -1, 0, false)) - elog(WARNING, "tg_parseSubQuery: unexpected result from TupleDescInitEntry"); - else - { - relid = heap_create_with_catalog( - child->nodeElem->outTypes->val[0], - tupdesc, RELKIND_RELATION, false); - } - } - } - } - else if (n->nodeType == TG_RECIPE_NODE) - elog(WARNING, "tg_parseSubQuery: can't handle embedded recipes yet!"); - else - elog(WARNING, "unknown nodeType: %d", n->nodeType); - - return qList; -} - -/* - * OffsetVarAttno - - * recursively find all the var nodes with the specified varno - * and offset their varattno with the offset - * - * code is similar to OffsetVarNodes in rewriteManip.c - */ - -void -OffsetVarAttno(Node *node, int varno, int offset) -{ - if (node == NULL) - return; - switch (nodeTag(node)) - { - case T_TargetEntry: - { - TargetEntry *tle = (TargetEntry *) node; - - OffsetVarAttno(tle->expr, varno, offset); - } - break; - case T_Expr: - { - Expr *expr = (Expr *) node; - - OffsetVarAttno((Node *) expr->args, varno, offset); - } - break; - case T_Var: - { - Var *var = (Var *) node; - - if (var->varno == varno) - var->varattno += offset; - } - break; - case T_List: - { - List *l; - - foreach(l, (List *) node) - OffsetVarAttno(lfirst(l), varno, offset); - } - break; - default: - /* ignore the others */ - break; - } -} - -/* - * appendQlist - * add the contents of a QueryTreeList q2 to the end of the QueryTreeList - * q1 - * - * returns a new querytree list - */ - -QueryTreeList * -appendQlist(QueryTreeList * q1, QueryTreeList * q2) -{ - QueryTreeList *newq; - int i, - j; - int newlen; - - if (q1 == NULL) - return q2; - - if (q2 == NULL) - return q1; - - newlen = q1->len + q2->len; - newq = (QueryTreeList *) malloc(sizeof(QueryTreeList)); - newq->len = newlen; - newq->qtrees = (Query **) malloc(newlen * sizeof(Query *)); - for (i = 0; i < q1->len; i++) - newq->qtrees[i] = q1->qtrees[i]; - for (j = 0; j < q2->len; j++) - newq->qtrees[i + j] = q2->qtrees[j]; - return newq; -} - -/* - * appendTeeQuery - * - * modify the query field of the teeInfo list of the particular tee node - */ -static void -appendTeeQuery(TeeInfo * teeInfo, QueryTreeList * q, char *teeNodeName) -{ - int i; - - Assert(teeInfo); - - for (i = 0; i < teeInfo->num; i++) - { - if (strcmp(teeInfo->val[i].tpi_relName, teeNodeName) == 0) - { - - Assert(q->len == 1); - teeInfo->val[i].tpi_parsetree = q->qtrees[0]; - return; - } - } - elog(WARNING, "appendTeeQuery: teeNodeName '%s' not found in teeInfo"); -} - - - -/* - * replaceSeqScan - * replaces sequential scans of a specified relation with the tee plan - * the relation is specified by its index in the range table, rt_ind - * - * returns the modified plan - * the offset_attno is the offset that needs to be added to the parent's - * qual or targetlist because the child plan has been replaced with a tee node - */ -static void -replaceSeqScan(Plan *plan, Plan *parent, - int rt_ind, Plan *tplan) -{ - Scan *snode; - Tee *teePlan; - Result *newPlan; - - if (plan == NULL) - return; - - if (plan->type == T_SeqScan) - { - snode = (Scan *) plan; - if (snode->scanrelid == rt_ind) - { - /* - * found the sequential scan that should be replaced with the - * tplan. - */ - /* we replace the plan, but we also need to modify its parent */ - - /* - * replace the sequential scan with a Result node the reason - * we use a result node is so that we get the proper - * projection behavior. The Result node is simply (ab)used as - * a projection node - */ - - newPlan = makeNode(Result); - newPlan->plan.cost = 0.0; - newPlan->plan.state = (EState *) NULL; - newPlan->plan.targetlist = plan->targetlist; - newPlan->plan.lefttree = tplan; - newPlan->plan.righttree = NULL; - newPlan->resconstantqual = NULL; - newPlan->resstate = NULL; - - /* change all the varno's to 1 */ - ChangeVarNodes((Node *) newPlan->plan.targetlist, - snode->scanrelid, 1); - - if (parent) - { - teePlan = (Tee *) tplan; - - if (parent->lefttree == plan) - parent->lefttree = (Plan *) newPlan; - else - parent->righttree = (Plan *) newPlan; - - - if (teePlan->leftParent == NULL) - teePlan->leftParent = (Plan *) newPlan; - else - teePlan->rightParent = (Plan *) newPlan; - -/* comment for now to test out executor-stuff - if (parent->state) { - ExecInitNode((Plan*)newPlan, parent->state, (Plan*)newPlan); - } -*/ - } - } - - } - else - { - if (plan->lefttree) - replaceSeqScan(plan->lefttree, plan, rt_ind, tplan); - if (plan->righttree) - replaceSeqScan(plan->righttree, plan, rt_ind, tplan); - } -} - -/* - * replaceTeeScans - * places the sequential scans of the Tee table with - * a connection to the actual tee plan node - */ -static Plan * -replaceTeeScans(Plan *plan, Query *parsetree, TeeInfo * teeInfo) -{ - - int i; - List *rtable; - RangeTblEntry *rte; - char prefix[5]; - int rt_ind; - Plan *tplan; - - rtable = parsetree->rtable; - if (rtable == NULL) - return plan; - - /* - * look through the range table for the tee relation entry, that will - * give use the varno we need to detect which sequential scans need to - * be replaced with tee nodes - */ - - rt_ind = 0; - while (rtable != NIL) - { - rte = lfirst(rtable); - rtable = lnext(rtable); - rt_ind++; /* range table references in varno fields - * start w/ 1 */ - - /* - * look for the "tee_" prefix in the refname, also check to see - * that the relname and the refname are the same this should - * eliminate any user-specified table and leave us with the tee - * table entries only - */ - if ((strlen(rte->refname) < 4) || - (strcmp(rte->relname, rte->refname) != 0)) - continue; - StrNCpy(prefix, rte->refname, 5); - if (strcmp(prefix, "tee_") == 0) - { - /* okay, we found a tee node entry in the range table */ - - /* find the appropriate plan in the teeInfo list */ - tplan = NULL; - for (i = 0; i < teeInfo->num; i++) - { - if (strcmp(teeInfo->val[i].tpi_relName, - rte->refname) == 0) - tplan = teeInfo->val[i].tpi_plan; - } - if (tplan == NULL) - elog(WARNING, "replaceTeeScans didn't find the corresponding tee plan"); - - /* - * replace the sequential scan node with that var number with - * the tee plan node - */ - replaceSeqScan(plan, NULL, rt_ind, tplan); - } - } - - return plan; -} - - -#endif /* TIOGA */ diff --git a/src/backend/commands/_deadcode/version.c b/src/backend/commands/_deadcode/version.c deleted file mode 100644 index a88247e684b..00000000000 --- a/src/backend/commands/_deadcode/version.c +++ /dev/null @@ -1,346 +0,0 @@ -/*------------------------------------------------------------------------- - * - * version.c - * This file contains all the rules that govern all version semantics. - * - * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * The version stuff has not been tested under postgres95 and probably - * doesn't work! - jolly 8/19/95 - * - * - * $Id: version.c,v 1.30 2002/06/20 20:29:27 momjian Exp $ - * - * NOTES - * At the point the version is defined, 2 physical relations are created - * <vname>_added and <vname>_deleted. - * - * In addition, 4 rules are defined which govern the semantics of - * versions w.r.t retrieves, appends, replaces and deletes. - * - *------------------------------------------------------------------------- - */ - -#include "postgres.h" - - -#define MAX_QUERY_LEN 1024 - -char rule_buf[MAX_QUERY_LEN]; - -/* - * problem: the version system assumes that the rules it declares will - * be fired in the order of declaration, it also assumes - * goh's silly instead semantics. Unfortunately, it is a pain - * to make the version system work with the new semantics. - * However the whole problem can be solved, and some nice - * functionality can be achieved if we get multiple action rules - * to work. So thats what I did -- glass - * - * Well, at least they've been working for about 20 minutes. - * - * So any comments in this code about 1 rule per transction are false...:) - * - */ - -/* - * This is needed because the rule system only allows - * *1* rule to be defined per transaction. - * - * NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO - * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO - * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO - * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO - * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO - * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO - * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO - * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO - * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO - * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO - * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO - * OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO - * OOOOOOOOOOOOOOOOOOO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * - * DONT DO THAT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - * - * If you commit the current Xact all the palloced memory GOES AWAY - * and could be re-palloced in the new Xact and the whole hell breaks - * loose and poor people like me spend 2 hours of their live chassing - * a strange memory bug instead of watching the "Get Smart" marathon - * in NICK ! - * DO NOT COMMIT THE XACT, just increase the Cid counter! - * _sp. - */ -#ifdef NOT_USED -static void -eval_as_new_xact(char *query) -{ - - /*------ - * WARNING! do not uncomment the following lines WARNING! - * - * CommitTransactionCommand(); - * StartTransactionCommand(); - *------ - */ - CommandCounterIncrement(); - pg_exec_query(query); -} -#endif -/* - * Define a version. - */ -#ifdef NOT_USED -void -DefineVersion(char *name, char *fromRelname, char *date) -{ - char *bname; - static char saved_basename[512]; - static char saved_snapshot[512]; - - if (date == NULL) - { - /* no time ranges */ - bname = fromRelname; - strcpy(saved_basename, (char *) bname); - *saved_snapshot = (char) NULL; - } - else - { - /* version is a snapshot */ - bname = fromRelname; - strcpy(saved_basename, (char *) bname); - sprintf(saved_snapshot, "['%s']", date); - } - - - /* - * Calls the routine ``GetAttrList'' get the list of attributes from - * the base relation. Code is put here so that we only need to look up - * the attribute once for both appends and replaces. - */ - setAttrList(bname); - - VersionCreate(name, saved_basename); - VersionAppend(name, saved_basename); - VersionDelete(name, saved_basename, saved_snapshot); - VersionReplace(name, saved_basename, saved_snapshot); - VersionRetrieve(name, saved_basename, saved_snapshot); -} -#endif - -/* - * Creates the deltas. - */ -#ifdef NOT_USED -void -VersionCreate(char *vname, char *bname) -{ - static char query_buf[MAX_QUERY_LEN]; - - /* - * Creating the dummy version relation for triggering rules. - */ - sprintf(query_buf, "SELECT * INTO TABLE %s from %s where 1 =2", - vname, bname); - - pg_exec_query(query_buf); - - /* - * Creating the ``v_added'' relation - */ - sprintf(query_buf, "SELECT * INTO TABLE %s_added from %s where 1 = 2", - vname, bname); - eval_as_new_xact(query_buf); - - /* - * Creating the ``v_deleted'' relation. - */ - sprintf(query_buf, "CREATE TABLE %s_del (DOID oid)", vname); - eval_as_new_xact(query_buf); -} -#endif - - -/* - * Given the relation name, does a catalog lookup for that relation and - * sets the global variable 'attr_list' with the list of attributes (names) - * for that relation. - */ -#ifdef NOT_USED -static void -setAttrList(char *bname) -{ - Relation rel; - int i = 0; - int maxattrs = 0; - char *attrname; - char temp_buf[512]; - int notfirst = 0; - - rel = heap_openr(bname); - if (rel == NULL) - { - elog(ERROR, "Unable to expand all -- amopenr failed "); - return; - } - maxattrs = RelationGetNumberOfAttributes(rel); - - attr_list[0] = '\0'; - - for (i = maxattrs - 1; i > -1; --i) - { - attrname = NameStr(rel->rd_att->attrs[i]->attname); - - if (notfirst == 1) - sprintf(temp_buf, ", %s = new.%s", attrname, attrname); - else - { - sprintf(temp_buf, "%s = new.%s", attrname, attrname); - notfirst = 1; - } - strcat(attr_list, temp_buf); - } - - heap_close(rel); - - return; -} -#endif - -/* - * This routine defines the rule governing the append semantics of - * versions. All tuples appended to a version gets appended to the - * <vname>_added relation. - */ -#ifdef NOT_USED -static void -VersionAppend(char *vname, char *bname) -{ - sprintf(rule_buf, - "define rewrite rule %s_append is on INSERT to %s do instead append %s_added(%s)", - vname, vname, vname, attr_list); - - eval_as_new_xact(rule_buf); -} -#endif - -/* - * This routine defines the rule governing the retrieval semantics of - * versions. To retrieve tuples from a version , we need to: - * - * 1. Retrieve all tuples in the <vname>_added relation. - * 2. Retrieve all tuples in the base relation which are not in - * the <vname>_del relation. - */ -#ifdef NOT_USED -void -VersionRetrieve(char *vname, char *bname, char *snapshot) -{ - - sprintf(rule_buf, - "define rewrite rule %s_retrieve is on SELECT to %s do instead\n\ -SELECT %s_1.oid, %s_1.* from _%s in %s%s, %s_1 in (%s_added | _%s) \ -where _%s.oid !!= '%s_del.DOID'", - vname, vname, vname, vname, bname, - bname, snapshot, - vname, vname, bname, bname, vname); - - eval_as_new_xact(rule_buf); - - /* printf("%s\n",rule_buf); */ - -} -#endif - -/* - * This routine defines the rules that govern the delete semantics of - * versions. Two things happens when we delete a tuple from a version: - * - * 1. If the tuple to be deleted was added to the version *after* - * the version was created, then we simply delete the tuple - * from the <vname>_added relation. - * 2. If the tuple to be deleted is actually in the base relation, - * then we have to mark that tuple as being deleted by adding - * it to the <vname>_del relation. - */ -#ifdef NOT_USED -void -VersionDelete(char *vname, char *bname, char *snapshot) -{ - - sprintf(rule_buf, - "define rewrite rule %s_delete1 is on delete to %s do instead\n \ -[delete %s_added where current.oid = %s_added.oid\n \ - append %s_del(DOID = current.oid) from _%s in %s%s \ - where current.oid = _%s.oid] \n", - vname, vname, vname, vname, vname, - bname, bname, snapshot, bname); - - eval_as_new_xact(rule_buf); -#ifdef OLD_REWRITE - sprintf(rule_buf, - "define rewrite rule %s_delete2 is on delete to %s do instead \n \ - append %s_del(DOID = current.oid) from _%s in %s%s \ - where current.oid = _%s.oid \n", - vname, vname, vname, bname, bname, snapshot, bname); - - eval_as_new_xact(rule_buf); -#endif /* OLD_REWRITE */ -} -#endif - -/* - * This routine defines the rules that govern the update semantics - * of versions. To update a tuple in a version: - * - * 1. If the tuple is in <vname>_added, we simply ``replace'' - * the tuple (as per postgres style). - * 2. if the tuple is in the base relation, then two things have to - * happen: - * 2.1 The tuple is marked ``deleted'' from the base relation by - * adding the tuple to the <vname>_del relation. - * 2.2 A copy of the tuple is appended to the <vname>_added relation - */ -#ifdef NOT_USED -void -VersionReplace(char *vname, char *bname, char *snapshot) -{ - sprintf(rule_buf, - "define rewrite rule %s_replace1 is on replace to %s do instead \n\ -[replace %s_added(%s) where current.oid = %s_added.oid \n\ - append %s_del(DOID = current.oid) from _%s in %s%s \ - where current.oid = _%s.oid\n\ - append %s_added(%s) from _%s in %s%s \ - where current.oid !!= '%s_added.oid' and current.oid = _%s.oid]\n", - vname, vname, vname, attr_list, vname, - vname, bname, bname, snapshot, bname, - vname, attr_list, bname, bname, snapshot, vname, bname); - - eval_as_new_xact(rule_buf); - -/* printf("%s\n",rule_buf); */ -#ifdef OLD_REWRITE - sprintf(rule_buf, - "define rewrite rule %s_replace2 is on replace to %s do \n\ - append %s_del(DOID = current.oid) from _%s in %s%s \ - where current.oid = _%s.oid\n", - vname, vname, vname, bname, bname, snapshot, bname); - - eval_as_new_xact(rule_buf); - - sprintf(rule_buf, - "define rewrite rule %s_replace3 is on replace to %s do instead\n\ - append %s_added(%s) from _%s in %s%s \ - where current.oid !!= '%s_added.oid' and current.oid = \ - _%s.oid\n", - vname, vname, vname, attr_list, bname, bname, snapshot, vname, bname); - - eval_as_new_xact(rule_buf); -#endif /* OLD_REWRITE */ -/* printf("%s\n",rule_buf); */ - -} - -#endif |