diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/Makefile | 4 | ||||
-rw-r--r-- | src/backend/executor/execAmi.c | 7 | ||||
-rw-r--r-- | src/backend/executor/execMain.c | 9 | ||||
-rw-r--r-- | src/backend/executor/execProcnode.c | 18 | ||||
-rw-r--r-- | src/backend/executor/execTuples.c | 14 | ||||
-rw-r--r-- | src/backend/executor/nodeAppend.c | 29 | ||||
-rw-r--r-- | src/backend/executor/nodeSetOp.c | 341 | ||||
-rw-r--r-- | src/backend/executor/nodeSubplan.c | 18 | ||||
-rw-r--r-- | src/backend/executor/nodeSubqueryscan.c | 55 |
9 files changed, 430 insertions, 65 deletions
diff --git a/src/backend/executor/Makefile b/src/backend/executor/Makefile index f26c35e9e10..7c79df5904d 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.14 2000/09/29 18:21:28 tgl Exp $ +# $Header: /cvsroot/pgsql/src/backend/executor/Makefile,v 1.15 2000/10/05 19:11:26 tgl Exp $ # #------------------------------------------------------------------------- @@ -16,7 +16,7 @@ OBJS = execAmi.o execFlatten.o execJunk.o execMain.o \ execProcnode.o execQual.o execScan.o execTuples.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 \ + nodeNestloop.o nodeResult.o nodeSeqscan.o nodeSetOp.o nodeSort.o \ nodeUnique.o nodeGroup.o spi.o nodeSubplan.o \ nodeSubqueryscan.o nodeTidscan.o diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c index 31ad291236b..9d008494b30 100644 --- a/src/backend/executor/execAmi.c +++ b/src/backend/executor/execAmi.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: execAmi.c,v 1.52 2000/09/29 18:21:28 tgl Exp $ + * $Id: execAmi.c,v 1.53 2000/10/05 19:11:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -42,6 +42,7 @@ #include "executor/nodeNestloop.h" #include "executor/nodeResult.h" #include "executor/nodeSeqscan.h" +#include "executor/nodeSetOp.h" #include "executor/nodeSort.h" #include "executor/nodeSubplan.h" #include "executor/nodeSubqueryscan.h" @@ -345,6 +346,10 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent) ExecReScanUnique((Unique *) node, exprCtxt, parent); break; + case T_SetOp: + ExecReScanSetOp((SetOp *) node, exprCtxt, parent); + break; + case T_Sort: ExecReScanSort((Sort *) node, exprCtxt, parent); break; diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index a202da98d2e..3393559d630 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -27,7 +27,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.128 2000/09/29 18:21:28 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.129 2000/10/05 19:11:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -463,7 +463,6 @@ ExecCheckPlanPerms(Plan *plan, List *rangeTable, CmdType operation) /* Append implements expansion of inheritance */ ExecCheckRTPerms(app->inheritrtable, operation); - /* Check appended plans w/outer rangetable */ foreach(appendplans, app->appendplans) { ExecCheckPlanPerms((Plan *) lfirst(appendplans), @@ -474,15 +473,11 @@ ExecCheckPlanPerms(Plan *plan, List *rangeTable, CmdType operation) else { /* Append implements UNION, which must be a SELECT */ - List *rtables = app->unionrtables; - - /* Check appended plans with their rangetables */ foreach(appendplans, app->appendplans) { ExecCheckPlanPerms((Plan *) lfirst(appendplans), - (List *) lfirst(rtables), + rangeTable, CMD_SELECT); - rtables = lnext(rtables); } } break; diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c index d6a15371311..6269a7caa10 100644 --- a/src/backend/executor/execProcnode.c +++ b/src/backend/executor/execProcnode.c @@ -12,7 +12,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.20 2000/09/29 18:21:29 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.21 2000/10/05 19:11:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -88,6 +88,7 @@ #include "executor/nodeNestloop.h" #include "executor/nodeResult.h" #include "executor/nodeSeqscan.h" +#include "executor/nodeSetOp.h" #include "executor/nodeSort.h" #include "executor/nodeSubplan.h" #include "executor/nodeSubqueryscan.h" @@ -199,6 +200,10 @@ ExecInitNode(Plan *node, EState *estate, Plan *parent) result = ExecInitUnique((Unique *) node, estate, parent); break; + case T_SetOp: + result = ExecInitSetOp((SetOp *) node, estate, parent); + break; + case T_Group: result = ExecInitGroup((Group *) node, estate, parent); break; @@ -322,6 +327,10 @@ ExecProcNode(Plan *node, Plan *parent) result = ExecUnique((Unique *) node); break; + case T_SetOp: + result = ExecSetOp((SetOp *) node); + break; + case T_Group: result = ExecGroup((Group *) node); break; @@ -401,6 +410,9 @@ ExecCountSlotsNode(Plan *node) case T_Unique: return ExecCountSlotsUnique((Unique *) node); + case T_SetOp: + return ExecCountSlotsSetOp((SetOp *) node); + case T_Group: return ExecCountSlotsGroup((Group *) node); @@ -519,6 +531,10 @@ ExecEndNode(Plan *node, Plan *parent) ExecEndUnique((Unique *) node); break; + case T_SetOp: + ExecEndSetOp((SetOp *) node); + break; + case T_Group: ExecEndGroup((Group *) node); break; diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index 008105719f3..d1cdfabab3b 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.40 2000/09/29 18:21:29 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.41 2000/10/05 19:11:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -762,6 +762,14 @@ NodeGetResultTupleSlot(Plan *node) } break; + case T_SetOp: + { + SetOpState *setopstate = ((SetOp *) node)->setopstate; + + slot = setopstate->cstate.cs_ResultTupleSlot; + } + break; + case T_MergeJoin: { MergeJoinState *mergestate = ((MergeJoin *) node)->mergestate; @@ -783,8 +791,8 @@ NodeGetResultTupleSlot(Plan *node) * should never get here * ---------------- */ - elog(ERROR, "NodeGetResultTupleSlot: node not yet supported: %d ", - nodeTag(node)); + elog(ERROR, "NodeGetResultTupleSlot: node not yet supported: %d", + (int) nodeTag(node)); return NULL; } diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c index 2b1eceb15d9..6c547854b55 100644 --- a/src/backend/executor/nodeAppend.c +++ b/src/backend/executor/nodeAppend.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.35 2000/07/12 02:37:03 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.36 2000/10/05 19:11:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -80,11 +80,9 @@ exec_append_initialize_next(Append *node) AppendState *appendstate; TupleTableSlot *result_slot; List *rangeTable; - int whichplan; int nplans; - List *rtables; - List *rtable; + List *inheritrtable; RangeTblEntry *rtentry; /* ---------------- @@ -98,8 +96,7 @@ exec_append_initialize_next(Append *node) whichplan = appendstate->as_whichplan; nplans = appendstate->as_nplans; - rtables = node->unionrtables; - rtable = node->inheritrtable; + inheritrtable = node->inheritrtable; if (whichplan < 0) { @@ -131,19 +128,17 @@ exec_append_initialize_next(Append *node) /* ---------------- * initialize the scan * (and update the range table appropriately) - * (doesn't this leave the range table hosed for anybody upstream - * of the Append node??? - jolly ) + * + * (doesn't this leave the range table hosed for anybody upstream + * of the Append node??? - jolly ) * ---------------- */ if (node->inheritrelid > 0) { - rtentry = nth(whichplan, rtable); + rtentry = nth(whichplan, inheritrtable); Assert(rtentry != NULL); - rt_store(node->inheritrelid, rangeTable, rtentry); } - else - estate->es_range_table = nth(whichplan, rtables); if (appendstate->as_junkFilter_list) { @@ -181,7 +176,7 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent) { AppendState *appendstate; int nplans; - List *rtable; + List *inheritrtable; List *appendplans; bool *initialized; int i; @@ -201,7 +196,7 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent) appendplans = node->appendplans; nplans = length(appendplans); - rtable = node->inheritrtable; + inheritrtable = node->inheritrtable; initialized = (bool *) palloc(nplans * sizeof(bool)); MemSet(initialized, 0, nplans * sizeof(bool)); @@ -214,7 +209,6 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent) appendstate->as_whichplan = 0; appendstate->as_nplans = nplans; appendstate->as_initialized = initialized; - appendstate->as_rtentries = rtable; node->appendstate = appendstate; @@ -250,7 +244,7 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent) inherited_result_rel = true; - foreach(rtentryP, rtable) + foreach(rtentryP, inheritrtable) { RangeTblEntry *rtentry = lfirst(rtentryP); Oid reloid = rtentry->relid; @@ -522,8 +516,7 @@ ExecEndAppend(Append *node) estate->es_result_relation_info = NULL; /* - * XXX should free appendstate->as_rtentries and - * appendstate->as_junkfilter_list here + * XXX should free appendstate->as_junkfilter_list here */ } void diff --git a/src/backend/executor/nodeSetOp.c b/src/backend/executor/nodeSetOp.c new file mode 100644 index 00000000000..8c285525051 --- /dev/null +++ b/src/backend/executor/nodeSetOp.c @@ -0,0 +1,341 @@ +/*------------------------------------------------------------------------- + * + * nodeSetOp.c + * Routines to handle INTERSECT and EXCEPT selection + * + * The input of a SetOp node consists of tuples from two relations, + * which have been combined into one dataset and sorted on all the nonjunk + * attributes. In addition there is a junk attribute that shows which + * relation each tuple came from. The SetOp node scans each group of + * identical tuples to determine how many came from each input relation. + * Then it is a simple matter to emit the output demanded by the SQL spec + * for INTERSECT, INTERSECT ALL, EXCEPT, or EXCEPT ALL. + * + * This node type is not used for UNION or UNION ALL, since those can be + * implemented more cheaply (there's no need for the junk attribute to + * identify the source relation). + * + * + * Portions Copyright (c) 1996-2000, PostgreSQL, Inc + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * $Header: /cvsroot/pgsql/src/backend/executor/nodeSetOp.c,v 1.1 2000/10/05 19:11:26 tgl Exp $ + * + *------------------------------------------------------------------------- + */ +/* + * INTERFACE ROUTINES + * ExecSetOp - filter input to generate INTERSECT/EXCEPT results + * ExecInitSetOp - initialize node and subnodes.. + * ExecEndSetOp - shutdown node and subnodes + */ + +#include "postgres.h" + +#include "access/heapam.h" +#include "executor/executor.h" +#include "executor/nodeGroup.h" +#include "executor/nodeSetOp.h" + +/* ---------------------------------------------------------------- + * ExecSetOp + * ---------------------------------------------------------------- + */ +TupleTableSlot * /* return: a tuple or NULL */ +ExecSetOp(SetOp *node) +{ + SetOpState *setopstate; + TupleTableSlot *resultTupleSlot; + Plan *outerPlan; + TupleDesc tupDesc; + + /* ---------------- + * get information from the node + * ---------------- + */ + setopstate = node->setopstate; + outerPlan = outerPlan((Plan *) node); + resultTupleSlot = setopstate->cstate.cs_ResultTupleSlot; + tupDesc = ExecGetResultType(&setopstate->cstate); + + /* ---------------- + * If the previously-returned tuple needs to be returned more than + * once, keep returning it. + * ---------------- + */ + if (setopstate->numOutput > 0) + { + setopstate->numOutput--; + return resultTupleSlot; + } + + /* Flag that we have no current tuple */ + ExecClearTuple(resultTupleSlot); + + /* ---------------- + * Absorb groups of duplicate tuples, counting them, and + * saving the first of each group as a possible return value. + * At the end of each group, decide whether to return anything. + * + * We assume that the tuples arrive in sorted order + * so we can detect duplicates easily. + * ---------------- + */ + for (;;) + { + TupleTableSlot *inputTupleSlot; + bool endOfGroup; + + /* ---------------- + * fetch a tuple from the outer subplan, unless we already did. + * ---------------- + */ + if (setopstate->cstate.cs_OuterTupleSlot == NULL && + ! setopstate->subplan_done) + { + setopstate->cstate.cs_OuterTupleSlot = + ExecProcNode(outerPlan, (Plan *) node); + if (TupIsNull(setopstate->cstate.cs_OuterTupleSlot)) + setopstate->subplan_done = true; + } + inputTupleSlot = setopstate->cstate.cs_OuterTupleSlot; + + if (TupIsNull(resultTupleSlot)) + { + /* + * First of group: save a copy in result slot, and reset + * duplicate-counters for new group. + */ + if (setopstate->subplan_done) + return NULL; /* no more tuples */ + ExecStoreTuple(heap_copytuple(inputTupleSlot->val), + resultTupleSlot, + InvalidBuffer, + true); /* free copied tuple at ExecClearTuple */ + setopstate->numLeft = 0; + setopstate->numRight = 0; + endOfGroup = false; + } + else if (setopstate->subplan_done) + { + /* + * Reached end of input, so finish processing final group + */ + endOfGroup = true; + } + else + { + /* + * Else test if the new tuple and the previously saved tuple match. + */ + if (execTuplesMatch(inputTupleSlot->val, + resultTupleSlot->val, + tupDesc, + node->numCols, node->dupColIdx, + setopstate->eqfunctions, + setopstate->tempContext)) + endOfGroup = false; + else + endOfGroup = true; + } + + if (endOfGroup) + { + /* + * We've reached the end of the group containing resultTuple. + * Decide how many copies (if any) to emit. This logic is + * straight from the SQL92 specification. + */ + switch (node->cmd) + { + case SETOPCMD_INTERSECT: + if (setopstate->numLeft > 0 && setopstate->numRight > 0) + setopstate->numOutput = 1; + else + setopstate->numOutput = 0; + break; + case SETOPCMD_INTERSECT_ALL: + setopstate->numOutput = + (setopstate->numLeft < setopstate->numRight) ? + setopstate->numLeft : setopstate->numRight; + break; + case SETOPCMD_EXCEPT: + if (setopstate->numLeft > 0 && setopstate->numRight == 0) + setopstate->numOutput = 1; + else + setopstate->numOutput = 0; + break; + case SETOPCMD_EXCEPT_ALL: + setopstate->numOutput = + (setopstate->numLeft < setopstate->numRight) ? + 0 : (setopstate->numLeft - setopstate->numRight); + break; + default: + elog(ERROR, "ExecSetOp: bogus command code %d", + (int) node->cmd); + break; + } + /* Fall out of for-loop if we have tuples to emit */ + if (setopstate->numOutput > 0) + break; + /* Else flag that we have no current tuple, and loop around */ + ExecClearTuple(resultTupleSlot); + } + else + { + /* + * Current tuple is member of same group as resultTuple. + * Count it in the appropriate counter. + */ + int flag; + bool isNull; + + flag = DatumGetInt32(heap_getattr(inputTupleSlot->val, + node->flagColIdx, + tupDesc, + &isNull)); + Assert(!isNull); + if (flag) + setopstate->numRight++; + else + setopstate->numLeft++; + /* Set flag to fetch a new input tuple, and loop around */ + setopstate->cstate.cs_OuterTupleSlot = NULL; + } + } + + /* + * If we fall out of loop, then we need to emit at least one copy + * of resultTuple. + */ + Assert(setopstate->numOutput > 0); + setopstate->numOutput--; + return resultTupleSlot; +} + +/* ---------------------------------------------------------------- + * ExecInitSetOp + * + * This initializes the setop node state structures and + * the node's subplan. + * ---------------------------------------------------------------- + */ +bool /* return: initialization status */ +ExecInitSetOp(SetOp *node, EState *estate, Plan *parent) +{ + SetOpState *setopstate; + Plan *outerPlan; + + /* ---------------- + * assign execution state to node + * ---------------- + */ + node->plan.state = estate; + + /* ---------------- + * create new SetOpState for node + * ---------------- + */ + setopstate = makeNode(SetOpState); + node->setopstate = setopstate; + setopstate->cstate.cs_OuterTupleSlot = NULL; + setopstate->subplan_done = false; + setopstate->numOutput = 0; + + /* ---------------- + * Miscellaneous initialization + * + * SetOp nodes have no ExprContext initialization because + * they never call ExecQual or ExecProject. But they do need a + * per-tuple memory context anyway for calling execTuplesMatch. + * ---------------- + */ + setopstate->tempContext = + AllocSetContextCreate(CurrentMemoryContext, + "SetOp", + ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, + ALLOCSET_DEFAULT_MAXSIZE); + +#define SETOP_NSLOTS 1 + /* ------------ + * Tuple table initialization + * ------------ + */ + ExecInitResultTupleSlot(estate, &setopstate->cstate); + + /* ---------------- + * then initialize outer plan + * ---------------- + */ + outerPlan = outerPlan((Plan *) node); + ExecInitNode(outerPlan, estate, (Plan *) node); + + /* ---------------- + * setop nodes do no projections, so initialize + * projection info for this node appropriately + * ---------------- + */ + ExecAssignResultTypeFromOuterPlan((Plan *) node, &setopstate->cstate); + setopstate->cstate.cs_ProjInfo = NULL; + + /* + * Precompute fmgr lookup data for inner loop + */ + setopstate->eqfunctions = + execTuplesMatchPrepare(ExecGetResultType(&setopstate->cstate), + node->numCols, + node->dupColIdx); + + return TRUE; +} + +int +ExecCountSlotsSetOp(SetOp *node) +{ + return ExecCountSlotsNode(outerPlan(node)) + + ExecCountSlotsNode(innerPlan(node)) + + SETOP_NSLOTS; +} + +/* ---------------------------------------------------------------- + * ExecEndSetOp + * + * This shuts down the subplan and frees resources allocated + * to this node. + * ---------------------------------------------------------------- + */ +void +ExecEndSetOp(SetOp *node) +{ + SetOpState *setopstate = node->setopstate; + + ExecEndNode(outerPlan((Plan *) node), (Plan *) node); + + MemoryContextDelete(setopstate->tempContext); + + /* clean up tuple table */ + ExecClearTuple(setopstate->cstate.cs_ResultTupleSlot); + setopstate->cstate.cs_OuterTupleSlot = NULL; +} + + +void +ExecReScanSetOp(SetOp *node, ExprContext *exprCtxt, Plan *parent) +{ + SetOpState *setopstate = node->setopstate; + + ExecClearTuple(setopstate->cstate.cs_ResultTupleSlot); + setopstate->cstate.cs_OuterTupleSlot = NULL; + setopstate->subplan_done = false; + setopstate->numOutput = 0; + + /* + * if chgParam of subnode is not null then plan will be re-scanned by + * first ExecProcNode. + */ + if (((Plan *) node)->lefttree->chgParam == NULL) + ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node); +} diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index aee6911e5e4..933dcc83425 100644 --- a/src/backend/executor/nodeSubplan.c +++ b/src/backend/executor/nodeSubplan.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.27 2000/08/24 03:29:03 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.28 2000/10/05 19:11:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -328,7 +328,14 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent) /* ---------------------------------------------------------------- * ExecSetParamPlan * - * Executes plan of node and sets parameters. + * Executes an InitPlan subplan and sets its output parameters. + * + * This is called from ExecEvalParam() when the value of a PARAM_EXEC + * parameter is requested and the param's execPlan field is set (indicating + * that the param has not yet been evaluated). This allows lazy evaluation + * of initplans: we don't run the subplan until/unless we need its output. + * Note that this routine MUST clear the execPlan fields of the plan's + * output parameters after evaluating them! * ---------------------------------------------------------------- */ void @@ -424,13 +431,13 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext) } } - MemoryContextSwitchTo(oldcontext); - if (plan->extParam == NULL) /* un-correlated ... */ { ExecEndNode(plan, plan); node->needShutdown = false; } + + MemoryContextSwitchTo(oldcontext); } /* ---------------------------------------------------------------- @@ -470,6 +477,9 @@ ExecReScanSetParamPlan(SubPlan *node, Plan *parent) * node->plan->chgParam is not NULL... ExecReScan (plan, NULL, plan); */ + /* + * Mark this subplan's output parameters as needing recalculation + */ foreach(lst, node->setParam) { ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(lst)]); diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c index 45f07a08b10..5593f71d0c6 100644 --- a/src/backend/executor/nodeSubqueryscan.c +++ b/src/backend/executor/nodeSubqueryscan.c @@ -3,12 +3,16 @@ * nodeSubqueryscan.c * Support routines for scanning subqueries (subselects in rangetable). * + * This is just enough different from sublinks (nodeSubplan.c) to mean that + * we need two sets of code. Ought to look at trying to unify the cases. + * + * * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.1 2000/09/29 18:21:29 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.2 2000/10/05 19:11:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -49,9 +53,7 @@ SubqueryNext(SubqueryScan *node) SubqueryScanState *subquerystate; EState *estate; ScanDirection direction; - int execdir; TupleTableSlot *slot; - Const countOne; /* ---------------- * get information from the estate and scan state @@ -60,7 +62,6 @@ SubqueryNext(SubqueryScan *node) estate = node->scan.plan.state; subquerystate = (SubqueryScanState *) node->scan.scanstate; direction = estate->es_direction; - execdir = ScanDirectionIsBackward(direction) ? EXEC_BACK : EXEC_FOR; slot = subquerystate->csstate.css_ScanTupleSlot; /* @@ -85,25 +86,13 @@ SubqueryNext(SubqueryScan *node) return (slot); } - memset(&countOne, 0, sizeof(countOne)); - countOne.type = T_Const; - countOne.consttype = INT4OID; - countOne.constlen = sizeof(int4); - countOne.constvalue = Int32GetDatum(1); - countOne.constisnull = false; - countOne.constbyval = true; - countOne.constisset = false; - countOne.constiscast = false; - /* ---------------- * get the next tuple from the sub-query * ---------------- */ - slot = ExecutorRun(subquerystate->sss_SubQueryDesc, - subquerystate->sss_SubEState, - execdir, - NULL, /* offset */ - (Node *) &countOne); + subquerystate->sss_SubEState->es_direction = direction; + + slot = ExecProcNode(node->subplan, node->subplan); subquerystate->csstate.css_ScanTupleSlot = slot; @@ -139,6 +128,7 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, Plan *parent) { SubqueryScanState *subquerystate; RangeTblEntry *rte; + EState *sp_estate; /* ---------------- * SubqueryScan should not have any "normal" children. @@ -177,18 +167,25 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, Plan *parent) /* ---------------- * initialize subquery + * + * This should agree with ExecInitSubPlan * ---------------- */ rte = rt_fetch(node->scan.scanrelid, estate->es_range_table); Assert(rte->subquery != NULL); - subquerystate->sss_SubQueryDesc = CreateQueryDesc(rte->subquery, - node->subplan, - None); - subquerystate->sss_SubEState = CreateExecutorState(); + sp_estate = CreateExecutorState(); + subquerystate->sss_SubEState = sp_estate; + + sp_estate->es_range_table = rte->subquery->rtable; + sp_estate->es_param_list_info = estate->es_param_list_info; + sp_estate->es_param_exec_vals = estate->es_param_exec_vals; + sp_estate->es_tupleTable = + ExecCreateTupleTable(ExecCountSlotsNode(node->subplan) + 10); + sp_estate->es_snapshot = estate->es_snapshot; - ExecutorStart(subquerystate->sss_SubQueryDesc, - subquerystate->sss_SubEState); + if (!ExecInitNode(node->subplan, sp_estate, NULL)) + return false; subquerystate->csstate.css_ScanTupleSlot = NULL; subquerystate->csstate.cstate.cs_TupFromTlist = false; @@ -247,10 +244,9 @@ ExecEndSubqueryScan(SubqueryScan *node) * close down subquery * ---------------- */ - ExecutorEnd(subquerystate->sss_SubQueryDesc, - subquerystate->sss_SubEState); + ExecEndNode(node->subplan, node->subplan); - /* XXX we seem to be leaking the querydesc and sub-EState... */ + /* XXX we seem to be leaking the sub-EState and tuple table... */ subquerystate->csstate.css_ScanTupleSlot = NULL; @@ -284,6 +280,7 @@ ExecSubqueryReScan(SubqueryScan *node, ExprContext *exprCtxt, Plan *parent) return; } - ExecReScan(node->subplan, NULL, NULL); + ExecReScan(node->subplan, NULL, node->subplan); + subquerystate->csstate.css_ScanTupleSlot = NULL; } |