From 344dfc0b0f83fdeb1dbbb83e308d888abc9b2ad0 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Tue, 23 Mar 1999 16:51:04 +0000 Subject: Remove Tee code, move to _deadcode. --- src/backend/commands/explain.c | 5 +- src/backend/executor/Makefile | 4 +- src/backend/executor/_deadcode/nodeTee.c | 503 +++++++++++++++++++++++++++++++ src/backend/executor/execAmi.c | 9 +- src/backend/executor/execMain.c | 5 +- src/backend/executor/execProcnode.c | 20 +- src/backend/executor/execTuples.c | 10 +- src/backend/executor/nodeTee.c | 503 ------------------------------- src/backend/nodes/outfuncs.c | 19 +- src/backend/nodes/print.c | 5 +- src/include/executor/nodeTee.h | 25 -- src/include/nodes/execnodes.h | 14 +- src/include/nodes/nodes.h | 4 +- src/include/nodes/plannodes.h | 4 +- 14 files changed, 526 insertions(+), 604 deletions(-) create mode 100644 src/backend/executor/_deadcode/nodeTee.c delete mode 100644 src/backend/executor/nodeTee.c delete mode 100644 src/include/executor/nodeTee.h (limited to 'src') diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 75fa4d8b2be..0983097ace6 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -4,7 +4,7 @@ * * Copyright (c) 1994-5, Regents of the University of California * - * $Id: explain.c,v 1.32 1999/02/13 23:15:06 momjian Exp $ + * $Id: explain.c,v 1.33 1999/03/23 16:50:46 momjian Exp $ * */ #include @@ -194,9 +194,6 @@ explain_outNode(StringInfo str, Plan *plan, int indent, ExplainState *es) case T_Hash: pname = "Hash"; break; - case T_Tee: - pname = "Tee"; - break; default: pname = ""; break; diff --git a/src/backend/executor/Makefile b/src/backend/executor/Makefile index 59339d14733..4f8c1341c83 100644 --- a/src/backend/executor/Makefile +++ b/src/backend/executor/Makefile @@ -4,7 +4,7 @@ # Makefile for executor # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/backend/executor/Makefile,v 1.7 1998/04/06 00:22:26 momjian Exp $ +# $Header: /cvsroot/pgsql/src/backend/executor/Makefile,v 1.8 1999/03/23 16:50:46 momjian Exp $ # #------------------------------------------------------------------------- @@ -18,7 +18,7 @@ OBJS = execAmi.o execFlatten.o execJunk.o execMain.o \ execUtils.o functions.o nodeAppend.o nodeAgg.o nodeHash.o \ nodeHashjoin.o nodeIndexscan.o nodeMaterial.o nodeMergejoin.o \ nodeNestloop.o nodeResult.o nodeSeqscan.o nodeSort.o \ - nodeUnique.o nodeTee.o nodeGroup.o spi.o nodeSubplan.o + nodeUnique.o nodeGroup.o spi.o nodeSubplan.o all: SUBSYS.o diff --git a/src/backend/executor/_deadcode/nodeTee.c b/src/backend/executor/_deadcode/nodeTee.c new file mode 100644 index 00000000000..b06c700c462 --- /dev/null +++ b/src/backend/executor/_deadcode/nodeTee.c @@ -0,0 +1,503 @@ +/*------------------------------------------------------------------------- + * + * nodeTee.c + * + * + * 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.1 1999/03/23 16:50:49 momjian Exp $ + * + *------------------------------------------------------------------------- + */ + +#include +#include +#include "postgres.h" + +#include "utils/palloc.h" +#include "utils/relcache.h" +#include "utils/mcxt.h" +#include "storage/bufmgr.h" +#include "storage/smgr.h" +#include "optimizer/internal.h" +#include "executor/executor.h" +#include "executor/nodeTee.h" +#include "catalog/catalog.h" +#include "catalog/heap.h" +#include "tcop/pquery.h" +#include "access/heapam.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) + pfree(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_destroy(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/executor/execAmi.c b/src/backend/executor/execAmi.c index a25b2fa45dc..83d0c3b6cad 100644 --- a/src/backend/executor/execAmi.c +++ b/src/backend/executor/execAmi.c @@ -5,7 +5,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: execAmi.c,v 1.32 1999/02/13 23:15:14 momjian Exp $ + * $Id: execAmi.c,v 1.33 1999/03/23 16:50:47 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -34,7 +34,6 @@ #include "executor/nodeSeqscan.h" #include "executor/nodeIndexscan.h" #include "executor/nodeSort.h" -#include "executor/nodeTee.h" #include "executor/nodeMaterial.h" #include "executor/nodeNestloop.h" #include "executor/nodeHashjoin.h" @@ -382,12 +381,6 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent) ExecReScanAppend((Append *) node, exprCtxt, parent); break; -/* - * Tee is never used - case T_Tee: - ExecTeeReScan((Tee *) node, exprCtxt, parent); - break; - */ default: elog(ERROR, "ExecReScan: node type %u not supported", nodeTag(node)); return; diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 793d8d3c364..a4be9a3967c 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -26,7 +26,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.81 1999/03/20 01:13:21 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.82 1999/03/23 16:50:47 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -884,7 +884,6 @@ ExecutePlan(EState *estate, DestReceiver* destfunc) { JunkFilter *junkfilter; - TupleTableSlot *slot; ItemPointer tupleid = NULL; ItemPointerData tuple_ctid; @@ -898,7 +897,7 @@ ExecutePlan(EState *estate, current_tuple_count = 0; result = NULL; - /* + /* * Set the direction. */ estate->es_direction = direction; diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c index b41e3ed9d45..1b693cbcaf1 100644 --- a/src/backend/executor/execProcnode.c +++ b/src/backend/executor/execProcnode.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.13 1999/02/13 23:15:17 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.14 1999/03/23 16:50:48 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -90,7 +90,6 @@ #include "executor/nodeAgg.h" #include "executor/nodeHash.h" #include "executor/nodeHashjoin.h" -#include "executor/nodeTee.h" #include "executor/nodeSubplan.h" /* ------------------------------------------------------------------------ @@ -196,10 +195,6 @@ ExecInitNode(Plan *node, EState *estate, Plan *parent) result = ExecInitHashJoin((HashJoin *) node, estate, parent); break; - case T_Tee: - result = ExecInitTee((Tee *) node, estate, parent); - break; - default: elog(ERROR, "ExecInitNode: node %d unsupported", nodeTag(node)); result = FALSE; @@ -248,7 +243,7 @@ ExecProcNode(Plan *node, Plan *parent) switch (nodeTag(node)) { /* ---------------- - * control nodes + * control nodes * ---------------- */ case T_Result: @@ -315,10 +310,6 @@ ExecProcNode(Plan *node, Plan *parent) result = ExecHashJoin((HashJoin *) node); break; - case T_Tee: - result = ExecTee((Tee *) node, parent); - break; - default: elog(ERROR, "ExecProcNode: node %d unsupported", nodeTag(node)); result = NULL; @@ -390,9 +381,6 @@ ExecCountSlotsNode(Plan *node) case T_HashJoin: return ExecCountSlotsHashJoin((HashJoin *) node); - case T_Tee: - return ExecCountSlotsTee((Tee *) node); - default: elog(ERROR, "ExecCountSlotsNode: node not yet supported: %d", nodeTag(node)); @@ -509,10 +497,6 @@ ExecEndNode(Plan *node, Plan *parent) ExecEndHashJoin((HashJoin *) node); break; - case T_Tee: - ExecEndTee((Tee *) node, parent); - break; - default: elog(ERROR, "ExecEndNode: node %d unsupported", nodeTag(node)); break; diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index bcabdef6be4..148b6b11c17 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.23 1999/02/13 23:15:19 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.24 1999/03/23 16:50:48 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -800,14 +800,6 @@ NodeGetResultTupleSlot(Plan *node) } break; - case T_Tee: - { - TeeState *teestate = ((Tee *) node)->teestate; - - slot = teestate->cstate.cs_ResultTupleSlot; - } - break; - default: /* ---------------- * should never get here diff --git a/src/backend/executor/nodeTee.c b/src/backend/executor/nodeTee.c deleted file mode 100644 index ed9a6eea2fe..00000000000 --- a/src/backend/executor/nodeTee.c +++ /dev/null @@ -1,503 +0,0 @@ -/*------------------------------------------------------------------------- - * - * nodeTee.c - * - * - * 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.30 1999/02/13 23:15:29 momjian Exp $ - * - *------------------------------------------------------------------------- - */ - -#include -#include -#include "postgres.h" - -#include "utils/palloc.h" -#include "utils/relcache.h" -#include "utils/mcxt.h" -#include "storage/bufmgr.h" -#include "storage/smgr.h" -#include "optimizer/internal.h" -#include "executor/executor.h" -#include "executor/nodeTee.h" -#include "catalog/catalog.h" -#include "catalog/heap.h" -#include "tcop/pquery.h" -#include "access/heapam.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) - pfree(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_destroy(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/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 11f79e47220..e4816e2e256 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -5,7 +5,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: outfuncs.c,v 1.77 1999/03/01 00:10:31 tgl Exp $ + * $Id: outfuncs.c,v 1.78 1999/03/23 16:50:53 momjian Exp $ * * NOTES * Every (plan) node in POSTGRES has an associated "out" routine which @@ -544,20 +544,6 @@ _outHash(StringInfo str, Hash *node) node->hashtablesize); } -static void -_outTee(StringInfo str, Tee *node) -{ - appendStringInfo(str, " TEE "); - _outPlanInfo(str, (Plan *) node); - - appendStringInfo(str, " :leftParent %X :rightParent %X ", - (int) node->leftParent, - (int) node->rightParent); - - appendStringInfo(str, " :rtentries "); - _outNode(str, node->rtentries); -} - /***************************************************************************** * * Stuff from primnodes.h. @@ -1528,9 +1514,6 @@ _outNode(StringInfo str, void *obj) case T_SubPlan: _outSubPlan(str, obj); break; - case T_Tee: - _outTee(str, obj); - break; case T_Resdom: _outResdom(str, obj); break; diff --git a/src/backend/nodes/print.c b/src/backend/nodes/print.c index d13819a11de..7d8e6e64b45 100644 --- a/src/backend/nodes/print.c +++ b/src/backend/nodes/print.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.25 1999/02/22 01:57:50 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/print.c,v 1.26 1999/03/23 16:50:54 momjian Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -339,9 +339,6 @@ plannode_type(Plan *p) case T_Hash: return "HASH"; break; - case T_Tee: - return "TEE"; - break; case T_Choose: return "CHOOSE"; break; diff --git a/src/include/executor/nodeTee.h b/src/include/executor/nodeTee.h deleted file mode 100644 index 817228e4cdc..00000000000 --- a/src/include/executor/nodeTee.h +++ /dev/null @@ -1,25 +0,0 @@ -/*------------------------------------------------------------------------- - * - * nodeTee.h - * support functions for a Tee executor node - * - * Copyright (c) 1994, Regents of the University of California - * - * $Id: nodeTee.h,v 1.8 1999/02/13 23:21:29 momjian Exp $ - * - *------------------------------------------------------------------------- - */ - -#ifndef NODETEE_H -#define NODETEE_H - -#include "executor/tuptable.h" -#include "nodes/execnodes.h" -#include "nodes/plannodes.h" - -extern TupleTableSlot *ExecTee(Tee *node, Plan *parent); -extern bool ExecInitTee(Tee *node, EState *estate, Plan *parent); -extern void ExecEndTee(Tee *node, Plan *parent); -extern int ExecCountSlotsTee(Tee *node); - -#endif /* NODETEE_H */ diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index c7f6fa35b2d..9685dacc62e 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: execnodes.h,v 1.26 1999/02/28 00:36:04 tgl Exp $ + * $Id: execnodes.h,v 1.27 1999/03/23 16:51:00 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -686,6 +686,7 @@ typedef struct HashState File *hashBatches; } HashState; +#ifdef NOT_USED /* ----------------------- * TeeState information * leftPlace : next item in the queue unseen by the left parent @@ -704,13 +705,14 @@ typedef struct TeeState { CommonState cstate; /* its first field is NodeTag */ int tee_leftPlace, - tee_rightPlace, - tee_lastPlace; + tee_rightPlace, + tee_lastPlace; char *tee_bufferRelname; - Relation tee_bufferRel; + Relation tee_bufferRel; MemoryContext tee_mcxt; - HeapScanDesc tee_leftScanDesc, - tee_rightScanDesc; + HeapScanDesc tee_leftScanDesc, + tee_rightScanDesc; } TeeState; +#endif #endif /* EXECNODES_H */ diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index c56b1fa9dc1..09d5a1bae5e 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: nodes.h,v 1.47 1999/03/07 03:34:11 momjian Exp $ + * $Id: nodes.h,v 1.48 1999/03/23 16:51:03 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -45,7 +45,6 @@ typedef enum NodeTag T_Unique, T_Hash, T_Choose, - T_Tee, T_Group, T_SubPlan, @@ -117,7 +116,6 @@ typedef enum NodeTag T_SortState, T_UniqueState, T_HashState, - T_TeeState, /*--------------------- * TAGS FOR MEMORY NODES (memnodes.h) diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 3d3b2ca917d..25c38f228cc 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: plannodes.h,v 1.23 1999/03/01 00:10:36 tgl Exp $ + * $Id: plannodes.h,v 1.24 1999/03/23 16:51:04 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -325,6 +325,7 @@ typedef struct Hash int hashtablesize; } Hash; +#ifdef NOT_USED /* ------------------- * Tee node information * @@ -344,6 +345,7 @@ typedef struct Tee * Tee may be different than the parent * plans */ } Tee; +#endif /* --------------------- * SubPlan node -- cgit v1.2.3