summaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
authorTom Lane2002-12-05 15:50:39 +0000
committerTom Lane2002-12-05 15:50:39 +0000
commit1fd0c59e25063e664f8a5cee6f723470c5979544 (patch)
treed7c1ba5ee25323021a65d0e419299162a9db9c19 /src/backend/executor
parent0f3b83edfaf65b6105b455f601c11af6e12170ca (diff)
Phase 1 of read-only-plans project: cause executor state nodes to point
to plan nodes, not vice-versa. All executor state nodes now inherit from struct PlanState. Copying of plan trees has been simplified by not storing a list of SubPlans in Plan nodes (eliminating duplicate links). The executor still needs such a list, but it can build it during ExecutorStart since it has to scan the plan tree anyway. No initdb forced since no stored-on-disk structures changed, but you will need a full recompile because of node-numbering changes.
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/README23
-rw-r--r--src/backend/executor/execAmi.c157
-rw-r--r--src/backend/executor/execMain.c263
-rw-r--r--src/backend/executor/execProcnode.c450
-rw-r--r--src/backend/executor/execQual.c168
-rw-r--r--src/backend/executor/execScan.c24
-rw-r--r--src/backend/executor/execTuples.c10
-rw-r--r--src/backend/executor/execUtils.c79
-rw-r--r--src/backend/executor/functions.c147
-rw-r--r--src/backend/executor/nodeAgg.c270
-rw-r--r--src/backend/executor/nodeAppend.c126
-rw-r--r--src/backend/executor/nodeFunctionscan.c140
-rw-r--r--src/backend/executor/nodeGroup.c129
-rw-r--r--src/backend/executor/nodeHash.c83
-rw-r--r--src/backend/executor/nodeHashjoin.c227
-rw-r--r--src/backend/executor/nodeIndexscan.c232
-rw-r--r--src/backend/executor/nodeLimit.c164
-rw-r--r--src/backend/executor/nodeMaterial.c104
-rw-r--r--src/backend/executor/nodeMergejoin.c383
-rw-r--r--src/backend/executor/nodeNestloop.c153
-rw-r--r--src/backend/executor/nodeResult.c122
-rw-r--r--src/backend/executor/nodeSeqscan.c147
-rw-r--r--src/backend/executor/nodeSetOp.c150
-rw-r--r--src/backend/executor/nodeSort.c126
-rw-r--r--src/backend/executor/nodeSubplan.c131
-rw-r--r--src/backend/executor/nodeSubqueryscan.c109
-rw-r--r--src/backend/executor/nodeTidscan.c189
-rw-r--r--src/backend/executor/nodeUnique.c102
-rw-r--r--src/backend/executor/spi.c110
29 files changed, 2251 insertions, 2267 deletions
diff --git a/src/backend/executor/README b/src/backend/executor/README
index 0a56c3fa6ae..d9b0ea1275a 100644
--- a/src/backend/executor/README
+++ b/src/backend/executor/README
@@ -1,4 +1,4 @@
-$Header: /cvsroot/pgsql/src/backend/executor/README,v 1.1 2001/05/15 00:35:50 tgl Exp $
+$Header: /cvsroot/pgsql/src/backend/executor/README,v 1.2 2002/12/05 15:50:30 tgl Exp $
The Postgres Executor
---------------------
@@ -39,6 +39,27 @@ delivered by the plan tree.
XXX a great deal more documentation needs to be written here...
+Plan Trees and State Trees
+--------------------------
+
+The plan tree delivered by the planner contains a tree of Plan nodes (struct
+types derived from struct Plan). Each Plan node may have expression trees
+associated with it, to represent its target list, qualification conditions,
+etc. During executor startup we build a parallel tree of identical structure
+containing executor state nodes --- every plan and expression node type has
+a corresponding executor state node type. Each node in the state tree has a
+pointer to its corresponding node in the plan tree, plus executor state data
+as needed to implement that node type. This arrangement allows the plan
+tree to be completely read-only as far as the executor is concerned: all data
+that is modified during execution is in the state tree. Read-only plan trees
+make life much simpler for plan caching and reuse.
+
+Altogether there are four classes of nodes used in these trees: Plan nodes,
+their corresponding PlanState nodes, Expr nodes, and their corresponding
+ExprState nodes. (Actually, there are also List nodes, which are used as
+"glue" in all four kinds of tree.)
+
+
EvalPlanQual (READ COMMITTED update checking)
---------------------------------------------
diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c
index 1d7bf67f60b..4ac4781ec7c 100644
--- a/src/backend/executor/execAmi.c
+++ b/src/backend/executor/execAmi.c
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: execAmi.c,v 1.65 2002/11/30 05:21:01 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.66 2002/12/05 15:50:30 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -19,12 +19,12 @@
#include "executor/instrument.h"
#include "executor/nodeAgg.h"
#include "executor/nodeAppend.h"
+#include "executor/nodeFunctionscan.h"
#include "executor/nodeGroup.h"
#include "executor/nodeGroup.h"
#include "executor/nodeHash.h"
#include "executor/nodeHashjoin.h"
#include "executor/nodeIndexscan.h"
-#include "executor/nodeTidscan.h"
#include "executor/nodeLimit.h"
#include "executor/nodeMaterial.h"
#include "executor/nodeMergejoin.h"
@@ -35,45 +35,45 @@
#include "executor/nodeSort.h"
#include "executor/nodeSubplan.h"
#include "executor/nodeSubqueryscan.h"
-#include "executor/nodeFunctionscan.h"
+#include "executor/nodeTidscan.h"
#include "executor/nodeUnique.h"
/* ----------------------------------------------------------------
* ExecReScan
*
- * XXX this should be extended to cope with all the node types..
- *
* takes the new expression context as an argument, so that
* index scans needn't have their scan keys updated separately
* - marcel 09/20/94
* ----------------------------------------------------------------
*/
void
-ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScan(PlanState *node, ExprContext *exprCtxt)
{
+ /* If collecting timing stats, update them */
if (node->instrument)
InstrEndLoop(node->instrument);
- if (node->chgParam != NULL) /* Wow! */
+ /* If we have changed parameters, propagate that info */
+ if (node->chgParam != NIL)
{
List *lst;
foreach(lst, node->initPlan)
{
- Plan *splan = ((SubPlan *) lfirst(lst))->plan;
+ PlanState *splan = ((SubPlanState *) lfirst(lst))->planstate;
- if (splan->extParam != NULL) /* don't care about child
+ if (splan->plan->extParam != NIL) /* don't care about child
* locParam */
SetChangedParamList(splan, node->chgParam);
- if (splan->chgParam != NULL)
- ExecReScanSetParamPlan((SubPlan *) lfirst(lst), node);
+ if (splan->chgParam != NIL)
+ ExecReScanSetParamPlan((SubPlanState *) lfirst(lst), node);
}
foreach(lst, node->subPlan)
{
- Plan *splan = ((SubPlan *) lfirst(lst))->plan;
+ PlanState *splan = ((SubPlanState *) lfirst(lst))->planstate;
- if (splan->extParam != NULL)
+ if (splan->plan->extParam != NIL)
SetChangedParamList(splan, node->chgParam);
}
/* Well. Now set chgParam for left/right trees. */
@@ -85,76 +85,76 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
switch (nodeTag(node))
{
- case T_SeqScan:
- ExecSeqReScan((SeqScan *) node, exprCtxt, parent);
+ case T_ResultState:
+ ExecReScanResult((ResultState *) node, exprCtxt);
break;
- case T_IndexScan:
- ExecIndexReScan((IndexScan *) node, exprCtxt, parent);
+ case T_AppendState:
+ ExecReScanAppend((AppendState *) node, exprCtxt);
break;
- case T_TidScan:
- ExecTidReScan((TidScan *) node, exprCtxt, parent);
+ case T_SeqScanState:
+ ExecSeqReScan((SeqScanState *) node, exprCtxt);
break;
- case T_SubqueryScan:
- ExecSubqueryReScan((SubqueryScan *) node, exprCtxt, parent);
+ case T_IndexScanState:
+ ExecIndexReScan((IndexScanState *) node, exprCtxt);
break;
- case T_FunctionScan:
- ExecFunctionReScan((FunctionScan *) node, exprCtxt, parent);
+ case T_TidScanState:
+ ExecTidReScan((TidScanState *) node, exprCtxt);
break;
- case T_Material:
- ExecMaterialReScan((Material *) node, exprCtxt, parent);
+ case T_SubqueryScanState:
+ ExecSubqueryReScan((SubqueryScanState *) node, exprCtxt);
break;
- case T_NestLoop:
- ExecReScanNestLoop((NestLoop *) node, exprCtxt, parent);
+ case T_FunctionScanState:
+ ExecFunctionReScan((FunctionScanState *) node, exprCtxt);
break;
- case T_HashJoin:
- ExecReScanHashJoin((HashJoin *) node, exprCtxt, parent);
+ case T_NestLoopState:
+ ExecReScanNestLoop((NestLoopState *) node, exprCtxt);
break;
- case T_Hash:
- ExecReScanHash((Hash *) node, exprCtxt, parent);
+ case T_MergeJoinState:
+ ExecReScanMergeJoin((MergeJoinState *) node, exprCtxt);
break;
- case T_Agg:
- ExecReScanAgg((Agg *) node, exprCtxt, parent);
+ case T_HashJoinState:
+ ExecReScanHashJoin((HashJoinState *) node, exprCtxt);
break;
- case T_Group:
- ExecReScanGroup((Group *) node, exprCtxt, parent);
+ case T_MaterialState:
+ ExecMaterialReScan((MaterialState *) node, exprCtxt);
break;
- case T_Result:
- ExecReScanResult((Result *) node, exprCtxt, parent);
+ case T_SortState:
+ ExecReScanSort((SortState *) node, exprCtxt);
break;
- case T_Unique:
- ExecReScanUnique((Unique *) node, exprCtxt, parent);
+ case T_GroupState:
+ ExecReScanGroup((GroupState *) node, exprCtxt);
break;
- case T_SetOp:
- ExecReScanSetOp((SetOp *) node, exprCtxt, parent);
+ case T_AggState:
+ ExecReScanAgg((AggState *) node, exprCtxt);
break;
- case T_Limit:
- ExecReScanLimit((Limit *) node, exprCtxt, parent);
+ case T_UniqueState:
+ ExecReScanUnique((UniqueState *) node, exprCtxt);
break;
- case T_Sort:
- ExecReScanSort((Sort *) node, exprCtxt, parent);
+ case T_HashState:
+ ExecReScanHash((HashState *) node, exprCtxt);
break;
- case T_MergeJoin:
- ExecReScanMergeJoin((MergeJoin *) node, exprCtxt, parent);
+ case T_SetOpState:
+ ExecReScanSetOp((SetOpState *) node, exprCtxt);
break;
- case T_Append:
- ExecReScanAppend((Append *) node, exprCtxt, parent);
+ case T_LimitState:
+ ExecReScanLimit((LimitState *) node, exprCtxt);
break;
default:
@@ -163,10 +163,10 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
return;
}
- if (node->chgParam != NULL)
+ if (node->chgParam != NIL)
{
freeList(node->chgParam);
- node->chgParam = NULL;
+ node->chgParam = NIL;
}
}
@@ -176,37 +176,37 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
* Marks the current scan position.
*/
void
-ExecMarkPos(Plan *node)
+ExecMarkPos(PlanState *node)
{
switch (nodeTag(node))
{
- case T_SeqScan:
- ExecSeqMarkPos((SeqScan *) node);
+ case T_SeqScanState:
+ ExecSeqMarkPos((SeqScanState *) node);
break;
- case T_IndexScan:
- ExecIndexMarkPos((IndexScan *) node);
+ case T_IndexScanState:
+ ExecIndexMarkPos((IndexScanState *) node);
break;
- case T_TidScan:
- ExecTidMarkPos((TidScan *) node);
+ case T_TidScanState:
+ ExecTidMarkPos((TidScanState *) node);
break;
- case T_FunctionScan:
- ExecFunctionMarkPos((FunctionScan *) node);
+ case T_FunctionScanState:
+ ExecFunctionMarkPos((FunctionScanState *) node);
break;
- case T_Material:
- ExecMaterialMarkPos((Material *) node);
+ case T_MaterialState:
+ ExecMaterialMarkPos((MaterialState *) node);
break;
- case T_Sort:
- ExecSortMarkPos((Sort *) node);
+ case T_SortState:
+ ExecSortMarkPos((SortState *) node);
break;
default:
/* don't make hard error unless caller asks to restore... */
- elog(LOG, "ExecMarkPos: node type %d not supported",
+ elog(DEBUG1, "ExecMarkPos: node type %d not supported",
nodeTag(node));
break;
}
@@ -218,32 +218,32 @@ ExecMarkPos(Plan *node)
* restores the scan position previously saved with ExecMarkPos()
*/
void
-ExecRestrPos(Plan *node)
+ExecRestrPos(PlanState *node)
{
switch (nodeTag(node))
{
- case T_SeqScan:
- ExecSeqRestrPos((SeqScan *) node);
+ case T_SeqScanState:
+ ExecSeqRestrPos((SeqScanState *) node);
break;
- case T_IndexScan:
- ExecIndexRestrPos((IndexScan *) node);
+ case T_IndexScanState:
+ ExecIndexRestrPos((IndexScanState *) node);
break;
- case T_TidScan:
- ExecTidRestrPos((TidScan *) node);
+ case T_TidScanState:
+ ExecTidRestrPos((TidScanState *) node);
break;
- case T_FunctionScan:
- ExecFunctionRestrPos((FunctionScan *) node);
+ case T_FunctionScanState:
+ ExecFunctionRestrPos((FunctionScanState *) node);
break;
- case T_Material:
- ExecMaterialRestrPos((Material *) node);
+ case T_MaterialState:
+ ExecMaterialRestrPos((MaterialState *) node);
break;
- case T_Sort:
- ExecSortRestrPos((Sort *) node);
+ case T_SortState:
+ ExecSortRestrPos((SortState *) node);
break;
default:
@@ -258,6 +258,7 @@ ExecRestrPos(Plan *node)
*
* XXX Ideally, all plan node types would support mark/restore, and this
* wouldn't be needed. For now, this had better match the routines above.
+ * But note the test is on Plan nodetype, not PlanState nodetype.
*/
bool
ExecSupportsMarkRestore(NodeTag plantype)
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 92026666894..15d47df669f 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -12,10 +12,9 @@
* ExecutorRun() and ExecutorEnd()
*
* These three procedures are the external interfaces to the executor.
- * In each case, the query descriptor and the execution state is required
- * as arguments
+ * In each case, the query descriptor is required as an argument.
*
- * ExecutorStart() must be called at the beginning of any execution of any
+ * ExecutorStart() must be called at the beginning of execution of any
* query plan and ExecutorEnd() should always be called at the end of
* execution of a plan.
*
@@ -27,7 +26,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.189 2002/12/05 04:04:42 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.190 2002/12/05 15:50:30 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -48,16 +47,13 @@
/* decls for local routines only used within this module */
-static TupleDesc InitPlan(CmdType operation,
- Query *parseTree,
- Plan *plan,
- EState *estate);
+static void InitPlan(QueryDesc *queryDesc);
static void initResultRelInfo(ResultRelInfo *resultRelInfo,
Index resultRelationIndex,
List *rangeTable,
CmdType operation);
-static void EndPlan(Plan *plan, EState *estate);
-static TupleTableSlot *ExecutePlan(EState *estate, Plan *plan,
+static void EndPlan(PlanState *planstate, EState *estate);
+static TupleTableSlot *ExecutePlan(EState *estate, PlanState *planstate,
CmdType operation,
long numberTuples,
ScanDirection direction,
@@ -73,11 +69,6 @@ static void ExecUpdate(TupleTableSlot *slot, ItemPointer tupleid,
EState *estate);
static TupleTableSlot *EvalPlanQualNext(EState *estate);
static void EndEvalPlanQual(EState *estate);
-static void ExecCheckQueryPerms(CmdType operation, Query *parseTree,
- Plan *plan);
-static void ExecCheckPlanPerms(Plan *plan, List *rangeTable,
- CmdType operation);
-static void ExecCheckRTPerms(List *rangeTable, CmdType operation);
static void ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation);
/* end of local decls */
@@ -89,26 +80,40 @@ static void ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation);
* This routine must be called at the beginning of any execution of any
* query plan
*
- * returns a TupleDesc which describes the attributes of the tuples to
- * be returned by the query. (Same value is saved in queryDesc)
+ * Takes a QueryDesc previously created by CreateQueryDesc (it's not real
+ * clear why we bother to separate the two functions, but...). The tupDesc
+ * field of the QueryDesc is filled in to describe the tuples that will be
+ * returned, and the internal fields (estate and planstate) are set up.
*
+ * XXX this will change soon:
* NB: the CurrentMemoryContext when this is called must be the context
* to be used as the per-query context for the query plan. ExecutorRun()
* and ExecutorEnd() must be called in this same memory context.
* ----------------------------------------------------------------
*/
-TupleDesc
-ExecutorStart(QueryDesc *queryDesc, EState *estate)
+void
+ExecutorStart(QueryDesc *queryDesc)
{
- TupleDesc result;
+ EState *estate;
- /* sanity checks */
+ /* sanity checks: queryDesc must not be started already */
Assert(queryDesc != NULL);
+ Assert(queryDesc->estate == NULL);
+
+ /*
+ * Build EState, fill with parameters from queryDesc
+ */
+ estate = CreateExecutorState();
+ queryDesc->estate = estate;
+
+ estate->es_param_list_info = queryDesc->params;
if (queryDesc->plantree->nParamExec > 0)
estate->es_param_exec_vals = (ParamExecData *)
palloc0(queryDesc->plantree->nParamExec * sizeof(ParamExecData));
+ estate->es_instrument = queryDesc->doInstrument;
+
/*
* Make our own private copy of the current query snapshot data.
*
@@ -119,16 +124,9 @@ ExecutorStart(QueryDesc *queryDesc, EState *estate)
estate->es_snapshot = CopyQuerySnapshot();
/*
- * Initialize the plan
+ * Initialize the plan state tree
*/
- result = InitPlan(queryDesc->operation,
- queryDesc->parsetree,
- queryDesc->plantree,
- estate);
-
- queryDesc->tupDesc = result;
-
- return result;
+ InitPlan(queryDesc);
}
/* ----------------------------------------------------------------
@@ -150,11 +148,11 @@ ExecutorStart(QueryDesc *queryDesc, EState *estate)
* ----------------------------------------------------------------
*/
TupleTableSlot *
-ExecutorRun(QueryDesc *queryDesc, EState *estate,
+ExecutorRun(QueryDesc *queryDesc,
ScanDirection direction, long count)
{
CmdType operation;
- Plan *plan;
+ EState *estate;
CommandDest dest;
DestReceiver *destfunc;
TupleTableSlot *result;
@@ -169,7 +167,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate,
* feature.
*/
operation = queryDesc->operation;
- plan = queryDesc->plantree;
+ estate = queryDesc->estate;
dest = queryDesc->dest;
/*
@@ -189,7 +187,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate,
result = NULL;
else
result = ExecutePlan(estate,
- plan,
+ queryDesc->planstate,
operation,
count,
direction,
@@ -211,12 +209,16 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate,
* ----------------------------------------------------------------
*/
void
-ExecutorEnd(QueryDesc *queryDesc, EState *estate)
+ExecutorEnd(QueryDesc *queryDesc)
{
+ EState *estate;
+
/* sanity checks */
Assert(queryDesc != NULL);
- EndPlan(queryDesc->plantree, estate);
+ estate = queryDesc->estate;
+
+ EndPlan(queryDesc->planstate, estate);
if (estate->es_snapshot != NULL)
{
@@ -235,97 +237,55 @@ ExecutorEnd(QueryDesc *queryDesc, EState *estate)
/*
- * ExecCheckQueryPerms
- * Check access permissions for all relations referenced in a query.
+ * CreateExecutorState
*/
-static void
-ExecCheckQueryPerms(CmdType operation, Query *parseTree, Plan *plan)
+EState *
+CreateExecutorState(void)
{
+ EState *state;
+
/*
- * Check RTEs in the query's primary rangetable.
+ * create a new executor state
*/
- ExecCheckRTPerms(parseTree->rtable, operation);
+ state = makeNode(EState);
/*
- * Search for subplans and APPEND nodes to check their rangetables.
+ * initialize the Executor State structure
*/
- ExecCheckPlanPerms(plan, parseTree->rtable, operation);
-}
-
-/*
- * ExecCheckPlanPerms
- * Recursively scan the plan tree to check access permissions in
- * subplans.
- */
-static void
-ExecCheckPlanPerms(Plan *plan, List *rangeTable, CmdType operation)
-{
- List *subp;
+ state->es_direction = ForwardScanDirection;
+ state->es_range_table = NIL;
- if (plan == NULL)
- return;
-
- /* Check subplans, which we assume are plain SELECT queries */
-
- foreach(subp, plan->initPlan)
- {
- SubPlan *subplan = (SubPlan *) lfirst(subp);
-
- ExecCheckRTPerms(subplan->rtable, CMD_SELECT);
- ExecCheckPlanPerms(subplan->plan, subplan->rtable, CMD_SELECT);
- }
- foreach(subp, plan->subPlan)
- {
- SubPlan *subplan = (SubPlan *) lfirst(subp);
+ state->es_result_relations = NULL;
+ state->es_num_result_relations = 0;
+ state->es_result_relation_info = NULL;
- ExecCheckRTPerms(subplan->rtable, CMD_SELECT);
- ExecCheckPlanPerms(subplan->plan, subplan->rtable, CMD_SELECT);
- }
+ state->es_junkFilter = NULL;
- /* Check lower plan nodes */
+ state->es_into_relation_descriptor = NULL;
- ExecCheckPlanPerms(plan->lefttree, rangeTable, operation);
- ExecCheckPlanPerms(plan->righttree, rangeTable, operation);
+ state->es_param_list_info = NULL;
+ state->es_param_exec_vals = NULL;
- /* Do node-type-specific checks */
+ state->es_tupleTable = NULL;
- switch (nodeTag(plan))
- {
- case T_SubqueryScan:
- {
- SubqueryScan *scan = (SubqueryScan *) plan;
- RangeTblEntry *rte;
+ state->es_query_cxt = CurrentMemoryContext;
- /* Recursively check the subquery */
- rte = rt_fetch(scan->scan.scanrelid, rangeTable);
- Assert(rte->rtekind == RTE_SUBQUERY);
- ExecCheckQueryPerms(operation, rte->subquery, scan->subplan);
- break;
- }
- case T_Append:
- {
- Append *app = (Append *) plan;
- List *appendplans;
+ state->es_instrument = false;
- foreach(appendplans, app->appendplans)
- {
- ExecCheckPlanPerms((Plan *) lfirst(appendplans),
- rangeTable,
- operation);
- }
- break;
- }
+ state->es_per_tuple_exprcontext = NULL;
- default:
- break;
- }
+ /*
+ * return the executor state structure
+ */
+ return state;
}
+
/*
* ExecCheckRTPerms
* Check access permissions for all relations listed in a range table.
*/
-static void
+void
ExecCheckRTPerms(List *rangeTable, CmdType operation)
{
List *lp;
@@ -350,11 +310,18 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
AclResult aclcheck_result;
/*
- * Only plain-relation RTEs need to be checked here. Subquery RTEs
- * will be checked when ExecCheckPlanPerms finds the SubqueryScan
- * node, and function RTEs are checked by init_fcache when the
- * function is prepared for execution. Join and special RTEs need no
- * checks.
+ * If it's a subquery, recursively examine its rangetable.
+ */
+ if (rte->rtekind == RTE_SUBQUERY)
+ {
+ ExecCheckRTPerms(rte->subquery->rtable, operation);
+ return;
+ }
+
+ /*
+ * Otherwise, only plain-relation RTEs need to be checked here.
+ * Function RTEs are checked by init_fcache when the function is prepared
+ * for execution. Join and special RTEs need no checks.
*/
if (rte->rtekind != RTE_RELATION)
return;
@@ -367,7 +334,7 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
*
* Note: GetUserId() is presently fast enough that there's no harm in
* calling it separately for each RTE. If that stops being true, we
- * could call it once in ExecCheckQueryPerms and pass the userid down
+ * could call it once in ExecCheckRTPerms and pass the userid down
* from there. But for now, no need for the extra clutter.
*/
userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
@@ -428,7 +395,8 @@ typedef struct execRowMark
typedef struct evalPlanQual
{
- Plan *plan;
+ Plan *plan; /* XXX temporary */
+ PlanState *planstate;
Index rti;
EState estate;
struct evalPlanQual *free;
@@ -441,17 +409,24 @@ typedef struct evalPlanQual
* and start up the rule manager
* ----------------------------------------------------------------
*/
-static TupleDesc
-InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
+static void
+InitPlan(QueryDesc *queryDesc)
{
+ CmdType operation = queryDesc->operation;
+ Query *parseTree = queryDesc->parsetree;
+ Plan *plan = queryDesc->plantree;
+ EState *estate = queryDesc->estate;
+ PlanState *planstate;
List *rangeTable;
Relation intoRelationDesc;
TupleDesc tupType;
/*
- * Do permissions checks.
+ * Do permissions checks. It's sufficient to examine the query's
+ * top rangetable here --- subplan RTEs will be checked during
+ * ExecInitSubPlan().
*/
- ExecCheckQueryPerms(operation, parseTree, plan);
+ ExecCheckRTPerms(parseTree->rtable, operation);
/*
* get information from query descriptor
@@ -575,14 +550,14 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
* query tree. This opens files, allocates storage and leaves us
* ready to start processing tuples.
*/
- ExecInitNode(plan, estate, NULL);
+ planstate = ExecInitNode(plan, estate);
/*
* Get the tuple descriptor describing the type of tuples to return.
* (this is especially important if we are creating a relation with
* "SELECT INTO")
*/
- tupType = ExecGetTupType(plan); /* tuple descriptor */
+ tupType = ExecGetTupType(planstate);
/*
* Initialize the junk filter if needed. SELECT and INSERT queries
@@ -627,26 +602,29 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
*/
if (parseTree->resultRelations != NIL)
{
- List *subplans;
+ PlanState **appendplans;
+ int as_nplans;
ResultRelInfo *resultRelInfo;
+ int i;
/* Top plan had better be an Append here. */
Assert(IsA(plan, Append));
Assert(((Append *) plan)->isTarget);
- subplans = ((Append *) plan)->appendplans;
- Assert(length(subplans) == estate->es_num_result_relations);
+ Assert(IsA(planstate, AppendState));
+ appendplans = ((AppendState *) planstate)->appendplans;
+ as_nplans = ((AppendState *) planstate)->as_nplans;
+ Assert(as_nplans == estate->es_num_result_relations);
resultRelInfo = estate->es_result_relations;
- while (subplans != NIL)
+ for (i = 0; i < as_nplans; i++)
{
- Plan *subplan = (Plan *) lfirst(subplans);
+ PlanState *subplan = appendplans[i];
JunkFilter *j;
- j = ExecInitJunkFilter(subplan->targetlist,
+ j = ExecInitJunkFilter(subplan->plan->targetlist,
ExecGetTupType(subplan),
ExecAllocTableSlot(estate->es_tupleTable));
resultRelInfo->ri_junkFilter = j;
resultRelInfo++;
- subplans = lnext(subplans);
}
/*
@@ -661,7 +639,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
/* Normal case with just one JunkFilter */
JunkFilter *j;
- j = ExecInitJunkFilter(plan->targetlist,
+ j = ExecInitJunkFilter(planstate->plan->targetlist,
tupType,
ExecAllocTableSlot(estate->es_tupleTable));
estate->es_junkFilter = j;
@@ -755,7 +733,8 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
estate->es_into_relation_descriptor = intoRelationDesc;
- return tupType;
+ queryDesc->tupDesc = tupType;
+ queryDesc->planstate = planstate;
}
/*
@@ -816,11 +795,11 @@ initResultRelInfo(ResultRelInfo *resultRelInfo,
/* ----------------------------------------------------------------
* EndPlan
*
- * Cleans up the query plan -- closes files and free up storages
+ * Cleans up the query plan -- closes files and frees up storage
* ----------------------------------------------------------------
*/
static void
-EndPlan(Plan *plan, EState *estate)
+EndPlan(PlanState *planstate, EState *estate)
{
ResultRelInfo *resultRelInfo;
int i;
@@ -835,7 +814,7 @@ EndPlan(Plan *plan, EState *estate)
/*
* shut down the node-type-specific query processing
*/
- ExecEndNode(plan, NULL);
+ ExecEndNode(planstate);
/*
* destroy the executor "tuple" table.
@@ -902,7 +881,7 @@ EndPlan(Plan *plan, EState *estate)
*/
static TupleTableSlot *
ExecutePlan(EState *estate,
- Plan *plan,
+ PlanState *planstate,
CmdType operation,
long numberTuples,
ScanDirection direction,
@@ -964,10 +943,10 @@ lnext: ;
{
slot = EvalPlanQualNext(estate);
if (TupIsNull(slot))
- slot = ExecProcNode(plan, NULL);
+ slot = ExecProcNode(planstate);
}
else
- slot = ExecProcNode(plan, NULL);
+ slot = ExecProcNode(planstate);
/*
* if the tuple is null, then we assume there is nothing more to
@@ -1765,7 +1744,7 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
oldepq = (evalPlanQual *) epqstate->es_evalPlanQual;
Assert(oldepq->rti != 0);
/* stop execution */
- ExecEndNode(epq->plan, NULL);
+ ExecEndNode(epq->planstate);
ExecDropTupleTable(epqstate->es_tupleTable, true);
epqstate->es_tupleTable = NULL;
heap_freetuple(epqstate->es_evTuple[epq->rti - 1]);
@@ -1793,10 +1772,8 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
/*
* Each stack level has its own copy of the plan tree. This
- * is wasteful, but necessary as long as plan nodes point to
- * exec state nodes rather than vice versa. Note that
- * copyfuncs.c doesn't attempt to copy the exec state nodes,
- * which is a good thing in this situation.
+ * is wasteful, but necessary until plan trees are fully
+ * read-only.
*/
newepq->plan = copyObject(estate->es_origPlan);
@@ -1858,7 +1835,7 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
if (endNode)
{
/* stop execution */
- ExecEndNode(epq->plan, NULL);
+ ExecEndNode(epq->planstate);
ExecDropTupleTable(epqstate->es_tupleTable, true);
epqstate->es_tupleTable = NULL;
}
@@ -1886,7 +1863,7 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
epqstate->es_tupleTable =
ExecCreateTupleTable(estate->es_tupleTable->size);
- ExecInitNode(epq->plan, epqstate, NULL);
+ epq->planstate = ExecInitNode(epq->plan, epqstate);
return EvalPlanQualNext(estate);
}
@@ -1902,7 +1879,7 @@ EvalPlanQualNext(EState *estate)
Assert(epq->rti != 0);
lpqnext:;
- slot = ExecProcNode(epq->plan, NULL);
+ slot = ExecProcNode(epq->planstate);
/*
* No more tuples for this PQ. Continue previous one.
@@ -1910,7 +1887,7 @@ lpqnext:;
if (TupIsNull(slot))
{
/* stop execution */
- ExecEndNode(epq->plan, NULL);
+ ExecEndNode(epq->planstate);
ExecDropTupleTable(epqstate->es_tupleTable, true);
epqstate->es_tupleTable = NULL;
heap_freetuple(epqstate->es_evTuple[epq->rti - 1]);
@@ -1951,7 +1928,7 @@ EndEvalPlanQual(EState *estate)
for (;;)
{
/* stop execution */
- ExecEndNode(epq->plan, NULL);
+ ExecEndNode(epq->planstate);
ExecDropTupleTable(epqstate->es_tupleTable, true);
epqstate->es_tupleTable = NULL;
if (epqstate->es_evTuple[epq->rti - 1] != NULL)
diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c
index 2054a6cf059..2db4a146bc1 100644
--- a/src/backend/executor/execProcnode.c
+++ b/src/backend/executor/execProcnode.c
@@ -5,23 +5,23 @@
* "get a tuple", and "cleanup" routines for the given node type.
* If the node has children, then it will presumably call ExecInitNode,
* ExecProcNode, or ExecEndNode on its subnodes and do the appropriate
- * processing..
+ * processing.
*
* 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/executor/execProcnode.c,v 1.30 2002/06/20 20:29:27 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.31 2002/12/05 15:50:31 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* INTERFACE ROUTINES
+ * ExecCountSlotsNode - count tuple slots needed by plan tree
* ExecInitNode - initialize a plan node and its subplans
* ExecProcNode - get a tuple by executing the plan node
* ExecEndNode - shut down a plan node and its subplans
- * ExecCountSlotsNode - count tuple slots needed by plan tree
* ExecGetTupType - get result tuple type of a plan node
*
* NOTES
@@ -53,10 +53,12 @@
* * ExecInitNode() notices that it is looking at a nest loop and
* as the code below demonstrates, it calls ExecInitNestLoop().
* Eventually this calls ExecInitNode() on the right and left subplans
- * and so forth until the entire plan is initialized.
+ * and so forth until the entire plan is initialized. The result
+ * of ExecInitNode() is a plan state tree built with the same structure
+ * as the underlying plan tree.
*
- * * Then when ExecRun() is called, it calls ExecutePlan() which
- * calls ExecProcNode() repeatedly on the top node of the plan.
+ * * Then when ExecRun() is called, it calls ExecutePlan() which calls
+ * ExecProcNode() repeatedly on the top node of the plan state tree.
* Each time this happens, ExecProcNode() will end up calling
* ExecNestLoop(), which calls ExecProcNode() on its subplans.
* Each of these subplans is a sequential scan so ExecSeqScan() is
@@ -73,7 +75,6 @@
* ExecInitNode(), ExecProcNode() and ExecEndNode() dispatch
* their work to the appopriate node support routines which may
* in turn call these routines themselves on their subplans.
- *
*/
#include "postgres.h"
@@ -81,11 +82,11 @@
#include "executor/instrument.h"
#include "executor/nodeAgg.h"
#include "executor/nodeAppend.h"
+#include "executor/nodeFunctionscan.h"
#include "executor/nodeGroup.h"
#include "executor/nodeHash.h"
#include "executor/nodeHashjoin.h"
#include "executor/nodeIndexscan.h"
-#include "executor/nodeTidscan.h"
#include "executor/nodeLimit.h"
#include "executor/nodeMaterial.h"
#include "executor/nodeMergejoin.h"
@@ -96,7 +97,7 @@
#include "executor/nodeSort.h"
#include "executor/nodeSubplan.h"
#include "executor/nodeSubqueryscan.h"
-#include "executor/nodeFunctionscan.h"
+#include "executor/nodeTidscan.h"
#include "executor/nodeUnique.h"
#include "miscadmin.h"
#include "tcop/tcopprot.h"
@@ -109,32 +110,23 @@
*
* Initial States:
* 'node' is the plan produced by the query planner
+ * 'estate' is the shared execution state for the query tree
*
- * returns TRUE/FALSE on whether the plan was successfully initialized
+ * Returns a PlanState node corresponding to the given Plan node.
* ------------------------------------------------------------------------
*/
-bool
-ExecInitNode(Plan *node, EState *estate, Plan *parent)
+PlanState *
+ExecInitNode(Plan *node, EState *estate)
{
- bool result;
+ PlanState *result;
+ List *subps;
List *subp;
/*
* do nothing when we get to the end of a leaf on tree.
*/
if (node == NULL)
- return FALSE;
-
- /* Set up instrumentation for this node if the parent has it */
- if (!node->instrument && parent && parent->instrument)
- node->instrument = InstrAlloc();
-
- foreach(subp, node->initPlan)
- {
- result = ExecInitSubPlan((SubPlan *) lfirst(subp), estate, node);
- if (result == FALSE)
- return FALSE;
- }
+ return NULL;
switch (nodeTag(node))
{
@@ -142,104 +134,124 @@ ExecInitNode(Plan *node, EState *estate, Plan *parent)
* control nodes
*/
case T_Result:
- result = ExecInitResult((Result *) node, estate, parent);
+ result = (PlanState *) ExecInitResult((Result *) node, estate);
break;
case T_Append:
- result = ExecInitAppend((Append *) node, estate, parent);
+ result = (PlanState *) ExecInitAppend((Append *) node, estate);
break;
/*
* scan nodes
*/
case T_SeqScan:
- result = ExecInitSeqScan((SeqScan *) node, estate, parent);
+ result = (PlanState *) ExecInitSeqScan((SeqScan *) node, estate);
break;
case T_IndexScan:
- result = ExecInitIndexScan((IndexScan *) node, estate, parent);
+ result = (PlanState *) ExecInitIndexScan((IndexScan *) node, estate);
break;
case T_TidScan:
- result = ExecInitTidScan((TidScan *) node, estate, parent);
+ result = (PlanState *) ExecInitTidScan((TidScan *) node, estate);
break;
case T_SubqueryScan:
- result = ExecInitSubqueryScan((SubqueryScan *) node, estate,
- parent);
+ result = (PlanState *) ExecInitSubqueryScan((SubqueryScan *) node, estate);
break;
case T_FunctionScan:
- result = ExecInitFunctionScan((FunctionScan *) node, estate,
- parent);
+ result = (PlanState *) ExecInitFunctionScan((FunctionScan *) node, estate);
break;
/*
* join nodes
*/
case T_NestLoop:
- result = ExecInitNestLoop((NestLoop *) node, estate, parent);
+ result = (PlanState *) ExecInitNestLoop((NestLoop *) node, estate);
break;
case T_MergeJoin:
- result = ExecInitMergeJoin((MergeJoin *) node, estate, parent);
- break;
-
- case T_Hash:
- result = ExecInitHash((Hash *) node, estate, parent);
+ result = (PlanState *) ExecInitMergeJoin((MergeJoin *) node, estate);
break;
case T_HashJoin:
- result = ExecInitHashJoin((HashJoin *) node, estate, parent);
+ result = (PlanState *) ExecInitHashJoin((HashJoin *) node, estate);
break;
/*
* materialization nodes
*/
case T_Material:
- result = ExecInitMaterial((Material *) node, estate, parent);
+ result = (PlanState *) ExecInitMaterial((Material *) node, estate);
break;
case T_Sort:
- result = ExecInitSort((Sort *) node, estate, parent);
+ result = (PlanState *) ExecInitSort((Sort *) node, estate);
break;
- case T_Unique:
- result = ExecInitUnique((Unique *) node, estate, parent);
+ case T_Group:
+ result = (PlanState *) ExecInitGroup((Group *) node, estate);
break;
- case T_SetOp:
- result = ExecInitSetOp((SetOp *) node, estate, parent);
+ case T_Agg:
+ result = (PlanState *) ExecInitAgg((Agg *) node, estate);
break;
- case T_Limit:
- result = ExecInitLimit((Limit *) node, estate, parent);
+ case T_Unique:
+ result = (PlanState *) ExecInitUnique((Unique *) node, estate);
break;
- case T_Group:
- result = ExecInitGroup((Group *) node, estate, parent);
+ case T_Hash:
+ result = (PlanState *) ExecInitHash((Hash *) node, estate);
break;
- case T_Agg:
- result = ExecInitAgg((Agg *) node, estate, parent);
+ case T_SetOp:
+ result = (PlanState *) ExecInitSetOp((SetOp *) node, estate);
+ break;
+
+ case T_Limit:
+ result = (PlanState *) ExecInitLimit((Limit *) node, estate);
break;
default:
elog(ERROR, "ExecInitNode: node type %d unsupported",
(int) nodeTag(node));
- result = FALSE;
+ result = NULL; /* keep compiler quiet */
break;
}
- if (result != FALSE)
+ /*
+ * Initialize any initPlans present in this node. The planner put
+ * them in a separate list for us.
+ */
+ subps = NIL;
+ foreach(subp, node->initPlan)
{
- foreach(subp, node->subPlan)
- {
- result = ExecInitSubPlan((SubPlan *) lfirst(subp), estate, node);
- if (result == FALSE)
- return FALSE;
- }
+ SubPlan *subplan = (SubPlan *) lfirst(subp);
+
+ Assert(IsA(subplan, SubPlan));
+ subps = lappend(subps, ExecInitSubPlan(subplan, estate));
}
+ result->initPlan = subps;
+
+ /*
+ * Initialize any subPlans present in this node. These were found
+ * by ExecInitExpr during initialization of the PlanState.
+ */
+ subps = NIL;
+ foreach(subp, result->subPlan)
+ {
+ SubPlan *subplan = (SubPlan *) lfirst(subp);
+
+ Assert(IsA(subplan, SubPlan));
+ subps = lappend(subps, ExecInitSubPlan(subplan, estate));
+ }
+ result->subPlan = subps;
+
+ /* Set up instrumentation for this node if requested */
+ if (estate->es_instrument)
+ result->instrument = InstrAlloc();
return result;
}
@@ -248,12 +260,11 @@ ExecInitNode(Plan *node, EState *estate, Plan *parent)
/* ----------------------------------------------------------------
* ExecProcNode
*
- * Initial States:
- * the query tree must be initialized once by calling ExecInit.
+ * Execute the given node to return a(nother) tuple.
* ----------------------------------------------------------------
*/
TupleTableSlot *
-ExecProcNode(Plan *node, Plan *parent)
+ExecProcNode(PlanState *node)
{
TupleTableSlot *result;
@@ -265,8 +276,8 @@ ExecProcNode(Plan *node, Plan *parent)
if (node == NULL)
return NULL;
- if (node->chgParam != NULL) /* something changed */
- ExecReScan(node, NULL, parent); /* let ReScan handle this */
+ if (node->chgParam != NIL) /* something changed */
+ ExecReScan(node, NULL); /* let ReScan handle this */
if (node->instrument)
InstrStartNode(node->instrument);
@@ -276,85 +287,85 @@ ExecProcNode(Plan *node, Plan *parent)
/*
* control nodes
*/
- case T_Result:
- result = ExecResult((Result *) node);
+ case T_ResultState:
+ result = ExecResult((ResultState *) node);
break;
- case T_Append:
- result = ExecProcAppend((Append *) node);
+ case T_AppendState:
+ result = ExecProcAppend((AppendState *) node);
break;
/*
* scan nodes
*/
- case T_SeqScan:
- result = ExecSeqScan((SeqScan *) node);
+ case T_SeqScanState:
+ result = ExecSeqScan((SeqScanState *) node);
break;
- case T_IndexScan:
- result = ExecIndexScan((IndexScan *) node);
+ case T_IndexScanState:
+ result = ExecIndexScan((IndexScanState *) node);
break;
- case T_TidScan:
- result = ExecTidScan((TidScan *) node);
+ case T_TidScanState:
+ result = ExecTidScan((TidScanState *) node);
break;
- case T_SubqueryScan:
- result = ExecSubqueryScan((SubqueryScan *) node);
+ case T_SubqueryScanState:
+ result = ExecSubqueryScan((SubqueryScanState *) node);
break;
- case T_FunctionScan:
- result = ExecFunctionScan((FunctionScan *) node);
+ case T_FunctionScanState:
+ result = ExecFunctionScan((FunctionScanState *) node);
break;
/*
* join nodes
*/
- case T_NestLoop:
- result = ExecNestLoop((NestLoop *) node);
+ case T_NestLoopState:
+ result = ExecNestLoop((NestLoopState *) node);
break;
- case T_MergeJoin:
- result = ExecMergeJoin((MergeJoin *) node);
+ case T_MergeJoinState:
+ result = ExecMergeJoin((MergeJoinState *) node);
break;
- case T_Hash:
- result = ExecHash((Hash *) node);
- break;
-
- case T_HashJoin:
- result = ExecHashJoin((HashJoin *) node);
+ case T_HashJoinState:
+ result = ExecHashJoin((HashJoinState *) node);
break;
/*
* materialization nodes
*/
- case T_Material:
- result = ExecMaterial((Material *) node);
+ case T_MaterialState:
+ result = ExecMaterial((MaterialState *) node);
break;
- case T_Sort:
- result = ExecSort((Sort *) node);
+ case T_SortState:
+ result = ExecSort((SortState *) node);
break;
- case T_Unique:
- result = ExecUnique((Unique *) node);
+ case T_GroupState:
+ result = ExecGroup((GroupState *) node);
break;
- case T_SetOp:
- result = ExecSetOp((SetOp *) node);
+ case T_AggState:
+ result = ExecAgg((AggState *) node);
break;
- case T_Limit:
- result = ExecLimit((Limit *) node);
+ case T_UniqueState:
+ result = ExecUnique((UniqueState *) node);
break;
- case T_Group:
- result = ExecGroup((Group *) node);
+ case T_HashState:
+ result = ExecHash((HashState *) node);
break;
- case T_Agg:
- result = ExecAgg((Agg *) node);
+ case T_SetOpState:
+ result = ExecSetOp((SetOpState *) node);
+ break;
+
+ case T_LimitState:
+ result = ExecLimit((LimitState *) node);
break;
default:
@@ -370,10 +381,16 @@ ExecProcNode(Plan *node, Plan *parent)
return result;
}
+/*
+ * ExecCountSlotsNode - count up the number of tuple table slots needed
+ *
+ * Note that this scans a Plan tree, not a PlanState tree, because we
+ * haven't built the PlanState tree yet ...
+ */
int
ExecCountSlotsNode(Plan *node)
{
- if (node == (Plan *) NULL)
+ if (node == NULL)
return 0;
switch (nodeTag(node))
@@ -414,9 +431,6 @@ ExecCountSlotsNode(Plan *node)
case T_MergeJoin:
return ExecCountSlotsMergeJoin((MergeJoin *) node);
- case T_Hash:
- return ExecCountSlotsHash((Hash *) node);
-
case T_HashJoin:
return ExecCountSlotsHashJoin((HashJoin *) node);
@@ -429,26 +443,30 @@ ExecCountSlotsNode(Plan *node)
case T_Sort:
return ExecCountSlotsSort((Sort *) node);
+ case T_Group:
+ return ExecCountSlotsGroup((Group *) node);
+
+ case T_Agg:
+ return ExecCountSlotsAgg((Agg *) node);
+
case T_Unique:
return ExecCountSlotsUnique((Unique *) node);
+ case T_Hash:
+ return ExecCountSlotsHash((Hash *) node);
+
case T_SetOp:
return ExecCountSlotsSetOp((SetOp *) node);
case T_Limit:
return ExecCountSlotsLimit((Limit *) node);
- case T_Group:
- return ExecCountSlotsGroup((Group *) node);
-
- case T_Agg:
- return ExecCountSlotsAgg((Agg *) node);
-
default:
elog(ERROR, "ExecCountSlotsNode: node type %d unsupported",
(int) nodeTag(node));
break;
}
+
return 0;
}
@@ -464,7 +482,7 @@ ExecCountSlotsNode(Plan *node)
* ----------------------------------------------------------------
*/
void
-ExecEndNode(Plan *node, Plan *parent)
+ExecEndNode(PlanState *node)
{
List *subp;
@@ -474,14 +492,19 @@ ExecEndNode(Plan *node, Plan *parent)
if (node == NULL)
return;
+ if (node->instrument)
+ InstrEndLoop(node->instrument);
+
+ /* Clean up initPlans and subPlans */
foreach(subp, node->initPlan)
- ExecEndSubPlan((SubPlan *) lfirst(subp));
+ ExecEndSubPlan((SubPlanState *) lfirst(subp));
foreach(subp, node->subPlan)
- ExecEndSubPlan((SubPlan *) lfirst(subp));
- if (node->chgParam != NULL)
+ ExecEndSubPlan((SubPlanState *) lfirst(subp));
+
+ if (node->chgParam != NIL)
{
freeList(node->chgParam);
- node->chgParam = NULL;
+ node->chgParam = NIL;
}
switch (nodeTag(node))
@@ -489,85 +512,85 @@ ExecEndNode(Plan *node, Plan *parent)
/*
* control nodes
*/
- case T_Result:
- ExecEndResult((Result *) node);
+ case T_ResultState:
+ ExecEndResult((ResultState *) node);
break;
- case T_Append:
- ExecEndAppend((Append *) node);
+ case T_AppendState:
+ ExecEndAppend((AppendState *) node);
break;
/*
* scan nodes
*/
- case T_SeqScan:
- ExecEndSeqScan((SeqScan *) node);
+ case T_SeqScanState:
+ ExecEndSeqScan((SeqScanState *) node);
break;
- case T_IndexScan:
- ExecEndIndexScan((IndexScan *) node);
+ case T_IndexScanState:
+ ExecEndIndexScan((IndexScanState *) node);
break;
- case T_TidScan:
- ExecEndTidScan((TidScan *) node);
+ case T_TidScanState:
+ ExecEndTidScan((TidScanState *) node);
break;
- case T_SubqueryScan:
- ExecEndSubqueryScan((SubqueryScan *) node);
+ case T_SubqueryScanState:
+ ExecEndSubqueryScan((SubqueryScanState *) node);
break;
- case T_FunctionScan:
- ExecEndFunctionScan((FunctionScan *) node);
+ case T_FunctionScanState:
+ ExecEndFunctionScan((FunctionScanState *) node);
break;
/*
* join nodes
*/
- case T_NestLoop:
- ExecEndNestLoop((NestLoop *) node);
- break;
-
- case T_MergeJoin:
- ExecEndMergeJoin((MergeJoin *) node);
+ case T_NestLoopState:
+ ExecEndNestLoop((NestLoopState *) node);
break;
- case T_Hash:
- ExecEndHash((Hash *) node);
+ case T_MergeJoinState:
+ ExecEndMergeJoin((MergeJoinState *) node);
break;
- case T_HashJoin:
- ExecEndHashJoin((HashJoin *) node);
+ case T_HashJoinState:
+ ExecEndHashJoin((HashJoinState *) node);
break;
/*
* materialization nodes
*/
- case T_Material:
- ExecEndMaterial((Material *) node);
+ case T_MaterialState:
+ ExecEndMaterial((MaterialState *) node);
break;
- case T_Sort:
- ExecEndSort((Sort *) node);
+ case T_SortState:
+ ExecEndSort((SortState *) node);
break;
- case T_Unique:
- ExecEndUnique((Unique *) node);
+ case T_GroupState:
+ ExecEndGroup((GroupState *) node);
break;
- case T_SetOp:
- ExecEndSetOp((SetOp *) node);
+ case T_AggState:
+ ExecEndAgg((AggState *) node);
break;
- case T_Limit:
- ExecEndLimit((Limit *) node);
+ case T_UniqueState:
+ ExecEndUnique((UniqueState *) node);
break;
- case T_Group:
- ExecEndGroup((Group *) node);
+ case T_HashState:
+ ExecEndHash((HashState *) node);
break;
- case T_Agg:
- ExecEndAgg((Agg *) node);
+ case T_SetOpState:
+ ExecEndSetOp((SetOpState *) node);
+ break;
+
+ case T_LimitState:
+ ExecEndLimit((LimitState *) node);
break;
default:
@@ -575,9 +598,6 @@ ExecEndNode(Plan *node, Plan *parent)
(int) nodeTag(node));
break;
}
-
- if (node->instrument)
- InstrEndLoop(node->instrument);
}
@@ -592,7 +612,7 @@ ExecEndNode(Plan *node, Plan *parent)
* ----------------------------------------------------------------
*/
TupleDesc
-ExecGetTupType(Plan *node)
+ExecGetTupType(PlanState *node)
{
TupleTableSlot *slot;
@@ -601,147 +621,147 @@ ExecGetTupType(Plan *node)
switch (nodeTag(node))
{
- case T_Result:
+ case T_ResultState:
{
- ResultState *resstate = ((Result *) node)->resstate;
+ ResultState *resstate = (ResultState *) node;
- slot = resstate->cstate.cs_ResultTupleSlot;
+ slot = resstate->ps.ps_ResultTupleSlot;
}
break;
- case T_SeqScan:
+ case T_AppendState:
{
- CommonScanState *scanstate = ((SeqScan *) node)->scanstate;
+ AppendState *appendstate = (AppendState *) node;
- slot = scanstate->cstate.cs_ResultTupleSlot;
+ slot = appendstate->ps.ps_ResultTupleSlot;
}
break;
- case T_NestLoop:
+ case T_SeqScanState:
{
- NestLoopState *nlstate = ((NestLoop *) node)->nlstate;
+ SeqScanState *scanstate = (SeqScanState *) node;
- slot = nlstate->jstate.cs_ResultTupleSlot;
+ slot = scanstate->ps.ps_ResultTupleSlot;
}
break;
- case T_Append:
+ case T_IndexScanState:
{
- AppendState *appendstate = ((Append *) node)->appendstate;
+ IndexScanState *scanstate = (IndexScanState *) node;
- slot = appendstate->cstate.cs_ResultTupleSlot;
+ slot = scanstate->ss.ps.ps_ResultTupleSlot;
}
break;
- case T_IndexScan:
+ case T_TidScanState:
{
- CommonScanState *scanstate = ((IndexScan *) node)->scan.scanstate;
+ TidScanState *scanstate = (TidScanState *) node;
- slot = scanstate->cstate.cs_ResultTupleSlot;
+ slot = scanstate->ss.ps.ps_ResultTupleSlot;
}
break;
- case T_TidScan:
+ case T_SubqueryScanState:
{
- CommonScanState *scanstate = ((TidScan *) node)->scan.scanstate;
+ SubqueryScanState *scanstate = (SubqueryScanState *) node;
- slot = scanstate->cstate.cs_ResultTupleSlot;
+ slot = scanstate->ss.ps.ps_ResultTupleSlot;
}
break;
- case T_SubqueryScan:
+ case T_FunctionScanState:
{
- CommonScanState *scanstate = ((SubqueryScan *) node)->scan.scanstate;
+ FunctionScanState *scanstate = (FunctionScanState *) node;
- slot = scanstate->cstate.cs_ResultTupleSlot;
+ slot = scanstate->ss.ps.ps_ResultTupleSlot;
}
break;
- case T_FunctionScan:
+ case T_NestLoopState:
{
- CommonScanState *scanstate = ((FunctionScan *) node)->scan.scanstate;
+ NestLoopState *nlstate = (NestLoopState *) node;
- slot = scanstate->cstate.cs_ResultTupleSlot;
+ slot = nlstate->js.ps.ps_ResultTupleSlot;
}
break;
- case T_Material:
+ case T_MergeJoinState:
{
- MaterialState *matstate = ((Material *) node)->matstate;
+ MergeJoinState *mergestate = (MergeJoinState *) node;
- slot = matstate->csstate.css_ScanTupleSlot;
+ slot = mergestate->js.ps.ps_ResultTupleSlot;
}
break;
- case T_Sort:
+ case T_HashJoinState:
{
- SortState *sortstate = ((Sort *) node)->sortstate;
+ HashJoinState *hashjoinstate = (HashJoinState *) node;
- slot = sortstate->csstate.css_ScanTupleSlot;
+ slot = hashjoinstate->js.ps.ps_ResultTupleSlot;
}
break;
- case T_Agg:
+ case T_MaterialState:
{
- AggState *aggstate = ((Agg *) node)->aggstate;
+ MaterialState *matstate = (MaterialState *) node;
- slot = aggstate->csstate.cstate.cs_ResultTupleSlot;
+ slot = matstate->ss.ss_ScanTupleSlot;
}
break;
- case T_Group:
+ case T_SortState:
{
- GroupState *grpstate = ((Group *) node)->grpstate;
+ SortState *sortstate = (SortState *) node;
- slot = grpstate->csstate.cstate.cs_ResultTupleSlot;
+ slot = sortstate->ss.ss_ScanTupleSlot;
}
break;
- case T_Hash:
+ case T_GroupState:
{
- HashState *hashstate = ((Hash *) node)->hashstate;
+ GroupState *grpstate = (GroupState *) node;
- slot = hashstate->cstate.cs_ResultTupleSlot;
+ slot = grpstate->ss.ps.ps_ResultTupleSlot;
}
break;
- case T_Unique:
+ case T_AggState:
{
- UniqueState *uniquestate = ((Unique *) node)->uniquestate;
+ AggState *aggstate = (AggState *) node;
- slot = uniquestate->cstate.cs_ResultTupleSlot;
+ slot = aggstate->ss.ps.ps_ResultTupleSlot;
}
break;
- case T_SetOp:
+ case T_UniqueState:
{
- SetOpState *setopstate = ((SetOp *) node)->setopstate;
+ UniqueState *uniquestate = (UniqueState *) node;
- slot = setopstate->cstate.cs_ResultTupleSlot;
+ slot = uniquestate->ps.ps_ResultTupleSlot;
}
break;
- case T_Limit:
+ case T_HashState:
{
- LimitState *limitstate = ((Limit *) node)->limitstate;
+ HashState *hashstate = (HashState *) node;
- slot = limitstate->cstate.cs_ResultTupleSlot;
+ slot = hashstate->ps.ps_ResultTupleSlot;
}
break;
- case T_MergeJoin:
+ case T_SetOpState:
{
- MergeJoinState *mergestate = ((MergeJoin *) node)->mergestate;
+ SetOpState *setopstate = (SetOpState *) node;
- slot = mergestate->jstate.cs_ResultTupleSlot;
+ slot = setopstate->ps.ps_ResultTupleSlot;
}
break;
- case T_HashJoin:
+ case T_LimitState:
{
- HashJoinState *hashjoinstate = ((HashJoin *) node)->hashjoinstate;
+ LimitState *limitstate = (LimitState *) node;
- slot = hashjoinstate->jstate.cs_ResultTupleSlot;
+ slot = limitstate->ps.ps_ResultTupleSlot;
}
break;
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index cb31c025df2..e7c724c66ed 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.112 2002/12/01 20:27:32 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.113 2002/12/05 15:50:31 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1766,7 +1766,8 @@ ExecEvalExpr(Node *expression,
isNull, isDone);
break;
case SUBPLAN_EXPR:
- retDatum = ExecSubPlan((SubPlan *) expr->oper,
+ /* XXX temporary hack to find exec state node */
+ retDatum = ExecSubPlan(((SubPlan *) expr->oper)->pstate,
expr->args, econtext,
isNull);
break;
@@ -1850,6 +1851,169 @@ ExecEvalExprSwitchContext(Node *expression,
}
+/*
+ * ExecInitExpr: prepare an expression tree for execution
+ *
+ * 'node' is the root of the expression tree to examine
+ * 'parent' is the PlanState node that owns the expression,
+ * or NULL if we are preparing an expression that is not associated
+ * with a plan. (If so, it can't have Aggrefs or SubPlans.)
+ *
+ * Soon this will generate an expression state tree paralleling the given
+ * expression tree. Right now, it just searches the expression tree for
+ * Aggref and SubPlan nodes.
+ */
+Node *
+ExecInitExpr(Node *node, PlanState *parent)
+{
+ List *temp;
+
+ if (node == NULL)
+ return NULL;
+ switch (nodeTag(node))
+ {
+ case T_Var:
+ break;
+ case T_Const:
+ break;
+ case T_Param:
+ break;
+ case T_Aggref:
+ if (parent && IsA(parent, AggState))
+ {
+ AggState *aggstate = (AggState *) parent;
+ int naggs;
+
+ aggstate->aggs = lcons(node, aggstate->aggs);
+ naggs = ++aggstate->numaggs;
+
+ ExecInitExpr(((Aggref *) node)->target, parent);
+
+ /*
+ * Complain if the aggregate's argument contains any
+ * aggregates; nested agg functions are semantically
+ * nonsensical. (This probably was caught earlier,
+ * but we defend against it here anyway.)
+ */
+ if (naggs != aggstate->numaggs)
+ elog(ERROR, "Aggregate function calls may not be nested");
+ }
+ else
+ elog(ERROR, "ExecInitExpr: Aggref not expected here");
+ break;
+ case T_ArrayRef:
+ {
+ ArrayRef *aref = (ArrayRef *) node;
+
+ ExecInitExpr((Node *) aref->refupperindexpr, parent);
+ ExecInitExpr((Node *) aref->reflowerindexpr, parent);
+ ExecInitExpr(aref->refexpr, parent);
+ ExecInitExpr(aref->refassgnexpr, parent);
+ }
+ break;
+ case T_Expr:
+ {
+ Expr *expr = (Expr *) node;
+
+ switch (expr->opType)
+ {
+ case OP_EXPR:
+ break;
+ case FUNC_EXPR:
+ break;
+ case OR_EXPR:
+ break;
+ case AND_EXPR:
+ break;
+ case NOT_EXPR:
+ break;
+ case DISTINCT_EXPR:
+ break;
+ case SUBPLAN_EXPR:
+ if (parent)
+ {
+ SubLink *sublink = ((SubPlan *) expr->oper)->sublink;
+
+ /*
+ * Here we just add the SubPlan nodes to
+ * parent->subPlan. Later they will be expanded
+ * to SubPlanState nodes.
+ */
+ parent->subPlan = lcons(expr->oper,
+ parent->subPlan);
+
+ /* Must recurse into oper list too */
+ Assert(IsA(sublink, SubLink));
+ if (sublink->lefthand)
+ elog(ERROR, "ExecInitExpr: sublink has not been transformed");
+ ExecInitExpr((Node *) sublink->oper, parent);
+ }
+ else
+ elog(ERROR, "ExecInitExpr: SubPlan not expected here");
+ break;
+ default:
+ elog(ERROR, "ExecInitExpr: unknown expression type %d",
+ expr->opType);
+ break;
+ }
+ /* for all Expr node types, examine args list */
+ ExecInitExpr((Node *) expr->args, parent);
+ }
+ break;
+ case T_FieldSelect:
+ ExecInitExpr(((FieldSelect *) node)->arg, parent);
+ break;
+ case T_RelabelType:
+ ExecInitExpr(((RelabelType *) node)->arg, parent);
+ break;
+ case T_CaseExpr:
+ {
+ CaseExpr *caseexpr = (CaseExpr *) node;
+
+ foreach(temp, caseexpr->args)
+ {
+ CaseWhen *when = (CaseWhen *) lfirst(temp);
+
+ Assert(IsA(when, CaseWhen));
+ ExecInitExpr(when->expr, parent);
+ ExecInitExpr(when->result, parent);
+ }
+ /* caseexpr->arg should be null, but we'll check it anyway */
+ ExecInitExpr(caseexpr->arg, parent);
+ ExecInitExpr(caseexpr->defresult, parent);
+ }
+ break;
+ case T_NullTest:
+ ExecInitExpr(((NullTest *) node)->arg, parent);
+ break;
+ case T_BooleanTest:
+ ExecInitExpr(((BooleanTest *) node)->arg, parent);
+ break;
+ case T_ConstraintTest:
+ ExecInitExpr(((ConstraintTest *) node)->arg, parent);
+ ExecInitExpr(((ConstraintTest *) node)->check_expr, parent);
+ break;
+ case T_ConstraintTestValue:
+ break;
+ case T_List:
+ foreach(temp, (List *) node)
+ {
+ ExecInitExpr((Node *) lfirst(temp), parent);
+ }
+ break;
+ case T_TargetEntry:
+ ExecInitExpr(((TargetEntry *) node)->expr, parent);
+ break;
+ default:
+ elog(ERROR, "ExecInitExpr: unknown expression type %d",
+ nodeTag(node));
+ break;
+ }
+
+ return node;
+}
+
+
/* ----------------------------------------------------------------
* ExecQual / ExecTargetList / ExecProject
* ----------------------------------------------------------------
diff --git a/src/backend/executor/execScan.c b/src/backend/executor/execScan.c
index 9fd7c4fb00c..6944e03e9bc 100644
--- a/src/backend/executor/execScan.c
+++ b/src/backend/executor/execScan.c
@@ -12,7 +12,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execScan.c,v 1.21 2002/09/02 02:47:02 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execScan.c,v 1.22 2002/12/05 15:50:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -44,10 +44,9 @@
* ----------------------------------------------------------------
*/
TupleTableSlot *
-ExecScan(Scan *node,
+ExecScan(ScanState *node,
ExecScanAccessMtd accessMtd) /* function returning a tuple */
{
- CommonScanState *scanstate;
EState *estate;
ExprContext *econtext;
List *qual;
@@ -57,23 +56,22 @@ ExecScan(Scan *node,
/*
* Fetch data from node
*/
- estate = node->plan.state;
- scanstate = node->scanstate;
- econtext = scanstate->cstate.cs_ExprContext;
- qual = node->plan.qual;
+ estate = node->ps.state;
+ econtext = node->ps.ps_ExprContext;
+ qual = node->ps.qual;
/*
* Check to see if we're still projecting out tuples from a previous
* scan tuple (because there is a function-returning-set in the
* projection expressions). If so, try to project another one.
*/
- if (scanstate->cstate.cs_TupFromTlist)
+ if (node->ps.ps_TupFromTlist)
{
- resultSlot = ExecProject(scanstate->cstate.cs_ProjInfo, &isDone);
+ resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
if (isDone == ExprMultipleResult)
return resultSlot;
/* Done with that source tuple... */
- scanstate->cstate.cs_TupFromTlist = false;
+ node->ps.ps_TupFromTlist = false;
}
/*
@@ -104,7 +102,7 @@ ExecScan(Scan *node,
if (TupIsNull(slot))
{
return ExecStoreTuple(NULL,
- scanstate->cstate.cs_ProjInfo->pi_slot,
+ node->ps.ps_ProjInfo->pi_slot,
InvalidBuffer,
true);
}
@@ -130,10 +128,10 @@ ExecScan(Scan *node,
* return it --- unless we find we can project no tuples from
* this scan tuple, in which case continue scan.
*/
- resultSlot = ExecProject(scanstate->cstate.cs_ProjInfo, &isDone);
+ resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
if (isDone != ExprEndResult)
{
- scanstate->cstate.cs_TupFromTlist = (isDone == ExprMultipleResult);
+ node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
return resultSlot;
}
}
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 7b0df664c74..f5a6863b1ac 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.60 2002/09/28 20:00:19 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.61 2002/12/05 15:50:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -483,11 +483,11 @@ ExecSetSlotDescriptorIsNew(TupleTableSlot *slot, /* slot to change */
* ----------------
*/
void
-ExecInitResultTupleSlot(EState *estate, CommonState *commonstate)
+ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
{
INIT_SLOT_DEFS;
INIT_SLOT_ALLOC;
- commonstate->cs_ResultTupleSlot = slot;
+ planstate->ps_ResultTupleSlot = slot;
}
/* ----------------
@@ -495,11 +495,11 @@ ExecInitResultTupleSlot(EState *estate, CommonState *commonstate)
* ----------------
*/
void
-ExecInitScanTupleSlot(EState *estate, CommonScanState *commonscanstate)
+ExecInitScanTupleSlot(EState *estate, ScanState *scanstate)
{
INIT_SLOT_DEFS;
INIT_SLOT_ALLOC;
- commonscanstate->css_ScanTupleSlot = slot;
+ scanstate->ss_ScanTupleSlot = slot;
}
/* ----------------
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 86440d10f9e..0dd17b7965b 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.90 2002/09/04 20:31:18 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.91 2002/12/05 15:50:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -142,7 +142,7 @@ DisplayTupleCount(FILE *statfp)
* ----------------
*/
void
-ExecAssignExprContext(EState *estate, CommonState *commonstate)
+ExecAssignExprContext(EState *estate, PlanState *planstate)
{
ExprContext *econtext = makeNode(ExprContext);
@@ -166,7 +166,7 @@ ExecAssignExprContext(EState *estate, CommonState *commonstate)
econtext->ecxt_aggnulls = NULL;
econtext->ecxt_callbacks = NULL;
- commonstate->cs_ExprContext = econtext;
+ planstate->ps_ExprContext = econtext;
}
/* ----------------
@@ -259,10 +259,10 @@ MakePerTupleExprContext(EState *estate)
* ----------------
*/
void
-ExecAssignResultType(CommonState *commonstate,
+ExecAssignResultType(PlanState *planstate,
TupleDesc tupDesc, bool shouldFree)
{
- TupleTableSlot *slot = commonstate->cs_ResultTupleSlot;
+ TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
ExecSetSlotDescriptor(slot, tupDesc, shouldFree);
}
@@ -272,15 +272,15 @@ ExecAssignResultType(CommonState *commonstate,
* ----------------
*/
void
-ExecAssignResultTypeFromOuterPlan(Plan *node, CommonState *commonstate)
+ExecAssignResultTypeFromOuterPlan(PlanState *planstate)
{
- Plan *outerPlan;
+ PlanState *outerPlan;
TupleDesc tupDesc;
- outerPlan = outerPlan(node);
+ outerPlan = outerPlanState(planstate);
tupDesc = ExecGetTupType(outerPlan);
- ExecAssignResultType(commonstate, tupDesc, false);
+ ExecAssignResultType(planstate, tupDesc, false);
}
/* ----------------
@@ -288,7 +288,7 @@ ExecAssignResultTypeFromOuterPlan(Plan *node, CommonState *commonstate)
* ----------------
*/
void
-ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate)
+ExecAssignResultTypeFromTL(PlanState *planstate)
{
ResultRelInfo *ri;
bool hasoid = false;
@@ -311,7 +311,7 @@ ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate)
* each of the child plans of the topmost Append plan. So, this is
* ugly but it works, for now ...
*/
- ri = node->state->es_result_relation_info;
+ ri = planstate->state->es_result_relation_info;
if (ri != NULL)
{
Relation rel = ri->ri_RelationDesc;
@@ -320,8 +320,13 @@ ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate)
hasoid = rel->rd_rel->relhasoids;
}
- tupDesc = ExecTypeFromTL(node->targetlist, hasoid);
- ExecAssignResultType(commonstate, tupDesc, true);
+ /*
+ * XXX Some plan nodes don't bother to set up planstate->targetlist,
+ * so use the underlying plan's targetlist instead. This will probably
+ * need to be fixed later.
+ */
+ tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid);
+ ExecAssignResultType(planstate, tupDesc, true);
}
/* ----------------
@@ -329,9 +334,9 @@ ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate)
* ----------------
*/
TupleDesc
-ExecGetResultType(CommonState *commonstate)
+ExecGetResultType(PlanState *planstate)
{
- TupleTableSlot *slot = commonstate->cs_ResultTupleSlot;
+ TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
return slot->ttc_tupleDescriptor;
}
@@ -342,23 +347,23 @@ ExecGetResultType(CommonState *commonstate)
* ----------------
*/
void
-ExecAssignProjectionInfo(Plan *node, CommonState *commonstate)
+ExecAssignProjectionInfo(PlanState *planstate)
{
ProjectionInfo *projInfo;
List *targetList;
int len;
- targetList = node->targetlist;
+ targetList = planstate->targetlist;
len = ExecTargetListLength(targetList);
projInfo = makeNode(ProjectionInfo);
projInfo->pi_targetlist = targetList;
projInfo->pi_len = len;
projInfo->pi_tupValue = (len <= 0) ? NULL : (Datum *) palloc(sizeof(Datum) * len);
- projInfo->pi_exprContext = commonstate->cs_ExprContext;
- projInfo->pi_slot = commonstate->cs_ResultTupleSlot;
+ projInfo->pi_exprContext = planstate->ps_ExprContext;
+ projInfo->pi_slot = planstate->ps_ResultTupleSlot;
- commonstate->cs_ProjInfo = projInfo;
+ planstate->ps_ProjInfo = projInfo;
}
@@ -367,7 +372,7 @@ ExecAssignProjectionInfo(Plan *node, CommonState *commonstate)
* ----------------
*/
void
-ExecFreeProjectionInfo(CommonState *commonstate)
+ExecFreeProjectionInfo(PlanState *planstate)
{
ProjectionInfo *projInfo;
@@ -375,7 +380,7 @@ ExecFreeProjectionInfo(CommonState *commonstate)
* get projection info. if NULL then this node has none so we just
* return.
*/
- projInfo = commonstate->cs_ProjInfo;
+ projInfo = planstate->ps_ProjInfo;
if (projInfo == NULL)
return;
@@ -386,7 +391,7 @@ ExecFreeProjectionInfo(CommonState *commonstate)
pfree(projInfo->pi_tupValue);
pfree(projInfo);
- commonstate->cs_ProjInfo = NULL;
+ planstate->ps_ProjInfo = NULL;
}
/* ----------------
@@ -394,7 +399,7 @@ ExecFreeProjectionInfo(CommonState *commonstate)
* ----------------
*/
void
-ExecFreeExprContext(CommonState *commonstate)
+ExecFreeExprContext(PlanState *planstate)
{
ExprContext *econtext;
@@ -402,7 +407,7 @@ ExecFreeExprContext(CommonState *commonstate)
* get expression context. if NULL then this node has none so we just
* return.
*/
- econtext = commonstate->cs_ExprContext;
+ econtext = planstate->ps_ExprContext;
if (econtext == NULL)
return;
@@ -416,7 +421,7 @@ ExecFreeExprContext(CommonState *commonstate)
*/
MemoryContextDelete(econtext->ecxt_per_tuple_memory);
pfree(econtext);
- commonstate->cs_ExprContext = NULL;
+ planstate->ps_ExprContext = NULL;
}
/* ----------------------------------------------------------------
@@ -434,9 +439,9 @@ ExecFreeExprContext(CommonState *commonstate)
* ----------------
*/
TupleDesc
-ExecGetScanType(CommonScanState *csstate)
+ExecGetScanType(ScanState *scanstate)
{
- TupleTableSlot *slot = csstate->css_ScanTupleSlot;
+ TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
return slot->ttc_tupleDescriptor;
}
@@ -446,10 +451,10 @@ ExecGetScanType(CommonScanState *csstate)
* ----------------
*/
void
-ExecAssignScanType(CommonScanState *csstate,
+ExecAssignScanType(ScanState *scanstate,
TupleDesc tupDesc, bool shouldFree)
{
- TupleTableSlot *slot = csstate->css_ScanTupleSlot;
+ TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
ExecSetSlotDescriptor(slot, tupDesc, shouldFree);
}
@@ -459,15 +464,15 @@ ExecAssignScanType(CommonScanState *csstate,
* ----------------
*/
void
-ExecAssignScanTypeFromOuterPlan(Plan *node, CommonScanState *csstate)
+ExecAssignScanTypeFromOuterPlan(ScanState *scanstate)
{
- Plan *outerPlan;
+ PlanState *outerPlan;
TupleDesc tupDesc;
- outerPlan = outerPlan(node);
+ outerPlan = outerPlanState(scanstate);
tupDesc = ExecGetTupType(outerPlan);
- ExecAssignScanType(csstate, tupDesc, false);
+ ExecAssignScanType(scanstate, tupDesc, false);
}
@@ -718,7 +723,7 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
}
void
-SetChangedParamList(Plan *node, List *newchg)
+SetChangedParamList(PlanState *node, List *newchg)
{
List *nl;
@@ -727,8 +732,8 @@ SetChangedParamList(Plan *node, List *newchg)
int paramId = lfirsti(nl);
/* if this node doesn't depend on a param ... */
- if (!intMember(paramId, node->extParam) &&
- !intMember(paramId, node->locParam))
+ if (!intMember(paramId, node->plan->extParam) &&
+ !intMember(paramId, node->plan->locParam))
continue;
/* if this param is already in list of changed ones ... */
if (intMember(paramId, node->chgParam))
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 71166d9096c..328aea5f079 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.60 2002/11/13 00:39:47 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.61 2002/12/05 15:50:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -28,7 +28,9 @@
/*
- * We have an execution_state record for each query in a function.
+ * We have an execution_state record for each query in a function. Each
+ * record contains a querytree and plantree for its query. If the query
+ * is currently in F_EXEC_RUN state then there's a QueryDesc too.
*/
typedef enum
{
@@ -37,10 +39,11 @@ typedef enum
typedef struct local_es
{
- QueryDesc *qd;
- EState *estate;
struct local_es *next;
ExecStatus status;
+ Query *query;
+ Plan *plan;
+ QueryDesc *qd; /* null unless status == RUN */
} execution_state;
#define LAST_POSTQUEL_COMMAND(es) ((es)->next == (execution_state *) NULL)
@@ -62,6 +65,8 @@ typedef struct
* we end execution of the function and
* free stuff */
+ ParamListInfo paramLI; /* Param list representing current args */
+
/* head of linked list of execution_state records */
execution_state *func_state;
} SQLFunctionCache;
@@ -73,10 +78,11 @@ typedef SQLFunctionCache *SQLFunctionCachePtr;
static execution_state *init_execution_state(char *src,
Oid *argOidVect, int nargs);
static void init_sql_fcache(FmgrInfo *finfo);
-static void postquel_start(execution_state *es);
+static void postquel_start(execution_state *es, SQLFunctionCachePtr fcache);
static TupleTableSlot *postquel_getnext(execution_state *es);
static void postquel_end(execution_state *es);
-static void postquel_sub_params(execution_state *es, FunctionCallInfo fcinfo);
+static void postquel_sub_params(SQLFunctionCachePtr fcache,
+ FunctionCallInfo fcinfo);
static Datum postquel_execute(execution_state *es,
FunctionCallInfo fcinfo,
SQLFunctionCachePtr fcache);
@@ -101,7 +107,6 @@ init_execution_state(char *src, Oid *argOidVect, int nargs)
Query *queryTree = lfirst(qtl_item);
Plan *planTree;
execution_state *newes;
- EState *estate;
planTree = pg_plan_query(queryTree);
@@ -113,29 +118,9 @@ init_execution_state(char *src, Oid *argOidVect, int nargs)
newes->next = NULL;
newes->status = F_EXEC_START;
- newes->qd = CreateQueryDesc(queryTree, planTree, None, NULL);
- newes->estate = estate = CreateExecutorState();
-
- if (nargs > 0)
- {
- int i;
- ParamListInfo paramLI;
-
- paramLI = (ParamListInfo) palloc0((nargs + 1) * sizeof(ParamListInfoData));
-
- estate->es_param_list_info = paramLI;
-
- for (i = 0; i < nargs; paramLI++, i++)
- {
- paramLI->kind = PARAM_NUM;
- paramLI->id = i + 1;
- paramLI->isnull = false;
- paramLI->value = (Datum) NULL;
- }
- paramLI->kind = PARAM_INVALID;
- }
- else
- estate->es_param_list_info = (ParamListInfo) NULL;
+ newes->query = queryTree;
+ newes->plan = planTree;
+ newes->qd = NULL;
preves = newes;
}
@@ -219,6 +204,10 @@ init_sql_fcache(FmgrInfo *finfo)
else
fcache->funcSlot = NULL;
+ /*
+ * Parse and plan the queries. We need the argument info to pass
+ * to the parser.
+ */
nargs = procedureStruct->pronargs;
if (nargs > 0)
@@ -252,15 +241,18 @@ init_sql_fcache(FmgrInfo *finfo)
static void
-postquel_start(execution_state *es)
+postquel_start(execution_state *es, SQLFunctionCachePtr fcache)
{
- /*
- * Do nothing for utility commands. (create, destroy...) DZ -
- * 30-8-1996
- */
- if (es->qd->operation == CMD_UTILITY)
- return;
- ExecutorStart(es->qd, es->estate);
+ Assert(es->qd == NULL);
+ es->qd = CreateQueryDesc(es->query, es->plan,
+ None, NULL,
+ fcache->paramLI, false);
+
+ /* Utility commands don't need Executor. */
+ if (es->qd->operation != CMD_UTILITY)
+ ExecutorStart(es->qd);
+
+ es->status = F_EXEC_RUN;
}
static TupleTableSlot *
@@ -282,40 +274,52 @@ postquel_getnext(execution_state *es)
/* If it's not the last command, just run it to completion */
count = (LAST_POSTQUEL_COMMAND(es)) ? 1L : 0L;
- return ExecutorRun(es->qd, es->estate, ForwardScanDirection, count);
+ return ExecutorRun(es->qd, ForwardScanDirection, count);
}
static void
postquel_end(execution_state *es)
{
- /*
- * Do nothing for utility commands. (create, destroy...) DZ -
- * 30-8-1996
- */
- if (es->qd->operation == CMD_UTILITY)
- return;
- ExecutorEnd(es->qd, es->estate);
+ /* Utility commands don't need Executor. */
+ if (es->qd->operation != CMD_UTILITY)
+ ExecutorEnd(es->qd);
+
+ pfree(es->qd);
+ es->qd = NULL;
+
+ es->status = F_EXEC_DONE;
}
+/* Build ParamListInfo array representing current arguments */
static void
-postquel_sub_params(execution_state *es, FunctionCallInfo fcinfo)
+postquel_sub_params(SQLFunctionCachePtr fcache,
+ FunctionCallInfo fcinfo)
{
- EState *estate;
ParamListInfo paramLI;
+ int nargs = fcinfo->nargs;
- estate = es->estate;
- paramLI = estate->es_param_list_info;
-
- while (paramLI->kind != PARAM_INVALID)
+ if (nargs > 0)
{
- if (paramLI->kind == PARAM_NUM)
+ int i;
+
+ paramLI = (ParamListInfo) palloc0((nargs + 1) * sizeof(ParamListInfoData));
+
+ for (i = 0; i < nargs; i++)
{
- Assert(paramLI->id <= fcinfo->nargs);
- paramLI->value = fcinfo->arg[paramLI->id - 1];
- paramLI->isnull = fcinfo->argnull[paramLI->id - 1];
+ paramLI[i].kind = PARAM_NUM;
+ paramLI[i].id = i + 1;
+ paramLI[i].value = fcinfo->arg[i];
+ paramLI[i].isnull = fcinfo->argnull[i];
}
- paramLI++;
+ paramLI[nargs].kind = PARAM_INVALID;
}
+ else
+ paramLI = (ParamListInfo) NULL;
+
+ if (fcache->paramLI)
+ pfree(fcache->paramLI);
+
+ fcache->paramLI = paramLI;
}
static TupleTableSlot *
@@ -359,27 +363,14 @@ postquel_execute(execution_state *es,
TupleTableSlot *slot;
Datum value;
- /*
- * It's more right place to do it (before
- * postquel_start->ExecutorStart). Now
- * ExecutorStart->ExecInitIndexScan->ExecEvalParam works ok. (But
- * note: I HOPE we can do it here). - vadim 01/22/97
- */
- if (fcinfo->nargs > 0)
- postquel_sub_params(es, fcinfo);
-
if (es->status == F_EXEC_START)
- {
- postquel_start(es);
- es->status = F_EXEC_RUN;
- }
+ postquel_start(es, fcache);
slot = postquel_getnext(es);
if (TupIsNull(slot))
{
postquel_end(es);
- es->status = F_EXEC_DONE;
fcinfo->isnull = true;
/*
@@ -438,10 +429,7 @@ postquel_execute(execution_state *es,
* execution now.
*/
if (!fcinfo->flinfo->fn_retset)
- {
postquel_end(es);
- es->status = F_EXEC_DONE;
- }
return value;
}
@@ -471,7 +459,7 @@ fmgr_sql(PG_FUNCTION_ARGS)
oldcontext = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
/*
- * Initialize fcache and execution state if first time through.
+ * Initialize fcache (build plans) if first time through.
*/
fcache = (SQLFunctionCachePtr) fcinfo->flinfo->fn_extra;
if (fcache == NULL)
@@ -482,6 +470,13 @@ fmgr_sql(PG_FUNCTION_ARGS)
es = fcache->func_state;
/*
+ * Convert params to appropriate format if starting a fresh execution.
+ * (If continuing execution, we can re-use prior params.)
+ */
+ if (es && es->status == F_EXEC_START)
+ postquel_sub_params(fcache, fcinfo);
+
+ /*
* Find first unfinished query in function.
*/
while (es && es->status == F_EXEC_DONE)
@@ -506,7 +501,7 @@ fmgr_sql(PG_FUNCTION_ARGS)
if (es == (execution_state *) NULL)
{
/*
- * Reset the execution states to start over again
+ * Reset the execution states to start over again on next call.
*/
es = fcache->func_state;
while (es)
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 82e9f48e1e0..bdbe61cb10a 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -45,7 +45,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.97 2002/11/29 21:39:11 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.98 2002/12/05 15:50:32 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -212,11 +212,12 @@ static void finalize_aggregate(AggState *aggstate,
AggStatePerAgg peraggstate,
AggStatePerGroup pergroupstate,
Datum *resultVal, bool *resultIsNull);
-static void build_hash_table(Agg *node);
-static AggHashEntry lookup_hash_entry(Agg *node, TupleTableSlot *slot);
-static TupleTableSlot *agg_retrieve_direct(Agg *node);
-static void agg_fill_hash_table(Agg *node);
-static TupleTableSlot *agg_retrieve_hash_table(Agg *node);
+static void build_hash_table(AggState *aggstate);
+static AggHashEntry lookup_hash_entry(AggState *aggstate,
+ TupleTableSlot *slot);
+static TupleTableSlot *agg_retrieve_direct(AggState *aggstate);
+static void agg_fill_hash_table(AggState *aggstate);
+static TupleTableSlot *agg_retrieve_hash_table(AggState *aggstate);
static Datum GetAggInitVal(Datum textInitVal, Oid transtype);
@@ -521,7 +522,7 @@ finalize_aggregate(AggState *aggstate,
{
MemoryContext oldContext;
- oldContext = MemoryContextSwitchTo(aggstate->csstate.cstate.cs_ExprContext->ecxt_per_tuple_memory);
+ oldContext = MemoryContextSwitchTo(aggstate->ss.ps.ps_ExprContext->ecxt_per_tuple_memory);
/*
* Apply the agg's finalfn if one is provided, else return transValue.
@@ -572,9 +573,9 @@ finalize_aggregate(AggState *aggstate,
* The hash table always lives in the aggcontext memory context.
*/
static void
-build_hash_table(Agg *node)
+build_hash_table(AggState *aggstate)
{
- AggState *aggstate = node->aggstate;
+ Agg *node = (Agg *) aggstate->ss.ps.plan;
AggHashTable hashtable;
Size tabsize;
@@ -596,9 +597,9 @@ build_hash_table(Agg *node)
* When called, CurrentMemoryContext should be the per-query context.
*/
static AggHashEntry
-lookup_hash_entry(Agg *node, TupleTableSlot *slot)
+lookup_hash_entry(AggState *aggstate, TupleTableSlot *slot)
{
- AggState *aggstate = node->aggstate;
+ Agg *node = (Agg *) aggstate->ss.ps.plan;
AggHashTable hashtable = aggstate->hashtable;
MemoryContext tmpmem = aggstate->tmpcontext->ecxt_per_tuple_memory;
HeapTuple tuple = slot->val;
@@ -684,16 +685,14 @@ lookup_hash_entry(Agg *node, TupleTableSlot *slot)
* the result tuple.
*/
TupleTableSlot *
-ExecAgg(Agg *node)
+ExecAgg(AggState *node)
{
- AggState *aggstate = node->aggstate;
-
- if (aggstate->agg_done)
+ if (node->agg_done)
return NULL;
- if (node->aggstrategy == AGG_HASHED)
+ if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
{
- if (!aggstate->table_filled)
+ if (!node->table_filled)
agg_fill_hash_table(node);
return agg_retrieve_hash_table(node);
}
@@ -707,10 +706,10 @@ ExecAgg(Agg *node)
* ExecAgg for non-hashed case
*/
static TupleTableSlot *
-agg_retrieve_direct(Agg *node)
+agg_retrieve_direct(AggState *aggstate)
{
- AggState *aggstate;
- Plan *outerPlan;
+ Agg *node = (Agg *) aggstate->ss.ps.plan;
+ PlanState *outerPlan;
ExprContext *econtext;
ExprContext *tmpcontext;
ProjectionInfo *projInfo;
@@ -726,22 +725,21 @@ agg_retrieve_direct(Agg *node)
/*
* get state info from node
*/
- aggstate = node->aggstate;
- outerPlan = outerPlan(node);
+ outerPlan = outerPlanState(aggstate);
/* econtext is the per-output-tuple expression context */
- econtext = aggstate->csstate.cstate.cs_ExprContext;
+ econtext = aggstate->ss.ps.ps_ExprContext;
aggvalues = econtext->ecxt_aggvalues;
aggnulls = econtext->ecxt_aggnulls;
/* tmpcontext is the per-input-tuple expression context */
tmpcontext = aggstate->tmpcontext;
- projInfo = aggstate->csstate.cstate.cs_ProjInfo;
+ projInfo = aggstate->ss.ps.ps_ProjInfo;
peragg = aggstate->peragg;
pergroup = aggstate->pergroup;
- firstSlot = aggstate->csstate.css_ScanTupleSlot;
+ firstSlot = aggstate->ss.ss_ScanTupleSlot;
/*
* We loop retrieving groups until we find one matching
- * node->plan.qual
+ * aggstate->ss.ps.qual
*/
do
{
@@ -754,7 +752,7 @@ agg_retrieve_direct(Agg *node)
*/
if (aggstate->grp_firstTuple == NULL)
{
- outerslot = ExecProcNode(outerPlan, (Plan *) node);
+ outerslot = ExecProcNode(outerPlan);
if (!TupIsNull(outerslot))
{
/*
@@ -810,7 +808,7 @@ agg_retrieve_direct(Agg *node)
/* Reset per-input-tuple context after each tuple */
ResetExprContext(tmpcontext);
- outerslot = ExecProcNode(outerPlan, (Plan *) node);
+ outerslot = ExecProcNode(outerPlan);
if (TupIsNull(outerslot))
{
/* no more outer-plan tuples available */
@@ -917,7 +915,7 @@ agg_retrieve_direct(Agg *node)
* Otherwise, return the tuple.
*/
}
- while (!ExecQual(node->plan.qual, econtext, false));
+ while (!ExecQual(aggstate->ss.ps.qual, econtext, false));
return resultSlot;
}
@@ -926,10 +924,9 @@ agg_retrieve_direct(Agg *node)
* ExecAgg for hashed case: phase 1, read input and build hash table
*/
static void
-agg_fill_hash_table(Agg *node)
+agg_fill_hash_table(AggState *aggstate)
{
- AggState *aggstate;
- Plan *outerPlan;
+ PlanState *outerPlan;
ExprContext *tmpcontext;
AggHashEntry entry;
TupleTableSlot *outerslot;
@@ -937,8 +934,7 @@ agg_fill_hash_table(Agg *node)
/*
* get state info from node
*/
- aggstate = node->aggstate;
- outerPlan = outerPlan(node);
+ outerPlan = outerPlanState(aggstate);
/* tmpcontext is the per-input-tuple expression context */
tmpcontext = aggstate->tmpcontext;
@@ -948,14 +944,14 @@ agg_fill_hash_table(Agg *node)
*/
for (;;)
{
- outerslot = ExecProcNode(outerPlan, (Plan *) node);
+ outerslot = ExecProcNode(outerPlan);
if (TupIsNull(outerslot))
break;
/* set up for advance_aggregates call */
tmpcontext->ecxt_scantuple = outerslot;
/* Find or build hashtable entry for this tuple's group */
- entry = lookup_hash_entry(node, outerslot);
+ entry = lookup_hash_entry(aggstate, outerslot);
/* Advance the aggregates */
advance_aggregates(aggstate, entry->pergroup);
@@ -974,9 +970,8 @@ agg_fill_hash_table(Agg *node)
* ExecAgg for hashed case: phase 2, retrieving groups from hash table
*/
static TupleTableSlot *
-agg_retrieve_hash_table(Agg *node)
+agg_retrieve_hash_table(AggState *aggstate)
{
- AggState *aggstate;
ExprContext *econtext;
ProjectionInfo *projInfo;
Datum *aggvalues;
@@ -992,19 +987,18 @@ agg_retrieve_hash_table(Agg *node)
/*
* get state info from node
*/
- aggstate = node->aggstate;
/* econtext is the per-output-tuple expression context */
- econtext = aggstate->csstate.cstate.cs_ExprContext;
+ econtext = aggstate->ss.ps.ps_ExprContext;
aggvalues = econtext->ecxt_aggvalues;
aggnulls = econtext->ecxt_aggnulls;
- projInfo = aggstate->csstate.cstate.cs_ProjInfo;
+ projInfo = aggstate->ss.ps.ps_ProjInfo;
peragg = aggstate->peragg;
hashtable = aggstate->hashtable;
- firstSlot = aggstate->csstate.css_ScanTupleSlot;
+ firstSlot = aggstate->ss.ss_ScanTupleSlot;
/*
- * We loop retrieving groups until we find one matching
- * node->plan.qual
+ * We loop retrieving groups until we find one satisfying
+ * aggstate->ss.ps.qual
*/
do
{
@@ -1071,7 +1065,7 @@ agg_retrieve_hash_table(Agg *node)
* Otherwise, return the tuple.
*/
}
- while (!ExecQual(node->plan.qual, econtext, false));
+ while (!ExecQual(aggstate->ss.ps.qual, econtext, false));
return resultSlot;
}
@@ -1083,8 +1077,8 @@ agg_retrieve_hash_table(Agg *node)
* planner and initializes its outer subtree
* -----------------
*/
-bool
-ExecInitAgg(Agg *node, EState *estate, Plan *parent)
+AggState *
+ExecInitAgg(Agg *node, EState *estate)
{
AggState *aggstate;
AggStatePerAgg peragg;
@@ -1095,15 +1089,14 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
List *alist;
/*
- * assign the node's execution state
- */
- node->plan.state = estate;
-
- /*
* create state structure
*/
aggstate = makeNode(AggState);
- node->aggstate = aggstate;
+ aggstate->ss.ps.plan = (Plan *) node;
+ aggstate->ss.ps.state = estate;
+
+ aggstate->aggs = NIL;
+ aggstate->numaggs = 0;
aggstate->eqfunctions = NULL;
aggstate->peragg = NULL;
aggstate->agg_done = false;
@@ -1112,37 +1105,13 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
aggstate->hashtable = NULL;
/*
- * find aggregates in targetlist and quals
- *
- * Note: pull_agg_clauses also checks that no aggs contain other agg
- * calls in their arguments. This would make no sense under SQL
- * semantics anyway (and it's forbidden by the spec). Because that is
- * true, we don't need to worry about evaluating the aggs in any
- * particular order.
- */
- aggstate->aggs = nconc(pull_agg_clause((Node *) node->plan.targetlist),
- pull_agg_clause((Node *) node->plan.qual));
- aggstate->numaggs = numaggs = length(aggstate->aggs);
- if (numaggs <= 0)
- {
- /*
- * This is not an error condition: we might be using the Agg node just
- * to do hash-based grouping. Even in the regular case,
- * constant-expression simplification could optimize away all of the
- * Aggrefs in the targetlist and qual. So keep going, but force local
- * copy of numaggs positive so that palloc()s below don't choke.
- */
- numaggs = 1;
- }
-
- /*
* Create expression contexts. We need two, one for per-input-tuple
* processing and one for per-output-tuple processing. We cheat a little
* by using ExecAssignExprContext() to build both.
*/
- ExecAssignExprContext(estate, &aggstate->csstate.cstate);
- aggstate->tmpcontext = aggstate->csstate.cstate.cs_ExprContext;
- ExecAssignExprContext(estate, &aggstate->csstate.cstate);
+ ExecAssignExprContext(estate, &aggstate->ss.ps);
+ aggstate->tmpcontext = aggstate->ss.ps.ps_ExprContext;
+ ExecAssignExprContext(estate, &aggstate->ss.ps);
/*
* We also need a long-lived memory context for holding hashtable
@@ -1163,14 +1132,64 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
/*
* tuple table initialization
*/
- ExecInitScanTupleSlot(estate, &aggstate->csstate);
- ExecInitResultTupleSlot(estate, &aggstate->csstate.cstate);
+ ExecInitScanTupleSlot(estate, &aggstate->ss);
+ ExecInitResultTupleSlot(estate, &aggstate->ss.ps);
+
+ /*
+ * initialize child expressions
+ *
+ * Note: ExecInitExpr finds Aggrefs for us, and also checks that no aggs
+ * contain other agg calls in their arguments. This would make no sense
+ * under SQL semantics anyway (and it's forbidden by the spec). Because
+ * that is true, we don't need to worry about evaluating the aggs in any
+ * particular order.
+ */
+ aggstate->ss.ps.targetlist = (List *)
+ ExecInitExpr((Node *) node->plan.targetlist,
+ (PlanState *) aggstate);
+ aggstate->ss.ps.qual = (List *)
+ ExecInitExpr((Node *) node->plan.qual,
+ (PlanState *) aggstate);
+
+ /*
+ * initialize child nodes
+ */
+ outerPlan = outerPlan(node);
+ outerPlanState(aggstate) = ExecInitNode(outerPlan, estate);
+
+ /*
+ * initialize source tuple type.
+ */
+ ExecAssignScanTypeFromOuterPlan(&aggstate->ss);
+
+ /*
+ * Initialize result tuple type and projection info.
+ */
+ ExecAssignResultTypeFromTL(&aggstate->ss.ps);
+ ExecAssignProjectionInfo(&aggstate->ss.ps);
+
+ /*
+ * get the count of aggregates in targetlist and quals
+ */
+ numaggs = aggstate->numaggs;
+ Assert(numaggs == length(aggstate->aggs));
+ if (numaggs <= 0)
+ {
+ /*
+ * This is not an error condition: we might be using the Agg node just
+ * to do hash-based grouping. Even in the regular case,
+ * constant-expression simplification could optimize away all of the
+ * Aggrefs in the targetlist and qual. So keep going, but force local
+ * copy of numaggs positive so that palloc()s below don't choke.
+ */
+ numaggs = 1;
+ }
/*
* Set up aggregate-result storage in the output expr context, and also
* allocate my private per-agg working storage
*/
- econtext = aggstate->csstate.cstate.cs_ExprContext;
+ econtext = aggstate->ss.ps.ps_ExprContext;
econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs);
econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs);
@@ -1179,7 +1198,7 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
if (node->aggstrategy == AGG_HASHED)
{
- build_hash_table(node);
+ build_hash_table(aggstate);
aggstate->table_filled = false;
}
else
@@ -1191,29 +1210,12 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
}
/*
- * initialize child nodes
- */
- outerPlan = outerPlan(node);
- ExecInitNode(outerPlan, estate, (Plan *) node);
-
- /*
- * initialize source tuple type.
- */
- ExecAssignScanTypeFromOuterPlan((Plan *) node, &aggstate->csstate);
-
- /*
- * Initialize result tuple type and projection info.
- */
- ExecAssignResultTypeFromTL((Plan *) node, &aggstate->csstate.cstate);
- ExecAssignProjectionInfo((Plan *) node, &aggstate->csstate.cstate);
-
- /*
* If we are grouping, precompute fmgr lookup data for inner loop
*/
if (node->numCols > 0)
{
aggstate->eqfunctions =
- execTuplesMatchPrepare(ExecGetScanType(&aggstate->csstate),
+ execTuplesMatchPrepare(ExecGetScanType(&aggstate->ss),
node->numCols,
node->grpColIdx);
}
@@ -1330,7 +1332,7 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
ReleaseSysCache(aggTuple);
}
- return TRUE;
+ return aggstate;
}
static Datum
@@ -1372,84 +1374,82 @@ ExecCountSlotsAgg(Agg *node)
}
void
-ExecEndAgg(Agg *node)
+ExecEndAgg(AggState *node)
{
- AggState *aggstate = node->aggstate;
- Plan *outerPlan;
+ PlanState *outerPlan;
int aggno;
/* Make sure we have closed any open tuplesorts */
- for (aggno = 0; aggno < aggstate->numaggs; aggno++)
+ for (aggno = 0; aggno < node->numaggs; aggno++)
{
- AggStatePerAgg peraggstate = &aggstate->peragg[aggno];
+ AggStatePerAgg peraggstate = &node->peragg[aggno];
if (peraggstate->sortstate)
tuplesort_end(peraggstate->sortstate);
}
- ExecFreeProjectionInfo(&aggstate->csstate.cstate);
+ ExecFreeProjectionInfo(&node->ss.ps);
/*
* Free both the expr contexts.
*/
- ExecFreeExprContext(&aggstate->csstate.cstate);
- aggstate->csstate.cstate.cs_ExprContext = aggstate->tmpcontext;
- ExecFreeExprContext(&aggstate->csstate.cstate);
+ ExecFreeExprContext(&node->ss.ps);
+ node->ss.ps.ps_ExprContext = node->tmpcontext;
+ ExecFreeExprContext(&node->ss.ps);
- MemoryContextDelete(aggstate->aggcontext);
+ MemoryContextDelete(node->aggcontext);
- outerPlan = outerPlan(node);
- ExecEndNode(outerPlan, (Plan *) node);
+ outerPlan = outerPlanState(node);
+ ExecEndNode(outerPlan);
/* clean up tuple table */
- ExecClearTuple(aggstate->csstate.css_ScanTupleSlot);
- if (aggstate->grp_firstTuple != NULL)
+ ExecClearTuple(node->ss.ss_ScanTupleSlot);
+ if (node->grp_firstTuple != NULL)
{
- heap_freetuple(aggstate->grp_firstTuple);
- aggstate->grp_firstTuple = NULL;
+ heap_freetuple(node->grp_firstTuple);
+ node->grp_firstTuple = NULL;
}
}
void
-ExecReScanAgg(Agg *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanAgg(AggState *node, ExprContext *exprCtxt)
{
- AggState *aggstate = node->aggstate;
- ExprContext *econtext = aggstate->csstate.cstate.cs_ExprContext;
+ ExprContext *econtext = node->ss.ps.ps_ExprContext;
int aggno;
/* Make sure we have closed any open tuplesorts */
- for (aggno = 0; aggno < aggstate->numaggs; aggno++)
+ for (aggno = 0; aggno < node->numaggs; aggno++)
{
- AggStatePerAgg peraggstate = &aggstate->peragg[aggno];
+ AggStatePerAgg peraggstate = &node->peragg[aggno];
if (peraggstate->sortstate)
tuplesort_end(peraggstate->sortstate);
peraggstate->sortstate = NULL;
}
- aggstate->agg_done = false;
- if (aggstate->grp_firstTuple != NULL)
+ node->agg_done = false;
+ if (node->grp_firstTuple != NULL)
{
- heap_freetuple(aggstate->grp_firstTuple);
- aggstate->grp_firstTuple = NULL;
+ heap_freetuple(node->grp_firstTuple);
+ node->grp_firstTuple = NULL;
}
- MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * aggstate->numaggs);
- MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * aggstate->numaggs);
+ MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numaggs);
+ MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numaggs);
- MemoryContextReset(aggstate->aggcontext);
+ MemoryContextReset(node->aggcontext);
- if (node->aggstrategy == AGG_HASHED)
+ if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
{
build_hash_table(node);
- aggstate->table_filled = false;
+ node->table_filled = false;
}
/*
* 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);
+ if (((PlanState *) node)->lefttree->chgParam == NIL)
+ ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
}
/*
diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c
index 9d0e5642229..bcb50fb7979 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.50 2002/11/13 00:39:47 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.51 2002/12/05 15:50:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -62,30 +62,27 @@
#include "executor/nodeAppend.h"
#include "parser/parsetree.h"
-static bool exec_append_initialize_next(Append *node);
+static bool exec_append_initialize_next(AppendState *appendstate);
/* ----------------------------------------------------------------
* exec_append_initialize_next
*
- * Sets up the append node state (i.e. the append state node)
- * for the "next" scan.
+ * Sets up the append state node for the "next" scan.
*
* Returns t iff there is a "next" scan to process.
* ----------------------------------------------------------------
*/
static bool
-exec_append_initialize_next(Append *node)
+exec_append_initialize_next(AppendState *appendstate)
{
EState *estate;
- AppendState *appendstate;
int whichplan;
/*
* get information from the append node
*/
- estate = node->plan.state;
- appendstate = node->appendstate;
+ estate = appendstate->ps.state;
whichplan = appendstate->as_whichplan;
if (whichplan < appendstate->as_firstplan)
@@ -116,7 +113,7 @@ exec_append_initialize_next(Append *node)
* If we are controlling the target relation, select the proper
* active ResultRelInfo and junk filter for this target.
*/
- if (node->isTarget)
+ if (((Append *) appendstate->ps.plan)->isTarget)
{
Assert(whichplan < estate->es_num_result_relations);
estate->es_result_relation_info =
@@ -132,9 +129,7 @@ exec_append_initialize_next(Append *node)
/* ----------------------------------------------------------------
* ExecInitAppend
*
- * Begins all of the subscans of the append node, storing the
- * scan structures in the 'initialized' vector of the append-state
- * structure.
+ * Begin all of the subscans of the append node.
*
* (This is potentially wasteful, since the entire result of the
* append node may not be scanned, but this way all of the
@@ -146,36 +141,31 @@ exec_append_initialize_next(Append *node)
* subplan that corresponds to the target relation being checked.
* ----------------------------------------------------------------
*/
-bool
-ExecInitAppend(Append *node, EState *estate, Plan *parent)
+AppendState *
+ExecInitAppend(Append *node, EState *estate)
{
- AppendState *appendstate;
+ AppendState *appendstate = makeNode(AppendState);
+ PlanState **appendplanstates;
int nplans;
- List *appendplans;
- bool *initialized;
int i;
Plan *initNode;
CXT1_printf("ExecInitAppend: context is %d\n", CurrentMemoryContext);
/*
- * assign execution state to node and get information for append state
+ * Set up empty vector of subplan states
*/
- node->plan.state = estate;
+ nplans = length(node->appendplans);
- appendplans = node->appendplans;
- nplans = length(appendplans);
-
- initialized = (bool *) palloc0(nplans * sizeof(bool));
+ appendplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
/*
* create new AppendState for our append node
*/
- appendstate = makeNode(AppendState);
+ appendstate->ps.plan = (Plan *) node;
+ appendstate->ps.state = estate;
+ appendstate->appendplans = appendplanstates;
appendstate->as_nplans = nplans;
- appendstate->as_initialized = initialized;
-
- node->appendstate = appendstate;
/*
* Do we want to scan just one subplan? (Special case for
@@ -212,36 +202,36 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
* append nodes still have Result slots, which hold pointers to
* tuples, so we have to initialize them.
*/
- ExecInitResultTupleSlot(estate, &appendstate->cstate);
+ ExecInitResultTupleSlot(estate, &appendstate->ps);
/*
* call ExecInitNode on each of the plans to be executed and save the
- * results into the array "initialized". Note we *must* set
+ * results into the array "appendplans". Note we *must* set
* estate->es_result_relation_info correctly while we initialize each
* sub-plan; ExecAssignResultTypeFromTL depends on that!
*/
for (i = appendstate->as_firstplan; i <= appendstate->as_lastplan; i++)
{
appendstate->as_whichplan = i;
- exec_append_initialize_next(node);
+ exec_append_initialize_next(appendstate);
- initNode = (Plan *) nth(i, appendplans);
- initialized[i] = ExecInitNode(initNode, estate, (Plan *) node);
+ initNode = (Plan *) nth(i, node->appendplans);
+ appendplanstates[i] = ExecInitNode(initNode, estate);
}
/*
* initialize tuple type
*/
- ExecAssignResultTypeFromTL((Plan *) node, &appendstate->cstate);
- appendstate->cstate.cs_ProjInfo = NULL;
+ ExecAssignResultTypeFromTL(&appendstate->ps);
+ appendstate->ps.ps_ProjInfo = NULL;
/*
* return the result from the first subplan's initialization
*/
appendstate->as_whichplan = appendstate->as_firstplan;
- exec_append_initialize_next(node);
+ exec_append_initialize_next(appendstate);
- return TRUE;
+ return appendstate;
}
int
@@ -264,13 +254,11 @@ ExecCountSlotsAppend(Append *node)
* ----------------------------------------------------------------
*/
TupleTableSlot *
-ExecProcAppend(Append *node)
+ExecProcAppend(AppendState *node)
{
EState *estate;
- AppendState *appendstate;
int whichplan;
- List *appendplans;
- Plan *subnode;
+ PlanState *subnode;
TupleTableSlot *result;
TupleTableSlot *result_slot;
ScanDirection direction;
@@ -278,25 +266,20 @@ ExecProcAppend(Append *node)
/*
* get information from the node
*/
- appendstate = node->appendstate;
- estate = node->plan.state;
+ estate = node->ps.state;
direction = estate->es_direction;
- appendplans = node->appendplans;
- whichplan = appendstate->as_whichplan;
- result_slot = appendstate->cstate.cs_ResultTupleSlot;
+ whichplan = node->as_whichplan;
+ result_slot = node->ps.ps_ResultTupleSlot;
/*
* figure out which subplan we are currently processing
*/
- subnode = (Plan *) nth(whichplan, appendplans);
-
- if (subnode == NULL)
- elog(DEBUG1, "ExecProcAppend: subnode is NULL");
+ subnode = node->appendplans[whichplan];
/*
* get a tuple from the subplan
*/
- result = ExecProcNode(subnode, (Plan *) node);
+ result = ExecProcNode(subnode);
if (!TupIsNull(result))
{
@@ -316,9 +299,9 @@ ExecProcAppend(Append *node)
* try processing again (recursively)
*/
if (ScanDirectionIsForward(direction))
- appendstate->as_whichplan++;
+ node->as_whichplan++;
else
- appendstate->as_whichplan--;
+ node->as_whichplan--;
/*
* return something from next node or an empty slot if all of our
@@ -343,65 +326,56 @@ ExecProcAppend(Append *node)
* ----------------------------------------------------------------
*/
void
-ExecEndAppend(Append *node)
+ExecEndAppend(AppendState *node)
{
- EState *estate;
- AppendState *appendstate;
+ PlanState **appendplans;
int nplans;
- List *appendplans;
- bool *initialized;
int i;
/*
* get information from the node
*/
- appendstate = node->appendstate;
- estate = node->plan.state;
appendplans = node->appendplans;
- nplans = appendstate->as_nplans;
- initialized = appendstate->as_initialized;
+ nplans = node->as_nplans;
/*
- * shut down each of the subscans
+ * shut down each of the subscans (that we've initialized)
*/
for (i = 0; i < nplans; i++)
{
- if (initialized[i])
- ExecEndNode((Plan *) nth(i, appendplans), (Plan *) node);
+ if (appendplans[i])
+ ExecEndNode(appendplans[i]);
}
}
void
-ExecReScanAppend(Append *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanAppend(AppendState *node, ExprContext *exprCtxt)
{
- AppendState *appendstate = node->appendstate;
int i;
- for (i = appendstate->as_firstplan; i <= appendstate->as_lastplan; i++)
+ for (i = node->as_firstplan; i <= node->as_lastplan; i++)
{
- Plan *subnode;
-
- subnode = (Plan *) nth(i, node->appendplans);
+ PlanState *subnode = node->appendplans[i];
/*
* ExecReScan doesn't know about my subplans, so I have to do
* changed-parameter signaling myself.
*/
- if (node->plan.chgParam != NULL)
- SetChangedParamList(subnode, node->plan.chgParam);
+ if (node->ps.chgParam != NIL)
+ SetChangedParamList(subnode, node->ps.chgParam);
/*
* if chgParam of subnode is not null then plan will be re-scanned
* by first ExecProcNode.
*/
- if (subnode->chgParam == NULL)
+ if (subnode->chgParam == NIL)
{
/* make sure estate is correct for this subnode (needed??) */
- appendstate->as_whichplan = i;
+ node->as_whichplan = i;
exec_append_initialize_next(node);
- ExecReScan(subnode, exprCtxt, (Plan *) node);
+ ExecReScan(subnode, exprCtxt);
}
}
- appendstate->as_whichplan = appendstate->as_firstplan;
+ node->as_whichplan = node->as_firstplan;
exec_append_initialize_next(node);
}
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index 97da70b2b78..f6df416d0f9 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.13 2002/12/01 20:27:32 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.14 2002/12/05 15:50:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -34,7 +34,7 @@
#include "utils/lsyscache.h"
-static TupleTableSlot *FunctionNext(FunctionScan *node);
+static TupleTableSlot *FunctionNext(FunctionScanState *node);
static bool tupledesc_mismatch(TupleDesc tupdesc1, TupleDesc tupdesc2);
/* ----------------------------------------------------------------
@@ -48,24 +48,22 @@ static bool tupledesc_mismatch(TupleDesc tupdesc1, TupleDesc tupdesc2);
* ----------------------------------------------------------------
*/
static TupleTableSlot *
-FunctionNext(FunctionScan *node)
+FunctionNext(FunctionScanState *node)
{
TupleTableSlot *slot;
EState *estate;
ScanDirection direction;
Tuplestorestate *tuplestorestate;
- FunctionScanState *scanstate;
bool should_free;
HeapTuple heapTuple;
/*
* get information from the estate and scan state
*/
- scanstate = (FunctionScanState *) node->scan.scanstate;
- estate = node->scan.plan.state;
+ estate = node->ss.ps.state;
direction = estate->es_direction;
- tuplestorestate = scanstate->tuplestorestate;
+ tuplestorestate = node->tuplestorestate;
/*
* If first time through, read all tuples from function and put them
@@ -74,13 +72,13 @@ FunctionNext(FunctionScan *node)
*/
if (tuplestorestate == NULL)
{
- ExprContext *econtext = scanstate->csstate.cstate.cs_ExprContext;
+ ExprContext *econtext = node->ss.ps.ps_ExprContext;
TupleDesc funcTupdesc;
- scanstate->tuplestorestate = tuplestorestate =
- ExecMakeTableFunctionResult(scanstate->funcexpr,
+ node->tuplestorestate = tuplestorestate =
+ ExecMakeTableFunctionResult(node->funcexpr,
econtext,
- scanstate->tupdesc,
+ node->tupdesc,
&funcTupdesc);
/*
@@ -89,14 +87,14 @@ FunctionNext(FunctionScan *node)
* well do it always.
*/
if (funcTupdesc &&
- tupledesc_mismatch(scanstate->tupdesc, funcTupdesc))
+ tupledesc_mismatch(node->tupdesc, funcTupdesc))
elog(ERROR, "Query-specified return tuple and actual function return tuple do not match");
}
/*
* Get the next tuple from tuplestore. Return NULL if no more tuples.
*/
- slot = scanstate->csstate.css_ScanTupleSlot;
+ slot = node->ss.ss_ScanTupleSlot;
if (tuplestorestate)
heapTuple = tuplestore_getheaptuple(tuplestorestate,
ScanDirectionIsForward(direction),
@@ -121,20 +119,20 @@ FunctionNext(FunctionScan *node)
*/
TupleTableSlot *
-ExecFunctionScan(FunctionScan *node)
+ExecFunctionScan(FunctionScanState *node)
{
/*
* use FunctionNext as access method
*/
- return ExecScan(&node->scan, (ExecScanAccessMtd) FunctionNext);
+ return ExecScan(&node->ss, (ExecScanAccessMtd) FunctionNext);
}
/* ----------------------------------------------------------------
* ExecInitFunctionScan
* ----------------------------------------------------------------
*/
-bool
-ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent)
+FunctionScanState *
+ExecInitFunctionScan(FunctionScan *node, EState *estate)
{
FunctionScanState *scanstate;
RangeTblEntry *rte;
@@ -145,34 +143,40 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent)
/*
* FunctionScan should not have any children.
*/
- Assert(outerPlan((Plan *) node) == NULL);
- Assert(innerPlan((Plan *) node) == NULL);
-
- /*
- * assign the node's execution state
- */
- node->scan.plan.state = estate;
+ Assert(outerPlan(node) == NULL);
+ Assert(innerPlan(node) == NULL);
/*
* create new ScanState for node
*/
scanstate = makeNode(FunctionScanState);
- node->scan.scanstate = &scanstate->csstate;
+ scanstate->ss.ps.plan = (Plan *) node;
+ scanstate->ss.ps.state = estate;
/*
* Miscellaneous initialization
*
* create expression context for node
*/
- ExecAssignExprContext(estate, &scanstate->csstate.cstate);
+ ExecAssignExprContext(estate, &scanstate->ss.ps);
#define FUNCTIONSCAN_NSLOTS 2
/*
* tuple table initialization
*/
- ExecInitResultTupleSlot(estate, &scanstate->csstate.cstate);
- ExecInitScanTupleSlot(estate, &scanstate->csstate);
+ ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
+ ExecInitScanTupleSlot(estate, &scanstate->ss);
+
+ /*
+ * initialize child expressions
+ */
+ scanstate->ss.ps.targetlist = (List *)
+ ExecInitExpr((Node *) node->scan.plan.targetlist,
+ (PlanState *) scanstate);
+ scanstate->ss.ps.qual = (List *)
+ ExecInitExpr((Node *) node->scan.plan.qual,
+ (PlanState *) scanstate);
/*
* get info about function
@@ -230,7 +234,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent)
elog(ERROR, "Unknown kind of return type specified for function");
scanstate->tupdesc = tupdesc;
- ExecSetSlotDescriptor(scanstate->csstate.css_ScanTupleSlot,
+ ExecSetSlotDescriptor(scanstate->ss.ss_ScanTupleSlot,
tupdesc, false);
/*
@@ -239,15 +243,15 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent)
scanstate->tuplestorestate = NULL;
scanstate->funcexpr = rte->funcexpr;
- scanstate->csstate.cstate.cs_TupFromTlist = false;
+ scanstate->ss.ps.ps_TupFromTlist = false;
/*
* initialize tuple type
*/
- ExecAssignResultTypeFromTL((Plan *) node, &scanstate->csstate.cstate);
- ExecAssignProjectionInfo((Plan *) node, &scanstate->csstate.cstate);
+ ExecAssignResultTypeFromTL(&scanstate->ss.ps);
+ ExecAssignProjectionInfo(&scanstate->ss.ps);
- return TRUE;
+ return scanstate;
}
int
@@ -265,39 +269,26 @@ ExecCountSlotsFunctionScan(FunctionScan *node)
* ----------------------------------------------------------------
*/
void
-ExecEndFunctionScan(FunctionScan *node)
+ExecEndFunctionScan(FunctionScanState *node)
{
- FunctionScanState *scanstate;
- EState *estate;
-
- /*
- * get information from node
- */
- scanstate = (FunctionScanState *) node->scan.scanstate;
- estate = node->scan.plan.state;
-
/*
* Free the projection info and the scan attribute info
- *
- * Note: we don't ExecFreeResultType(scanstate) because the rule manager
- * depends on the tupType returned by ExecMain(). So for now, this is
- * freed at end-transaction time. -cim 6/2/91
*/
- ExecFreeProjectionInfo(&scanstate->csstate.cstate);
- ExecFreeExprContext(&scanstate->csstate.cstate);
+ ExecFreeProjectionInfo(&node->ss.ps);
+ ExecFreeExprContext(&node->ss.ps);
/*
* clean out the tuple table
*/
- ExecClearTuple(scanstate->csstate.cstate.cs_ResultTupleSlot);
- ExecClearTuple(scanstate->csstate.css_ScanTupleSlot);
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ ExecClearTuple(node->ss.ss_ScanTupleSlot);
/*
* Release tuplestore resources
*/
- if (scanstate->tuplestorestate != NULL)
- tuplestore_end(scanstate->tuplestorestate);
- scanstate->tuplestorestate = NULL;
+ if (node->tuplestorestate != NULL)
+ tuplestore_end(node->tuplestorestate);
+ node->tuplestorestate = NULL;
}
/* ----------------------------------------------------------------
@@ -307,19 +298,15 @@ ExecEndFunctionScan(FunctionScan *node)
* ----------------------------------------------------------------
*/
void
-ExecFunctionMarkPos(FunctionScan *node)
+ExecFunctionMarkPos(FunctionScanState *node)
{
- FunctionScanState *scanstate;
-
- scanstate = (FunctionScanState *) node->scan.scanstate;
-
/*
* if we haven't materialized yet, just return.
*/
- if (!scanstate->tuplestorestate)
+ if (!node->tuplestorestate)
return;
- tuplestore_markpos(scanstate->tuplestorestate);
+ tuplestore_markpos(node->tuplestorestate);
}
/* ----------------------------------------------------------------
@@ -329,19 +316,15 @@ ExecFunctionMarkPos(FunctionScan *node)
* ----------------------------------------------------------------
*/
void
-ExecFunctionRestrPos(FunctionScan *node)
+ExecFunctionRestrPos(FunctionScanState *node)
{
- FunctionScanState *scanstate;
-
- scanstate = (FunctionScanState *) node->scan.scanstate;
-
/*
* if we haven't materialized yet, just return.
*/
- if (!scanstate->tuplestorestate)
+ if (!node->tuplestorestate)
return;
- tuplestore_restorepos(scanstate->tuplestorestate);
+ tuplestore_restorepos(node->tuplestorestate);
}
/* ----------------------------------------------------------------
@@ -351,21 +334,14 @@ ExecFunctionRestrPos(FunctionScan *node)
* ----------------------------------------------------------------
*/
void
-ExecFunctionReScan(FunctionScan *node, ExprContext *exprCtxt, Plan *parent)
+ExecFunctionReScan(FunctionScanState *node, ExprContext *exprCtxt)
{
- FunctionScanState *scanstate;
-
- /*
- * get information from node
- */
- scanstate = (FunctionScanState *) node->scan.scanstate;
-
- ExecClearTuple(scanstate->csstate.cstate.cs_ResultTupleSlot);
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
/*
* If we haven't materialized yet, just return.
*/
- if (!scanstate->tuplestorestate)
+ if (!node->tuplestorestate)
return;
/*
@@ -374,13 +350,13 @@ ExecFunctionReScan(FunctionScan *node, ExprContext *exprCtxt, Plan *parent)
* whether the function expression contains parameters and/or is
* marked volatile. FIXME soon.
*/
- if (node->scan.plan.chgParam != NULL)
+ if (node->ss.ps.chgParam != NULL)
{
- tuplestore_end(scanstate->tuplestorestate);
- scanstate->tuplestorestate = NULL;
+ tuplestore_end(node->tuplestorestate);
+ node->tuplestorestate = NULL;
}
else
- tuplestore_rescan(scanstate->tuplestorestate);
+ tuplestore_rescan(node->tuplestorestate);
}
diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c
index d41bcbb6fcc..3d562a476b8 100644
--- a/src/backend/executor/nodeGroup.c
+++ b/src/backend/executor/nodeGroup.c
@@ -15,7 +15,7 @@
* locate group boundaries.
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.50 2002/11/29 21:39:11 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.51 2002/12/05 15:50:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -38,12 +38,13 @@
* Return one tuple for each group of matching input tuples.
*/
TupleTableSlot *
-ExecGroup(Group *node)
+ExecGroup(GroupState *node)
{
- GroupState *grpstate;
EState *estate;
ExprContext *econtext;
TupleDesc tupdesc;
+ int numCols;
+ AttrNumber *grpColIdx;
HeapTuple outerTuple = NULL;
HeapTuple firsttuple;
TupleTableSlot *outerslot;
@@ -53,12 +54,13 @@ ExecGroup(Group *node)
/*
* get state info from node
*/
- grpstate = node->grpstate;
- if (grpstate->grp_done)
+ if (node->grp_done)
return NULL;
- estate = node->plan.state;
- econtext = node->grpstate->csstate.cstate.cs_ExprContext;
- tupdesc = ExecGetScanType(&grpstate->csstate);
+ estate = node->ss.ps.state;
+ econtext = node->ss.ps.ps_ExprContext;
+ tupdesc = ExecGetScanType(&node->ss);
+ numCols = ((Group *) node->ss.ps.plan)->numCols;
+ grpColIdx = ((Group *) node->ss.ps.plan)->grpColIdx;
/*
* We need not call ResetExprContext here because execTuplesMatch will
@@ -67,16 +69,16 @@ ExecGroup(Group *node)
/* If we don't already have first tuple of group, fetch it */
/* this should occur on the first call only */
- firsttuple = grpstate->grp_firstTuple;
+ firsttuple = node->grp_firstTuple;
if (firsttuple == NULL)
{
- outerslot = ExecProcNode(outerPlan(node), (Plan *) node);
+ outerslot = ExecProcNode(outerPlanState(node));
if (TupIsNull(outerslot))
{
- grpstate->grp_done = TRUE;
+ node->grp_done = TRUE;
return NULL;
}
- grpstate->grp_firstTuple = firsttuple =
+ node->grp_firstTuple = firsttuple =
heap_copytuple(outerslot->val);
}
@@ -85,10 +87,10 @@ ExecGroup(Group *node)
*/
for (;;)
{
- outerslot = ExecProcNode(outerPlan(node), (Plan *) node);
+ outerslot = ExecProcNode(outerPlanState(node));
if (TupIsNull(outerslot))
{
- grpstate->grp_done = TRUE;
+ node->grp_done = TRUE;
outerTuple = NULL;
break;
}
@@ -100,8 +102,8 @@ ExecGroup(Group *node)
*/
if (!execTuplesMatch(firsttuple, outerTuple,
tupdesc,
- node->numCols, node->grpColIdx,
- grpstate->eqfunctions,
+ numCols, grpColIdx,
+ node->eqfunctions,
econtext->ecxt_per_tuple_memory))
break;
}
@@ -111,18 +113,18 @@ ExecGroup(Group *node)
* group, and store it in the result tuple slot.
*/
ExecStoreTuple(firsttuple,
- grpstate->csstate.css_ScanTupleSlot,
+ node->ss.ss_ScanTupleSlot,
InvalidBuffer,
false);
- econtext->ecxt_scantuple = grpstate->csstate.css_ScanTupleSlot;
- projInfo = grpstate->csstate.cstate.cs_ProjInfo;
+ econtext->ecxt_scantuple = node->ss.ss_ScanTupleSlot;
+ projInfo = node->ss.ps.ps_ProjInfo;
resultSlot = ExecProject(projInfo, NULL);
/* save first tuple of next group, if we are not done yet */
- if (!grpstate->grp_done)
+ if (!node->grp_done)
{
heap_freetuple(firsttuple);
- grpstate->grp_firstTuple = heap_copytuple(outerTuple);
+ node->grp_firstTuple = heap_copytuple(outerTuple);
}
return resultSlot;
@@ -135,65 +137,69 @@ ExecGroup(Group *node)
* planner and initializes its outer subtree
* -----------------
*/
-bool
-ExecInitGroup(Group *node, EState *estate, Plan *parent)
+GroupState *
+ExecInitGroup(Group *node, EState *estate)
{
GroupState *grpstate;
- Plan *outerPlan;
-
- /*
- * assign the node's execution state
- */
- node->plan.state = estate;
/*
* create state structure
*/
grpstate = makeNode(GroupState);
- node->grpstate = grpstate;
+ grpstate->ss.ps.plan = (Plan *) node;
+ grpstate->ss.ps.state = estate;
grpstate->grp_firstTuple = NULL;
grpstate->grp_done = FALSE;
/*
* create expression context
*/
- ExecAssignExprContext(estate, &grpstate->csstate.cstate);
+ ExecAssignExprContext(estate, &grpstate->ss.ps);
#define GROUP_NSLOTS 2
/*
* tuple table initialization
*/
- ExecInitScanTupleSlot(estate, &grpstate->csstate);
- ExecInitResultTupleSlot(estate, &grpstate->csstate.cstate);
+ ExecInitScanTupleSlot(estate, &grpstate->ss);
+ ExecInitResultTupleSlot(estate, &grpstate->ss.ps);
+
+ /*
+ * initialize child expressions
+ */
+ grpstate->ss.ps.targetlist = (List *)
+ ExecInitExpr((Node *) node->plan.targetlist,
+ (PlanState *) grpstate);
+ grpstate->ss.ps.qual = (List *)
+ ExecInitExpr((Node *) node->plan.qual,
+ (PlanState *) grpstate);
/*
- * initializes child nodes
+ * initialize child nodes
*/
- outerPlan = outerPlan(node);
- ExecInitNode(outerPlan, estate, (Plan *) node);
+ outerPlanState(grpstate) = ExecInitNode(outerPlan(node), estate);
/*
* initialize tuple type.
*/
- ExecAssignScanTypeFromOuterPlan((Plan *) node, &grpstate->csstate);
+ ExecAssignScanTypeFromOuterPlan(&grpstate->ss);
/*
* Initialize tuple type for both result and scan. This node does no
* projection
*/
- ExecAssignResultTypeFromTL((Plan *) node, &grpstate->csstate.cstate);
- ExecAssignProjectionInfo((Plan *) node, &grpstate->csstate.cstate);
+ ExecAssignResultTypeFromTL(&grpstate->ss.ps);
+ ExecAssignProjectionInfo(&grpstate->ss.ps);
/*
* Precompute fmgr lookup data for inner loop
*/
grpstate->eqfunctions =
- execTuplesMatchPrepare(ExecGetScanType(&grpstate->csstate),
+ execTuplesMatchPrepare(ExecGetScanType(&grpstate->ss),
node->numCols,
node->grpColIdx);
- return TRUE;
+ return grpstate;
}
int
@@ -208,43 +214,38 @@ ExecCountSlotsGroup(Group *node)
* -----------------------
*/
void
-ExecEndGroup(Group *node)
+ExecEndGroup(GroupState *node)
{
- GroupState *grpstate;
- Plan *outerPlan;
+ PlanState *outerPlan;
- grpstate = node->grpstate;
+ ExecFreeProjectionInfo(&node->ss.ps);
+ ExecFreeExprContext(&node->ss.ps);
- ExecFreeProjectionInfo(&grpstate->csstate.cstate);
- ExecFreeExprContext(&grpstate->csstate.cstate);
-
- outerPlan = outerPlan(node);
- ExecEndNode(outerPlan, (Plan *) node);
+ outerPlan = outerPlanState(node);
+ ExecEndNode(outerPlan);
/* clean up tuple table */
- ExecClearTuple(grpstate->csstate.css_ScanTupleSlot);
- if (grpstate->grp_firstTuple != NULL)
+ ExecClearTuple(node->ss.ss_ScanTupleSlot);
+ if (node->grp_firstTuple != NULL)
{
- heap_freetuple(grpstate->grp_firstTuple);
- grpstate->grp_firstTuple = NULL;
+ heap_freetuple(node->grp_firstTuple);
+ node->grp_firstTuple = NULL;
}
}
void
-ExecReScanGroup(Group *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanGroup(GroupState *node, ExprContext *exprCtxt)
{
- GroupState *grpstate = node->grpstate;
-
- grpstate->grp_done = FALSE;
- if (grpstate->grp_firstTuple != NULL)
+ node->grp_done = FALSE;
+ if (node->grp_firstTuple != NULL)
{
- heap_freetuple(grpstate->grp_firstTuple);
- grpstate->grp_firstTuple = NULL;
+ heap_freetuple(node->grp_firstTuple);
+ node->grp_firstTuple = NULL;
}
- if (((Plan *) node)->lefttree &&
- ((Plan *) node)->lefttree->chgParam == NULL)
- ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);
+ if (((PlanState *) node)->lefttree &&
+ ((PlanState *) node)->lefttree->chgParam == NULL)
+ ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
}
/*****************************************************************************
diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c
index c2c3ab66644..9448ee466a8 100644
--- a/src/backend/executor/nodeHash.c
+++ b/src/backend/executor/nodeHash.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeHash.c,v 1.68 2002/11/30 00:08:15 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeHash.c,v 1.69 2002/12/05 15:50:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -40,11 +40,10 @@
* ----------------------------------------------------------------
*/
TupleTableSlot *
-ExecHash(Hash *node)
+ExecHash(HashState *node)
{
EState *estate;
- HashState *hashstate;
- Plan *outerNode;
+ PlanState *outerNode;
List *hashkeys;
HashJoinTable hashtable;
TupleTableSlot *slot;
@@ -55,12 +54,10 @@ ExecHash(Hash *node)
/*
* get state info from node
*/
+ estate = node->ps.state;
+ outerNode = outerPlanState(node);
- hashstate = node->hashstate;
- estate = node->plan.state;
- outerNode = outerPlan(node);
-
- hashtable = hashstate->hashtable;
+ hashtable = node->hashtable;
if (hashtable == NULL)
elog(ERROR, "ExecHash: hash table is NULL.");
@@ -79,15 +76,15 @@ ExecHash(Hash *node)
/*
* set expression context
*/
- hashkeys = node->hashkeys;
- econtext = hashstate->cstate.cs_ExprContext;
+ hashkeys = ((Hash *) node->ps.plan)->hashkeys;
+ econtext = node->ps.ps_ExprContext;
/*
* get all inner tuples and insert into the hash table (or temp files)
*/
for (;;)
{
- slot = ExecProcNode(outerNode, (Plan *) node);
+ slot = ExecProcNode(outerNode);
if (TupIsNull(slot))
break;
econtext->ecxt_innertuple = slot;
@@ -108,24 +105,19 @@ ExecHash(Hash *node)
* Init routine for Hash node
* ----------------------------------------------------------------
*/
-bool
-ExecInitHash(Hash *node, EState *estate, Plan *parent)
+HashState *
+ExecInitHash(Hash *node, EState *estate)
{
HashState *hashstate;
- Plan *outerPlan;
SO_printf("ExecInitHash: initializing hash node\n");
/*
- * assign the node's execution state
- */
- node->plan.state = estate;
-
- /*
* create state structure
*/
hashstate = makeNode(HashState);
- node->hashstate = hashstate;
+ hashstate->ps.plan = (Plan *) node;
+ hashstate->ps.state = estate;
hashstate->hashtable = NULL;
/*
@@ -133,29 +125,38 @@ ExecInitHash(Hash *node, EState *estate, Plan *parent)
*
* create expression context for node
*/
- ExecAssignExprContext(estate, &hashstate->cstate);
+ ExecAssignExprContext(estate, &hashstate->ps);
#define HASH_NSLOTS 1
/*
* initialize our result slot
*/
- ExecInitResultTupleSlot(estate, &hashstate->cstate);
+ ExecInitResultTupleSlot(estate, &hashstate->ps);
/*
- * initializes child nodes
+ * initialize child expressions
*/
- outerPlan = outerPlan(node);
- ExecInitNode(outerPlan, estate, (Plan *) node);
+ hashstate->ps.targetlist = (List *)
+ ExecInitExpr((Node *) node->plan.targetlist,
+ (PlanState *) hashstate);
+ hashstate->ps.qual = (List *)
+ ExecInitExpr((Node *) node->plan.qual,
+ (PlanState *) hashstate);
+
+ /*
+ * initialize child nodes
+ */
+ outerPlanState(hashstate) = ExecInitNode(outerPlan(node), estate);
/*
* initialize tuple type. no need to initialize projection info
* because this node doesn't do projections
*/
- ExecAssignResultTypeFromOuterPlan((Plan *) node, &hashstate->cstate);
- hashstate->cstate.cs_ProjInfo = NULL;
+ ExecAssignResultTypeFromOuterPlan(&hashstate->ps);
+ hashstate->ps.ps_ProjInfo = NULL;
- return TRUE;
+ return hashstate;
}
int
@@ -173,28 +174,22 @@ ExecCountSlotsHash(Hash *node)
* ----------------------------------------------------------------
*/
void
-ExecEndHash(Hash *node)
+ExecEndHash(HashState *node)
{
- HashState *hashstate;
- Plan *outerPlan;
-
- /*
- * get info from the hash state
- */
- hashstate = node->hashstate;
+ PlanState *outerPlan;
/*
* free projection info. no need to free result type info because
* that came from the outer plan...
*/
- ExecFreeProjectionInfo(&hashstate->cstate);
- ExecFreeExprContext(&hashstate->cstate);
+ ExecFreeProjectionInfo(&node->ps);
+ ExecFreeExprContext(&node->ps);
/*
* shut down the subplan
*/
- outerPlan = outerPlan(node);
- ExecEndNode(outerPlan, (Plan *) node);
+ outerPlan = outerPlanState(node);
+ ExecEndNode(outerPlan);
}
@@ -758,12 +753,12 @@ ExecHashTableReset(HashJoinTable hashtable, long ntuples)
}
void
-ExecReScanHash(Hash *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanHash(HashState *node, ExprContext *exprCtxt)
{
/*
* 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);
+ if (((PlanState *) node)->lefttree->chgParam == NULL)
+ ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
}
diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c
index 8f0e700ac35..06796c590e3 100644
--- a/src/backend/executor/nodeHashjoin.c
+++ b/src/backend/executor/nodeHashjoin.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.42 2002/11/30 00:08:15 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.43 2002/12/05 15:50:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -22,8 +22,8 @@
#include "utils/memutils.h"
-static TupleTableSlot *ExecHashJoinOuterGetTuple(Plan *node, Plan *parent,
- HashJoinState *hjstate);
+static TupleTableSlot *ExecHashJoinOuterGetTuple(PlanState *node,
+ HashJoinState *hjstate);
static TupleTableSlot *ExecHashJoinGetSavedTuple(HashJoinState *hjstate,
BufFile *file,
TupleTableSlot *tupleSlot);
@@ -41,12 +41,11 @@ static int ExecHashJoinNewBatch(HashJoinState *hjstate);
* ----------------------------------------------------------------
*/
TupleTableSlot * /* return: a tuple or NULL */
-ExecHashJoin(HashJoin *node)
+ExecHashJoin(HashJoinState *node)
{
- HashJoinState *hjstate;
EState *estate;
- Plan *outerNode;
- Hash *hashNode;
+ PlanState *outerNode;
+ HashState *hashNode;
List *hjclauses;
List *outerkeys;
List *joinqual;
@@ -65,37 +64,36 @@ ExecHashJoin(HashJoin *node)
/*
* get information from HashJoin node
*/
- hjstate = node->hashjoinstate;
hjclauses = node->hashclauses;
- estate = node->join.plan.state;
- joinqual = node->join.joinqual;
- otherqual = node->join.plan.qual;
- hashNode = (Hash *) innerPlan(node);
- outerNode = outerPlan(node);
- hashPhaseDone = hjstate->hj_hashdone;
+ estate = node->js.ps.state;
+ joinqual = node->js.joinqual;
+ otherqual = node->js.ps.qual;
+ hashNode = (HashState *) innerPlanState(node);
+ outerNode = outerPlanState(node);
+ hashPhaseDone = node->hj_hashdone;
dir = estate->es_direction;
/*
* get information from HashJoin state
*/
- hashtable = hjstate->hj_HashTable;
- outerkeys = hjstate->hj_OuterHashKeys;
- econtext = hjstate->jstate.cs_ExprContext;
+ hashtable = node->hj_HashTable;
+ outerkeys = node->hj_OuterHashKeys;
+ econtext = node->js.ps.ps_ExprContext;
/*
* Check to see if we're still projecting out tuples from a previous
* join tuple (because there is a function-returning-set in the
* projection expressions). If so, try to project another one.
*/
- if (hjstate->jstate.cs_TupFromTlist)
+ if (node->js.ps.ps_TupFromTlist)
{
TupleTableSlot *result;
- result = ExecProject(hjstate->jstate.cs_ProjInfo, &isDone);
+ result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
if (isDone == ExprMultipleResult)
return result;
/* Done with that source tuple... */
- hjstate->jstate.cs_TupFromTlist = false;
+ node->js.ps.ps_TupFromTlist = false;
}
/*
@@ -116,16 +114,16 @@ ExecHashJoin(HashJoin *node)
/*
* create the hash table
*/
- hashtable = ExecHashTableCreate(hashNode);
- hjstate->hj_HashTable = hashtable;
+ hashtable = ExecHashTableCreate((Hash *) hashNode->ps.plan);
+ node->hj_HashTable = hashtable;
/*
* execute the Hash node, to build the hash table
*/
- hashNode->hashstate->hashtable = hashtable;
- innerTupleSlot = ExecProcNode((Plan *) hashNode, (Plan *) node);
+ hashNode->hashtable = hashtable;
+ innerTupleSlot = ExecProcNode((PlanState *) hashNode);
}
- hjstate->hj_hashdone = true;
+ node->hj_hashdone = true;
/*
* Open temp files for outer batches, if needed. Note that file
@@ -140,40 +138,39 @@ ExecHashJoin(HashJoin *node)
/*
* Now get an outer tuple and probe into the hash table for matches
*/
- outerTupleSlot = hjstate->jstate.cs_OuterTupleSlot;
+ outerTupleSlot = node->js.ps.ps_OuterTupleSlot;
for (;;)
{
/*
* If we don't have an outer tuple, get the next one
*/
- if (hjstate->hj_NeedNewOuter)
+ if (node->hj_NeedNewOuter)
{
outerTupleSlot = ExecHashJoinOuterGetTuple(outerNode,
- (Plan *) node,
- hjstate);
+ node);
if (TupIsNull(outerTupleSlot))
{
/*
* when the last batch runs out, clean up and exit
*/
ExecHashTableDestroy(hashtable);
- hjstate->hj_HashTable = NULL;
+ node->hj_HashTable = NULL;
return NULL;
}
- hjstate->jstate.cs_OuterTupleSlot = outerTupleSlot;
+ node->js.ps.ps_OuterTupleSlot = outerTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot;
- hjstate->hj_NeedNewOuter = false;
- hjstate->hj_MatchedOuter = false;
+ node->hj_NeedNewOuter = false;
+ node->hj_MatchedOuter = false;
/*
* now we have an outer tuple, find the corresponding bucket
* for this tuple from the hash table
*/
- hjstate->hj_CurBucketNo = ExecHashGetBucket(hashtable, econtext,
+ node->hj_CurBucketNo = ExecHashGetBucket(hashtable, econtext,
outerkeys);
- hjstate->hj_CurTuple = NULL;
+ node->hj_CurTuple = NULL;
/*
* Now we've got an outer tuple and the corresponding hash
@@ -182,7 +179,7 @@ ExecHashJoin(HashJoin *node)
*/
if (hashtable->curbatch == 0)
{
- int batch = ExecHashJoinGetBatch(hjstate->hj_CurBucketNo,
+ int batch = ExecHashJoinGetBatch(node->hj_CurBucketNo,
hashtable);
if (batch > 0)
@@ -196,7 +193,7 @@ ExecHashJoin(HashJoin *node)
hashtable->outerBatchSize[batchno]++;
ExecHashJoinSaveTuple(outerTupleSlot->val,
hashtable->outerBatchFile[batchno]);
- hjstate->hj_NeedNewOuter = true;
+ node->hj_NeedNewOuter = true;
continue; /* loop around for a new outer tuple */
}
}
@@ -207,7 +204,7 @@ ExecHashJoin(HashJoin *node)
*/
for (;;)
{
- curtuple = ExecScanHashBucket(hjstate,
+ curtuple = ExecScanHashBucket(node,
hjclauses,
econtext);
if (curtuple == NULL)
@@ -217,7 +214,7 @@ ExecHashJoin(HashJoin *node)
* we've got a match, but still need to test non-hashed quals
*/
inntuple = ExecStoreTuple(curtuple,
- hjstate->hj_HashTupleSlot,
+ node->hj_HashTupleSlot,
InvalidBuffer,
false); /* don't pfree this tuple */
econtext->ecxt_innertuple = inntuple;
@@ -235,17 +232,17 @@ ExecHashJoin(HashJoin *node)
*/
if (ExecQual(joinqual, econtext, false))
{
- hjstate->hj_MatchedOuter = true;
+ node->hj_MatchedOuter = true;
if (otherqual == NIL || ExecQual(otherqual, econtext, false))
{
TupleTableSlot *result;
- result = ExecProject(hjstate->jstate.cs_ProjInfo, &isDone);
+ result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
if (isDone != ExprEndResult)
{
- hjstate->jstate.cs_TupFromTlist =
+ node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult);
return result;
}
@@ -258,10 +255,10 @@ ExecHashJoin(HashJoin *node)
* whether to emit a dummy outer-join tuple. If not, loop around
* to get a new outer tuple.
*/
- hjstate->hj_NeedNewOuter = true;
+ node->hj_NeedNewOuter = true;
- if (!hjstate->hj_MatchedOuter &&
- node->join.jointype == JOIN_LEFT)
+ if (!node->hj_MatchedOuter &&
+ node->js.jointype == JOIN_LEFT)
{
/*
* We are doing an outer join and there were no join matches
@@ -269,7 +266,7 @@ ExecHashJoin(HashJoin *node)
* nulls for the inner tuple, and return it if it passes the
* non-join quals.
*/
- econtext->ecxt_innertuple = hjstate->hj_NullInnerTupleSlot;
+ econtext->ecxt_innertuple = node->hj_NullInnerTupleSlot;
if (ExecQual(otherqual, econtext, false))
{
@@ -280,11 +277,11 @@ ExecHashJoin(HashJoin *node)
*/
TupleTableSlot *result;
- result = ExecProject(hjstate->jstate.cs_ProjInfo, &isDone);
+ result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
if (isDone != ExprEndResult)
{
- hjstate->jstate.cs_TupFromTlist =
+ node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult);
return result;
}
@@ -299,8 +296,8 @@ ExecHashJoin(HashJoin *node)
* Init routine for HashJoin node.
* ----------------------------------------------------------------
*/
-bool /* return: initialization status */
-ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
+HashJoinState *
+ExecInitHashJoin(HashJoin *node, EState *estate)
{
HashJoinState *hjstate;
Plan *outerNode;
@@ -308,38 +305,51 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
List *hcl;
/*
- * assign the node's execution state
- */
- node->join.plan.state = estate;
-
- /*
* create state structure
*/
hjstate = makeNode(HashJoinState);
- node->hashjoinstate = hjstate;
+ hjstate->js.ps.plan = (Plan *) node;
+ hjstate->js.ps.state = estate;
/*
* Miscellaneous initialization
*
* create expression context for node
*/
- ExecAssignExprContext(estate, &hjstate->jstate);
+ ExecAssignExprContext(estate, &hjstate->js.ps);
+
+ /*
+ * initialize child expressions
+ */
+ hjstate->js.ps.targetlist = (List *)
+ ExecInitExpr((Node *) node->join.plan.targetlist,
+ (PlanState *) hjstate);
+ hjstate->js.ps.qual = (List *)
+ ExecInitExpr((Node *) node->join.plan.qual,
+ (PlanState *) hjstate);
+ hjstate->js.jointype = node->join.jointype;
+ hjstate->js.joinqual = (List *)
+ ExecInitExpr((Node *) node->join.joinqual,
+ (PlanState *) hjstate);
+ hjstate->hashclauses = (List *)
+ ExecInitExpr((Node *) node->hashclauses,
+ (PlanState *) hjstate);
/*
- * initializes child nodes
+ * initialize child nodes
*/
- outerNode = outerPlan((Plan *) node);
- hashNode = (Hash *) innerPlan((Plan *) node);
+ outerNode = outerPlan(node);
+ hashNode = (Hash *) innerPlan(node);
- ExecInitNode(outerNode, estate, (Plan *) node);
- ExecInitNode((Plan *) hashNode, estate, (Plan *) node);
+ outerPlanState(hjstate) = ExecInitNode(outerNode, estate);
+ innerPlanState(hjstate) = ExecInitNode((Plan *) hashNode, estate);
#define HASHJOIN_NSLOTS 3
/*
* tuple table initialization
*/
- ExecInitResultTupleSlot(estate, &hjstate->jstate);
+ ExecInitResultTupleSlot(estate, &hjstate->js.ps);
hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate);
switch (node->join.jointype)
@@ -349,7 +359,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
case JOIN_LEFT:
hjstate->hj_NullInnerTupleSlot =
ExecInitNullTupleSlot(estate,
- ExecGetTupType((Plan *) hashNode));
+ ExecGetTupType(innerPlanState(hjstate)));
break;
default:
elog(ERROR, "ExecInitHashJoin: unsupported join type %d",
@@ -364,8 +374,8 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
* the contents of the hash table. -cim 6/9/91
*/
{
- HashState *hashstate = hashNode->hashstate;
- TupleTableSlot *slot = hashstate->cstate.cs_ResultTupleSlot;
+ HashState *hashstate = (HashState *) innerPlanState(hjstate);
+ TupleTableSlot *slot = hashstate->ps.ps_ResultTupleSlot;
hjstate->hj_HashTupleSlot = slot;
}
@@ -373,11 +383,11 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
/*
* initialize tuple type and projection info
*/
- ExecAssignResultTypeFromTL((Plan *) node, &hjstate->jstate);
- ExecAssignProjectionInfo((Plan *) node, &hjstate->jstate);
+ ExecAssignResultTypeFromTL(&hjstate->js.ps);
+ ExecAssignProjectionInfo(&hjstate->js.ps);
ExecSetSlotDescriptor(hjstate->hj_OuterTupleSlot,
- ExecGetTupType(outerNode),
+ ExecGetTupType(outerPlanState(hjstate)),
false);
/*
@@ -402,12 +412,12 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
get_leftop(lfirst(hcl)));
}
- hjstate->jstate.cs_OuterTupleSlot = NULL;
- hjstate->jstate.cs_TupFromTlist = false;
+ hjstate->js.ps.ps_OuterTupleSlot = NULL;
+ hjstate->js.ps.ps_TupFromTlist = false;
hjstate->hj_NeedNewOuter = true;
hjstate->hj_MatchedOuter = false;
- return TRUE;
+ return hjstate;
}
int
@@ -425,46 +435,35 @@ ExecCountSlotsHashJoin(HashJoin *node)
* ----------------------------------------------------------------
*/
void
-ExecEndHashJoin(HashJoin *node)
+ExecEndHashJoin(HashJoinState *node)
{
- HashJoinState *hjstate;
-
- /*
- * get info from the HashJoin state
- */
- hjstate = node->hashjoinstate;
-
/*
* free hash table in case we end plan before all tuples are retrieved
*/
- if (hjstate->hj_HashTable)
+ if (node->hj_HashTable)
{
- ExecHashTableDestroy(hjstate->hj_HashTable);
- hjstate->hj_HashTable = NULL;
+ ExecHashTableDestroy(node->hj_HashTable);
+ node->hj_HashTable = NULL;
}
/*
* Free the projection info and the scan attribute info
- *
- * Note: we don't ExecFreeResultType(hjstate) because the rule manager
- * depends on the tupType returned by ExecMain(). So for now, this is
- * freed at end-transaction time. -cim 6/2/91
*/
- ExecFreeProjectionInfo(&hjstate->jstate);
- ExecFreeExprContext(&hjstate->jstate);
+ ExecFreeProjectionInfo(&node->js.ps);
+ ExecFreeExprContext(&node->js.ps);
/*
* clean up subtrees
*/
- ExecEndNode(outerPlan((Plan *) node), (Plan *) node);
- ExecEndNode(innerPlan((Plan *) node), (Plan *) node);
+ ExecEndNode(outerPlanState(node));
+ ExecEndNode(innerPlanState(node));
/*
* clean out the tuple table
*/
- ExecClearTuple(hjstate->jstate.cs_ResultTupleSlot);
- ExecClearTuple(hjstate->hj_OuterTupleSlot);
- ExecClearTuple(hjstate->hj_HashTupleSlot);
+ ExecClearTuple(node->js.ps.ps_ResultTupleSlot);
+ ExecClearTuple(node->hj_OuterTupleSlot);
+ ExecClearTuple(node->hj_HashTupleSlot);
}
@@ -478,7 +477,7 @@ ExecEndHashJoin(HashJoin *node)
*/
static TupleTableSlot *
-ExecHashJoinOuterGetTuple(Plan *node, Plan *parent, HashJoinState *hjstate)
+ExecHashJoinOuterGetTuple(PlanState *node, HashJoinState *hjstate)
{
HashJoinTable hashtable = hjstate->hj_HashTable;
int curbatch = hashtable->curbatch;
@@ -486,7 +485,7 @@ ExecHashJoinOuterGetTuple(Plan *node, Plan *parent, HashJoinState *hjstate)
if (curbatch == 0)
{ /* if it is the first pass */
- slot = ExecProcNode(node, parent);
+ slot = ExecProcNode(node);
if (!TupIsNull(slot))
return slot;
@@ -611,7 +610,7 @@ ExecHashJoinNewBatch(HashJoinState *hjstate)
*/
ExecHashTableReset(hashtable, innerBatchSize[newbatch - 1]);
- econtext = hjstate->jstate.cs_ExprContext;
+ econtext = hjstate->js.ps.ps_ExprContext;
innerhashkeys = hjstate->hj_InnerHashKeys;
while ((slot = ExecHashJoinGetSavedTuple(hjstate,
@@ -682,39 +681,37 @@ ExecHashJoinSaveTuple(HeapTuple heapTuple,
}
void
-ExecReScanHashJoin(HashJoin *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanHashJoin(HashJoinState *node, ExprContext *exprCtxt)
{
- HashJoinState *hjstate = node->hashjoinstate;
-
- if (!hjstate->hj_hashdone)
+ if (!node->hj_hashdone)
return;
- hjstate->hj_hashdone = false;
+ node->hj_hashdone = false;
/*
* Unfortunately, currently we have to destroy hashtable in all
* cases...
*/
- if (hjstate->hj_HashTable)
+ if (node->hj_HashTable)
{
- ExecHashTableDestroy(hjstate->hj_HashTable);
- hjstate->hj_HashTable = NULL;
+ ExecHashTableDestroy(node->hj_HashTable);
+ node->hj_HashTable = NULL;
}
- hjstate->hj_CurBucketNo = 0;
- hjstate->hj_CurTuple = (HashJoinTuple) NULL;
+ node->hj_CurBucketNo = 0;
+ node->hj_CurTuple = (HashJoinTuple) NULL;
- hjstate->jstate.cs_OuterTupleSlot = (TupleTableSlot *) NULL;
- hjstate->jstate.cs_TupFromTlist = false;
- hjstate->hj_NeedNewOuter = true;
- hjstate->hj_MatchedOuter = false;
+ node->js.ps.ps_OuterTupleSlot = (TupleTableSlot *) NULL;
+ node->js.ps.ps_TupFromTlist = false;
+ node->hj_NeedNewOuter = true;
+ node->hj_MatchedOuter = false;
/*
* if chgParam of subnodes is not null then plans will be re-scanned
* by first ExecProcNode.
*/
- if (((Plan *) node)->lefttree->chgParam == NULL)
- ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);
- if (((Plan *) node)->righttree->chgParam == NULL)
- ExecReScan(((Plan *) node)->righttree, exprCtxt, (Plan *) node);
+ if (((PlanState *) node)->lefttree->chgParam == NULL)
+ ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
+ if (((PlanState *) node)->righttree->chgParam == NULL)
+ ExecReScan(((PlanState *) node)->righttree, exprCtxt);
}
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 78f5ad0ba26..e9888c4d3f5 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.71 2002/09/04 20:31:18 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.72 2002/12/05 15:50:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -40,7 +40,7 @@
#define LEFT_OP 1
#define RIGHT_OP 2
-static TupleTableSlot *IndexNext(IndexScan *node);
+static TupleTableSlot *IndexNext(IndexScanState *node);
/* ----------------------------------------------------------------
* IndexNext
@@ -65,15 +65,14 @@ static TupleTableSlot *IndexNext(IndexScan *node);
* ----------------------------------------------------------------
*/
static TupleTableSlot *
-IndexNext(IndexScan *node)
+IndexNext(IndexScanState *node)
{
EState *estate;
- CommonScanState *scanstate;
- IndexScanState *indexstate;
ExprContext *econtext;
ScanDirection direction;
IndexScanDescPtr scanDescs;
IndexScanDesc scandesc;
+ Index scanrelid;
HeapTuple tuple;
TupleTableSlot *slot;
int numIndices;
@@ -83,21 +82,20 @@ IndexNext(IndexScan *node)
/*
* extract necessary information from index scan node
*/
- estate = node->scan.plan.state;
+ estate = node->ss.ps.state;
direction = estate->es_direction;
- if (ScanDirectionIsBackward(node->indxorderdir))
+ if (ScanDirectionIsBackward(((IndexScan *) node->ss.ps.plan)->indxorderdir))
{
if (ScanDirectionIsForward(direction))
direction = BackwardScanDirection;
else if (ScanDirectionIsBackward(direction))
direction = ForwardScanDirection;
}
- scanstate = node->scan.scanstate;
- indexstate = node->indxstate;
- scanDescs = indexstate->iss_ScanDescs;
- numIndices = indexstate->iss_NumIndices;
- econtext = scanstate->cstate.cs_ExprContext;
- slot = scanstate->css_ScanTupleSlot;
+ scanDescs = node->iss_ScanDescs;
+ numIndices = node->iss_NumIndices;
+ econtext = node->ss.ps.ps_ExprContext;
+ slot = node->ss.ss_ScanTupleSlot;
+ scanrelid = ((IndexScan *) node->ss.ps.plan)->scan.scanrelid;
/*
* Check if we are evaluating PlanQual for tuple of this relation.
@@ -106,15 +104,15 @@ IndexNext(IndexScan *node)
* switching in Init/ReScan plan...
*/
if (estate->es_evTuple != NULL &&
- estate->es_evTuple[node->scan.scanrelid - 1] != NULL)
+ estate->es_evTuple[scanrelid - 1] != NULL)
{
List *qual;
ExecClearTuple(slot);
- if (estate->es_evTupleNull[node->scan.scanrelid - 1])
+ if (estate->es_evTupleNull[scanrelid - 1])
return slot; /* return empty slot */
- ExecStoreTuple(estate->es_evTuple[node->scan.scanrelid - 1],
+ ExecStoreTuple(estate->es_evTuple[scanrelid - 1],
slot, InvalidBuffer, false);
/* Does the tuple meet any of the OR'd indxqual conditions? */
@@ -131,7 +129,7 @@ IndexNext(IndexScan *node)
slot->val = NULL;
/* Flag for the next call that no more tuples */
- estate->es_evTupleNull[node->scan.scanrelid - 1] = true;
+ estate->es_evTupleNull[scanrelid - 1] = true;
return slot;
}
@@ -144,24 +142,24 @@ IndexNext(IndexScan *node)
bBackward = ScanDirectionIsBackward(direction);
if (bBackward)
{
- indexNumber = numIndices - indexstate->iss_IndexPtr - 1;
+ indexNumber = numIndices - node->iss_IndexPtr - 1;
if (indexNumber < 0)
{
indexNumber = 0;
- indexstate->iss_IndexPtr = numIndices - 1;
+ node->iss_IndexPtr = numIndices - 1;
}
}
else
{
- if ((indexNumber = indexstate->iss_IndexPtr) < 0)
+ if ((indexNumber = node->iss_IndexPtr) < 0)
{
indexNumber = 0;
- indexstate->iss_IndexPtr = 0;
+ node->iss_IndexPtr = 0;
}
}
while (indexNumber < numIndices)
{
- scandesc = scanDescs[indexstate->iss_IndexPtr];
+ scandesc = scanDescs[node->iss_IndexPtr];
while ((tuple = index_getnext(scandesc, direction)) != NULL)
{
/*
@@ -181,7 +179,7 @@ IndexNext(IndexScan *node)
* We do this by passing the tuple through ExecQual and
* checking for failure with all previous qualifications.
*/
- if (indexstate->iss_IndexPtr > 0)
+ if (node->iss_IndexPtr > 0)
{
bool prev_matches = false;
int prev_index;
@@ -191,7 +189,7 @@ IndexNext(IndexScan *node)
ResetExprContext(econtext);
qual = node->indxqualorig;
for (prev_index = 0;
- prev_index < indexstate->iss_IndexPtr;
+ prev_index < node->iss_IndexPtr;
prev_index++)
{
if (ExecQual((List *) lfirst(qual), econtext, false))
@@ -216,9 +214,9 @@ IndexNext(IndexScan *node)
{
indexNumber++;
if (bBackward)
- indexstate->iss_IndexPtr--;
+ node->iss_IndexPtr--;
else
- indexstate->iss_IndexPtr++;
+ node->iss_IndexPtr++;
}
}
@@ -251,21 +249,19 @@ IndexNext(IndexScan *node)
* ----------------------------------------------------------------
*/
TupleTableSlot *
-ExecIndexScan(IndexScan *node)
+ExecIndexScan(IndexScanState *node)
{
- IndexScanState *indexstate = node->indxstate;
-
/*
* If we have runtime keys and they've not already been set up, do it
* now.
*/
- if (indexstate->iss_RuntimeKeyInfo && !indexstate->iss_RuntimeKeysReady)
- ExecReScan((Plan *) node, NULL, NULL);
+ if (node->iss_RuntimeKeyInfo && !node->iss_RuntimeKeysReady)
+ ExecReScan((PlanState *) node, NULL);
/*
* use IndexNext as access method
*/
- return ExecScan(&node->scan, (ExecScanAccessMtd) IndexNext);
+ return ExecScan(&node->ss, (ExecScanAccessMtd) IndexNext);
}
/* ----------------------------------------------------------------
@@ -280,28 +276,27 @@ ExecIndexScan(IndexScan *node)
* ----------------------------------------------------------------
*/
void
-ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
+ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt)
{
EState *estate;
- IndexScanState *indexstate;
ExprContext *econtext;
int numIndices;
IndexScanDescPtr scanDescs;
ScanKey *scanKeys;
int **runtimeKeyInfo;
int *numScanKeys;
+ Index scanrelid;
int i;
int j;
- estate = node->scan.plan.state;
- indexstate = node->indxstate;
- econtext = indexstate->iss_RuntimeContext; /* context for runtime
- * keys */
- numIndices = indexstate->iss_NumIndices;
- scanDescs = indexstate->iss_ScanDescs;
- scanKeys = indexstate->iss_ScanKeys;
- runtimeKeyInfo = indexstate->iss_RuntimeKeyInfo;
- numScanKeys = indexstate->iss_NumScanKeys;
+ estate = node->ss.ps.state;
+ econtext = node->iss_RuntimeContext; /* context for runtime keys */
+ numIndices = node->iss_NumIndices;
+ scanDescs = node->iss_ScanDescs;
+ scanKeys = node->iss_ScanKeys;
+ runtimeKeyInfo = node->iss_RuntimeKeyInfo;
+ numScanKeys = node->iss_NumScanKeys;
+ scanrelid = ((IndexScan *) node->ss.ps.plan)->scan.scanrelid;
if (econtext)
{
@@ -315,7 +310,7 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
ExprContext *stdecontext;
econtext->ecxt_outertuple = exprCtxt->ecxt_outertuple;
- stdecontext = node->scan.scanstate->cstate.cs_ExprContext;
+ stdecontext = node->ss.ps.ps_ExprContext;
stdecontext->ecxt_outertuple = exprCtxt->ecxt_outertuple;
}
@@ -392,22 +387,22 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
}
}
- indexstate->iss_RuntimeKeysReady = true;
+ node->iss_RuntimeKeysReady = true;
}
/* If this is re-scanning of PlanQual ... */
if (estate->es_evTuple != NULL &&
- estate->es_evTuple[node->scan.scanrelid - 1] != NULL)
+ estate->es_evTuple[scanrelid - 1] != NULL)
{
- estate->es_evTupleNull[node->scan.scanrelid - 1] = false;
+ estate->es_evTupleNull[scanrelid - 1] = false;
return;
}
/* reset index scans */
- if (ScanDirectionIsBackward(node->indxorderdir))
- indexstate->iss_IndexPtr = numIndices;
+ if (ScanDirectionIsBackward(((IndexScan *) node->ss.ps.plan)->indxorderdir))
+ node->iss_IndexPtr = numIndices;
else
- indexstate->iss_IndexPtr = -1;
+ node->iss_IndexPtr = -1;
for (i = 0; i < numIndices; i++)
{
@@ -427,13 +422,10 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
* ----------------------------------------------------------------
*/
void
-ExecEndIndexScan(IndexScan *node)
+ExecEndIndexScan(IndexScanState *node)
{
- CommonScanState *scanstate;
- IndexScanState *indexstate;
int **runtimeKeyInfo;
ScanKey *scanKeys;
- List *indxqual;
int *numScanKeys;
int numIndices;
Relation relation;
@@ -441,32 +433,25 @@ ExecEndIndexScan(IndexScan *node)
IndexScanDescPtr indexScanDescs;
int i;
- scanstate = node->scan.scanstate;
- indexstate = node->indxstate;
- indxqual = node->indxqual;
- runtimeKeyInfo = indexstate->iss_RuntimeKeyInfo;
+ runtimeKeyInfo = node->iss_RuntimeKeyInfo;
/*
* extract information from the node
*/
- numIndices = indexstate->iss_NumIndices;
- scanKeys = indexstate->iss_ScanKeys;
- numScanKeys = indexstate->iss_NumScanKeys;
- indexRelationDescs = indexstate->iss_RelationDescs;
- indexScanDescs = indexstate->iss_ScanDescs;
- relation = scanstate->css_currentRelation;
+ numIndices = node->iss_NumIndices;
+ scanKeys = node->iss_ScanKeys;
+ numScanKeys = node->iss_NumScanKeys;
+ indexRelationDescs = node->iss_RelationDescs;
+ indexScanDescs = node->iss_ScanDescs;
+ relation = node->ss.ss_currentRelation;
/*
* Free the projection info and the scan attribute info
- *
- * Note: we don't ExecFreeResultType(scanstate) because the rule manager
- * depends on the tupType returned by ExecMain(). So for now, this is
- * freed at end-transaction time. -cim 6/2/91
*/
- ExecFreeProjectionInfo(&scanstate->cstate);
- ExecFreeExprContext(&scanstate->cstate);
- if (indexstate->iss_RuntimeContext)
- FreeExprContext(indexstate->iss_RuntimeContext);
+ ExecFreeProjectionInfo(&node->ss.ps);
+ ExecFreeExprContext(&node->ss.ps);
+ if (node->iss_RuntimeContext)
+ FreeExprContext(node->iss_RuntimeContext);
/*
* close the index relations
@@ -514,12 +499,11 @@ ExecEndIndexScan(IndexScan *node)
/*
* clear out tuple table slots
*/
- ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
- ExecClearTuple(scanstate->css_ScanTupleSlot);
- pfree(scanstate);
- pfree(indexstate->iss_RelationDescs);
- pfree(indexstate->iss_ScanDescs);
- pfree(indexstate);
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ ExecClearTuple(node->ss.ss_ScanTupleSlot);
+ pfree(node->iss_RelationDescs);
+ pfree(node->iss_ScanDescs);
+ pfree(node);
}
/* ----------------------------------------------------------------
@@ -531,21 +515,16 @@ ExecEndIndexScan(IndexScan *node)
* ----------------------------------------------------------------
*/
void
-ExecIndexMarkPos(IndexScan *node)
+ExecIndexMarkPos(IndexScanState *node)
{
- IndexScanState *indexstate;
IndexScanDescPtr indexScanDescs;
IndexScanDesc scanDesc;
int indexPtr;
- indexstate = node->indxstate;
- indexPtr = indexstate->iss_MarkIndexPtr = indexstate->iss_IndexPtr;
- indexScanDescs = indexstate->iss_ScanDescs;
+ indexPtr = node->iss_MarkIndexPtr = node->iss_IndexPtr;
+ indexScanDescs = node->iss_ScanDescs;
scanDesc = indexScanDescs[indexPtr];
-#ifdef NOT_USED
- IndexScanMarkPosition(scanDesc);
-#endif
index_markpos(scanDesc);
}
@@ -560,21 +539,16 @@ ExecIndexMarkPos(IndexScan *node)
* ----------------------------------------------------------------
*/
void
-ExecIndexRestrPos(IndexScan *node)
+ExecIndexRestrPos(IndexScanState *node)
{
- IndexScanState *indexstate;
IndexScanDescPtr indexScanDescs;
IndexScanDesc scanDesc;
int indexPtr;
- indexstate = node->indxstate;
- indexPtr = indexstate->iss_IndexPtr = indexstate->iss_MarkIndexPtr;
- indexScanDescs = indexstate->iss_ScanDescs;
+ indexPtr = node->iss_IndexPtr = node->iss_MarkIndexPtr;
+ indexScanDescs = node->iss_ScanDescs;
scanDesc = indexScanDescs[indexPtr];
-#ifdef NOT_USED
- IndexScanRestorePosition(scanDesc);
-#endif
index_restrpos(scanDesc);
}
@@ -597,11 +571,10 @@ ExecIndexRestrPos(IndexScan *node)
* estate: the execution state initialized in InitPlan.
* ----------------------------------------------------------------
*/
-bool
-ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
+IndexScanState *
+ExecInitIndexScan(IndexScan *node, EState *estate)
{
IndexScanState *indexstate;
- CommonScanState *scanstate;
List *indxqual;
List *indxid;
List *listscan;
@@ -620,45 +593,52 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
Relation currentRelation;
/*
- * assign execution state to node
+ * create state structure
*/
- node->scan.plan.state = estate;
+ indexstate = makeNode(IndexScanState);
+ indexstate->ss.ps.plan = (Plan *) node;
+ indexstate->ss.ps.state = estate;
/*
- * Part 1) initialize scan state
+ * Miscellaneous initialization
*
- * create new CommonScanState for node
+ * create expression context for node
*/
- scanstate = makeNode(CommonScanState);
- node->scan.scanstate = scanstate;
+ ExecAssignExprContext(estate, &indexstate->ss.ps);
/*
- * Miscellaneous initialization
- *
- * create expression context for node
+ * initialize child expressions
*/
- ExecAssignExprContext(estate, &scanstate->cstate);
+ indexstate->ss.ps.targetlist = (List *)
+ ExecInitExpr((Node *) node->scan.plan.targetlist,
+ (PlanState *) indexstate);
+ indexstate->ss.ps.qual = (List *)
+ ExecInitExpr((Node *) node->scan.plan.qual,
+ (PlanState *) indexstate);
+ indexstate->indxqual = (List *)
+ ExecInitExpr((Node *) node->indxqual,
+ (PlanState *) indexstate);
+ indexstate->indxqualorig = (List *)
+ ExecInitExpr((Node *) node->indxqualorig,
+ (PlanState *) indexstate);
#define INDEXSCAN_NSLOTS 2
/*
* tuple table initialization
*/
- ExecInitResultTupleSlot(estate, &scanstate->cstate);
- ExecInitScanTupleSlot(estate, scanstate);
+ ExecInitResultTupleSlot(estate, &indexstate->ss.ps);
+ ExecInitScanTupleSlot(estate, &indexstate->ss);
/*
* initialize projection info. result type comes from scan desc
* below..
*/
- ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate);
+ ExecAssignProjectionInfo(&indexstate->ss.ps);
/*
- * Part 2) initialize index scan state
- *
- * create new IndexScanState for node
+ * Initialize index-specific scan state
*/
- indexstate = makeNode(IndexScanState);
indexstate->iss_NumIndices = 0;
indexstate->iss_IndexPtr = -1;
indexstate->iss_ScanKeys = NULL;
@@ -669,8 +649,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
indexstate->iss_RelationDescs = NULL;
indexstate->iss_ScanDescs = NULL;
- node->indxstate = indexstate;
-
/*
* get the index node information
*/
@@ -836,7 +814,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
{
/* treat Param like a constant */
scanvalue = ExecEvalParam((Param *) leftop,
- scanstate->cstate.cs_ExprContext,
+ indexstate->ss.ps.ps_ExprContext,
&isnull);
if (isnull)
flags |= SK_ISNULL;
@@ -911,7 +889,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
{
/* treat Param like a constant */
scanvalue = ExecEvalParam((Param *) rightop,
- scanstate->cstate.cs_ExprContext,
+ indexstate->ss.ps.ps_ExprContext,
&isnull);
if (isnull)
flags |= SK_ISNULL;
@@ -976,12 +954,12 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
*/
if (have_runtime_keys)
{
- ExprContext *stdecontext = scanstate->cstate.cs_ExprContext;
+ ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext;
- ExecAssignExprContext(estate, &scanstate->cstate);
+ ExecAssignExprContext(estate, &indexstate->ss.ps);
indexstate->iss_RuntimeKeyInfo = runtimeKeyInfo;
- indexstate->iss_RuntimeContext = scanstate->cstate.cs_ExprContext;
- scanstate->cstate.cs_ExprContext = stdecontext;
+ indexstate->iss_RuntimeContext = indexstate->ss.ps.ps_ExprContext;
+ indexstate->ss.ps.ps_ExprContext = stdecontext;
}
else
{
@@ -1008,14 +986,14 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
if (!RelationGetForm(currentRelation)->relhasindex)
elog(ERROR, "indexes of the relation %u was inactivated", reloid);
- scanstate->css_currentRelation = currentRelation;
- scanstate->css_currentScanDesc = NULL; /* no heap scan here */
+ indexstate->ss.ss_currentRelation = currentRelation;
+ indexstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */
/*
* get the scan type from the relation descriptor.
*/
- ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false);
- ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);
+ ExecAssignScanType(&indexstate->ss, RelationGetDescr(currentRelation), false);
+ ExecAssignResultTypeFromTL(&indexstate->ss.ps);
/*
* open the index relations and initialize relation and scan
@@ -1043,7 +1021,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
/*
* all done.
*/
- return TRUE;
+ return indexstate;
}
int
diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c
index 4b22b93d579..1ea3aa62b52 100644
--- a/src/backend/executor/nodeLimit.c
+++ b/src/backend/executor/nodeLimit.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeLimit.c,v 1.11 2002/11/22 22:10:01 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeLimit.c,v 1.12 2002/12/05 15:50:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -24,7 +24,7 @@
#include "executor/executor.h"
#include "executor/nodeLimit.h"
-static void recompute_limits(Limit *node);
+static void recompute_limits(LimitState *node);
/* ----------------------------------------------------------------
@@ -35,26 +35,24 @@ static void recompute_limits(Limit *node);
* ----------------------------------------------------------------
*/
TupleTableSlot * /* return: a tuple or NULL */
-ExecLimit(Limit *node)
+ExecLimit(LimitState *node)
{
- LimitState *limitstate;
ScanDirection direction;
TupleTableSlot *resultTupleSlot;
TupleTableSlot *slot;
- Plan *outerPlan;
+ PlanState *outerPlan;
/*
* get information from the node
*/
- limitstate = node->limitstate;
- direction = node->plan.state->es_direction;
- outerPlan = outerPlan((Plan *) node);
- resultTupleSlot = limitstate->cstate.cs_ResultTupleSlot;
+ direction = node->ps.state->es_direction;
+ outerPlan = outerPlanState(node);
+ resultTupleSlot = node->ps.ps_ResultTupleSlot;
/*
* The main logic is a simple state machine.
*/
- switch (limitstate->lstate)
+ switch (node->lstate)
{
case LIMIT_INITIAL:
/*
@@ -71,9 +69,9 @@ ExecLimit(Limit *node)
/*
* Check for empty window; if so, treat like empty subplan.
*/
- if (limitstate->count <= 0 && !limitstate->noCount)
+ if (node->count <= 0 && !node->noCount)
{
- limitstate->lstate = LIMIT_EMPTY;
+ node->lstate = LIMIT_EMPTY;
return NULL;
}
/*
@@ -81,24 +79,24 @@ ExecLimit(Limit *node)
*/
for (;;)
{
- slot = ExecProcNode(outerPlan, (Plan *) node);
+ slot = ExecProcNode(outerPlan);
if (TupIsNull(slot))
{
/*
* The subplan returns too few tuples for us to produce
* any output at all.
*/
- limitstate->lstate = LIMIT_EMPTY;
+ node->lstate = LIMIT_EMPTY;
return NULL;
}
- limitstate->subSlot = slot;
- if (++limitstate->position > limitstate->offset)
+ node->subSlot = slot;
+ if (++node->position > node->offset)
break;
}
/*
* Okay, we have the first tuple of the window.
*/
- limitstate->lstate = LIMIT_INWINDOW;
+ node->lstate = LIMIT_INWINDOW;
break;
case LIMIT_EMPTY:
@@ -117,23 +115,23 @@ ExecLimit(Limit *node)
* advancing the subplan or the position variable; but
* change the state machine state to record having done so.
*/
- if (!limitstate->noCount &&
- limitstate->position >= limitstate->offset + limitstate->count)
+ if (!node->noCount &&
+ node->position >= node->offset + node->count)
{
- limitstate->lstate = LIMIT_WINDOWEND;
+ node->lstate = LIMIT_WINDOWEND;
return NULL;
}
/*
* Get next tuple from subplan, if any.
*/
- slot = ExecProcNode(outerPlan, (Plan *) node);
+ slot = ExecProcNode(outerPlan);
if (TupIsNull(slot))
{
- limitstate->lstate = LIMIT_SUBPLANEOF;
+ node->lstate = LIMIT_SUBPLANEOF;
return NULL;
}
- limitstate->subSlot = slot;
- limitstate->position++;
+ node->subSlot = slot;
+ node->position++;
}
else
{
@@ -141,19 +139,19 @@ ExecLimit(Limit *node)
* Backwards scan, so check for stepping off start of window.
* As above, change only state-machine status if so.
*/
- if (limitstate->position <= limitstate->offset + 1)
+ if (node->position <= node->offset + 1)
{
- limitstate->lstate = LIMIT_WINDOWSTART;
+ node->lstate = LIMIT_WINDOWSTART;
return NULL;
}
/*
* Get previous tuple from subplan; there should be one!
*/
- slot = ExecProcNode(outerPlan, (Plan *) node);
+ slot = ExecProcNode(outerPlan);
if (TupIsNull(slot))
elog(ERROR, "ExecLimit: subplan failed to run backwards");
- limitstate->subSlot = slot;
- limitstate->position--;
+ node->subSlot = slot;
+ node->position--;
}
break;
@@ -164,11 +162,11 @@ ExecLimit(Limit *node)
* Backing up from subplan EOF, so re-fetch previous tuple;
* there should be one! Note previous tuple must be in window.
*/
- slot = ExecProcNode(outerPlan, (Plan *) node);
+ slot = ExecProcNode(outerPlan);
if (TupIsNull(slot))
elog(ERROR, "ExecLimit: subplan failed to run backwards");
- limitstate->subSlot = slot;
- limitstate->lstate = LIMIT_INWINDOW;
+ node->subSlot = slot;
+ node->lstate = LIMIT_INWINDOW;
/* position does not change 'cause we didn't advance it before */
break;
@@ -179,8 +177,8 @@ ExecLimit(Limit *node)
* Backing up from window end: simply re-return the last
* tuple fetched from the subplan.
*/
- slot = limitstate->subSlot;
- limitstate->lstate = LIMIT_INWINDOW;
+ slot = node->subSlot;
+ node->lstate = LIMIT_INWINDOW;
/* position does not change 'cause we didn't advance it before */
break;
@@ -191,14 +189,14 @@ ExecLimit(Limit *node)
* Advancing after having backed off window start: simply
* re-return the last tuple fetched from the subplan.
*/
- slot = limitstate->subSlot;
- limitstate->lstate = LIMIT_INWINDOW;
+ slot = node->subSlot;
+ node->lstate = LIMIT_INWINDOW;
/* position does not change 'cause we didn't change it before */
break;
default:
elog(ERROR, "ExecLimit: impossible state %d",
- (int) limitstate->lstate);
+ (int) node->lstate);
slot = NULL; /* keep compiler quiet */
break;
}
@@ -220,55 +218,54 @@ ExecLimit(Limit *node)
* This is also a handy place to reset the current-position state info.
*/
static void
-recompute_limits(Limit *node)
+recompute_limits(LimitState *node)
{
- LimitState *limitstate = node->limitstate;
- ExprContext *econtext = limitstate->cstate.cs_ExprContext;
+ ExprContext *econtext = node->ps.ps_ExprContext;
bool isNull;
if (node->limitOffset)
{
- limitstate->offset =
+ node->offset =
DatumGetInt32(ExecEvalExprSwitchContext(node->limitOffset,
econtext,
&isNull,
NULL));
/* Interpret NULL offset as no offset */
if (isNull)
- limitstate->offset = 0;
- else if (limitstate->offset < 0)
- limitstate->offset = 0;
+ node->offset = 0;
+ else if (node->offset < 0)
+ node->offset = 0;
}
else
{
/* No OFFSET supplied */
- limitstate->offset = 0;
+ node->offset = 0;
}
if (node->limitCount)
{
- limitstate->noCount = false;
- limitstate->count =
+ node->noCount = false;
+ node->count =
DatumGetInt32(ExecEvalExprSwitchContext(node->limitCount,
econtext,
&isNull,
NULL));
/* Interpret NULL count as no count (LIMIT ALL) */
if (isNull)
- limitstate->noCount = true;
- else if (limitstate->count < 0)
- limitstate->count = 0;
+ node->noCount = true;
+ else if (node->count < 0)
+ node->count = 0;
}
else
{
/* No COUNT supplied */
- limitstate->count = 0;
- limitstate->noCount = true;
+ node->count = 0;
+ node->noCount = true;
}
/* Reset position to start-of-scan */
- limitstate->position = 0;
- limitstate->subSlot = NULL;
+ node->position = 0;
+ node->subSlot = NULL;
}
/* ----------------------------------------------------------------
@@ -278,22 +275,19 @@ recompute_limits(Limit *node)
* the node's subplan.
* ----------------------------------------------------------------
*/
-bool /* return: initialization status */
-ExecInitLimit(Limit *node, EState *estate, Plan *parent)
+LimitState *
+ExecInitLimit(Limit *node, EState *estate)
{
LimitState *limitstate;
Plan *outerPlan;
/*
- * assign execution state to node
- */
- node->plan.state = estate;
-
- /*
- * create new LimitState for node
+ * create state structure
*/
limitstate = makeNode(LimitState);
- node->limitstate = limitstate;
+ limitstate->ps.plan = (Plan *) node;
+ limitstate->ps.state = estate;
+
limitstate->lstate = LIMIT_INITIAL;
/*
@@ -302,29 +296,37 @@ ExecInitLimit(Limit *node, EState *estate, Plan *parent)
* Limit nodes never call ExecQual or ExecProject, but they need an
* exprcontext anyway to evaluate the limit/offset parameters in.
*/
- ExecAssignExprContext(estate, &limitstate->cstate);
+ ExecAssignExprContext(estate, &limitstate->ps);
+
+ /*
+ * initialize child expressions
+ */
+ limitstate->limitOffset = ExecInitExpr(node->limitOffset,
+ (PlanState *) limitstate);
+ limitstate->limitCount = ExecInitExpr(node->limitCount,
+ (PlanState *) limitstate);
#define LIMIT_NSLOTS 1
/*
* Tuple table initialization
*/
- ExecInitResultTupleSlot(estate, &limitstate->cstate);
+ ExecInitResultTupleSlot(estate, &limitstate->ps);
/*
* then initialize outer plan
*/
- outerPlan = outerPlan((Plan *) node);
- ExecInitNode(outerPlan, estate, (Plan *) node);
+ outerPlan = outerPlan(node);
+ outerPlanState(limitstate) = ExecInitNode(outerPlan, estate);
/*
* limit nodes do no projections, so initialize projection info for
* this node appropriately
*/
- ExecAssignResultTypeFromOuterPlan((Plan *) node, &limitstate->cstate);
- limitstate->cstate.cs_ProjInfo = NULL;
+ ExecAssignResultTypeFromOuterPlan(&limitstate->ps);
+ limitstate->ps.ps_ProjInfo = NULL;
- return TRUE;
+ return limitstate;
}
int
@@ -343,33 +345,29 @@ ExecCountSlotsLimit(Limit *node)
* ----------------------------------------------------------------
*/
void
-ExecEndLimit(Limit *node)
+ExecEndLimit(LimitState *node)
{
- LimitState *limitstate = node->limitstate;
+ ExecFreeExprContext(&node->ps);
- ExecFreeExprContext(&limitstate->cstate);
-
- ExecEndNode(outerPlan((Plan *) node), (Plan *) node);
+ ExecEndNode(outerPlanState(node));
/* clean up tuple table */
- ExecClearTuple(limitstate->cstate.cs_ResultTupleSlot);
+ ExecClearTuple(node->ps.ps_ResultTupleSlot);
}
void
-ExecReScanLimit(Limit *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanLimit(LimitState *node, ExprContext *exprCtxt)
{
- LimitState *limitstate = node->limitstate;
-
/* resetting lstate will force offset/limit recalculation */
- limitstate->lstate = LIMIT_INITIAL;
+ node->lstate = LIMIT_INITIAL;
- ExecClearTuple(limitstate->cstate.cs_ResultTupleSlot);
+ ExecClearTuple(node->ps.ps_ResultTupleSlot);
/*
* 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);
+ if (((PlanState *) node)->lefttree->chgParam == NULL)
+ ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
}
diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c
index 30eb9a285b6..cf7ca89f4a9 100644
--- a/src/backend/executor/nodeMaterial.c
+++ b/src/backend/executor/nodeMaterial.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeMaterial.c,v 1.38 2002/06/20 20:29:28 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeMaterial.c,v 1.39 2002/12/05 15:50:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -43,10 +43,9 @@
* ----------------------------------------------------------------
*/
TupleTableSlot * /* result tuple from subplan */
-ExecMaterial(Material *node)
+ExecMaterial(MaterialState *node)
{
EState *estate;
- MaterialState *matstate;
ScanDirection dir;
Tuplestorestate *tuplestorestate;
HeapTuple heapTuple;
@@ -56,10 +55,9 @@ ExecMaterial(Material *node)
/*
* get state info from node
*/
- matstate = node->matstate;
- estate = node->plan.state;
+ estate = node->ss.ps.state;
dir = estate->es_direction;
- tuplestorestate = (Tuplestorestate *) matstate->tuplestorestate;
+ tuplestorestate = (Tuplestorestate *) node->tuplestorestate;
/*
* If first time through, read all tuples from outer plan and pass
@@ -69,7 +67,7 @@ ExecMaterial(Material *node)
if (tuplestorestate == NULL)
{
- Plan *outerNode;
+ PlanState *outerNode;
/*
* Want to scan subplan in the forward direction while creating
@@ -84,16 +82,16 @@ ExecMaterial(Material *node)
tuplestorestate = tuplestore_begin_heap(true, /* randomAccess */
SortMem);
- matstate->tuplestorestate = (void *) tuplestorestate;
+ node->tuplestorestate = (void *) tuplestorestate;
/*
* Scan the subplan and feed all the tuples to tuplestore.
*/
- outerNode = outerPlan((Plan *) node);
+ outerNode = outerPlanState(node);
for (;;)
{
- slot = ExecProcNode(outerNode, (Plan *) node);
+ slot = ExecProcNode(outerNode);
if (TupIsNull(slot))
break;
@@ -117,7 +115,7 @@ ExecMaterial(Material *node)
* Get the first or next tuple from tuplestore. Returns NULL if no
* more tuples.
*/
- slot = (TupleTableSlot *) matstate->csstate.cstate.cs_ResultTupleSlot;
+ slot = (TupleTableSlot *) node->ss.ps.ps_ResultTupleSlot;
heapTuple = tuplestore_getheaptuple(tuplestorestate,
ScanDirectionIsForward(dir),
&should_free);
@@ -129,23 +127,20 @@ ExecMaterial(Material *node)
* ExecInitMaterial
* ----------------------------------------------------------------
*/
-bool /* initialization status */
-ExecInitMaterial(Material *node, EState *estate, Plan *parent)
+MaterialState *
+ExecInitMaterial(Material *node, EState *estate)
{
MaterialState *matstate;
Plan *outerPlan;
/*
- * assign the node's execution state
- */
- node->plan.state = estate;
-
- /*
* create state structure
*/
matstate = makeNode(MaterialState);
+ matstate->ss.ps.plan = (Plan *) node;
+ matstate->ss.ps.state = estate;
+
matstate->tuplestorestate = NULL;
- node->matstate = matstate;
/*
* Miscellaneous initialization
@@ -161,24 +156,24 @@ ExecInitMaterial(Material *node, EState *estate, Plan *parent)
*
* material nodes only return tuples from their materialized relation.
*/
- ExecInitResultTupleSlot(estate, &matstate->csstate.cstate);
- ExecInitScanTupleSlot(estate, &matstate->csstate);
+ ExecInitResultTupleSlot(estate, &matstate->ss.ps);
+ ExecInitScanTupleSlot(estate, &matstate->ss);
/*
* initializes child nodes
*/
- outerPlan = outerPlan((Plan *) node);
- ExecInitNode(outerPlan, estate, (Plan *) node);
+ outerPlan = outerPlan(node);
+ outerPlanState(matstate) = ExecInitNode(outerPlan, estate);
/*
* initialize tuple type. no need to initialize projection info
* because this node doesn't do projections.
*/
- ExecAssignResultTypeFromOuterPlan((Plan *) node, &matstate->csstate.cstate);
- ExecAssignScanTypeFromOuterPlan((Plan *) node, &matstate->csstate);
- matstate->csstate.cstate.cs_ProjInfo = NULL;
+ ExecAssignResultTypeFromOuterPlan(&matstate->ss.ps);
+ ExecAssignScanTypeFromOuterPlan(&matstate->ss);
+ matstate->ss.ps.ps_ProjInfo = NULL;
- return TRUE;
+ return matstate;
}
int
@@ -194,33 +189,24 @@ ExecCountSlotsMaterial(Material *node)
* ----------------------------------------------------------------
*/
void
-ExecEndMaterial(Material *node)
+ExecEndMaterial(MaterialState *node)
{
- MaterialState *matstate;
- Plan *outerPlan;
-
/*
- * get info from the material state
+ * clean out the tuple table
*/
- matstate = node->matstate;
+ ExecClearTuple(node->ss.ss_ScanTupleSlot);
/*
* shut down the subplan
*/
- outerPlan = outerPlan((Plan *) node);
- ExecEndNode(outerPlan, (Plan *) node);
-
- /*
- * clean out the tuple table
- */
- ExecClearTuple(matstate->csstate.css_ScanTupleSlot);
+ ExecEndNode(outerPlanState(node));
/*
* Release tuplestore resources
*/
- if (matstate->tuplestorestate != NULL)
- tuplestore_end((Tuplestorestate *) matstate->tuplestorestate);
- matstate->tuplestorestate = NULL;
+ if (node->tuplestorestate != NULL)
+ tuplestore_end((Tuplestorestate *) node->tuplestorestate);
+ node->tuplestorestate = NULL;
}
/* ----------------------------------------------------------------
@@ -230,17 +216,15 @@ ExecEndMaterial(Material *node)
* ----------------------------------------------------------------
*/
void
-ExecMaterialMarkPos(Material *node)
+ExecMaterialMarkPos(MaterialState *node)
{
- MaterialState *matstate = node->matstate;
-
/*
* if we haven't materialized yet, just return.
*/
- if (!matstate->tuplestorestate)
+ if (!node->tuplestorestate)
return;
- tuplestore_markpos((Tuplestorestate *) matstate->tuplestorestate);
+ tuplestore_markpos((Tuplestorestate *) node->tuplestorestate);
}
/* ----------------------------------------------------------------
@@ -250,20 +234,18 @@ ExecMaterialMarkPos(Material *node)
* ----------------------------------------------------------------
*/
void
-ExecMaterialRestrPos(Material *node)
+ExecMaterialRestrPos(MaterialState *node)
{
- MaterialState *matstate = node->matstate;
-
/*
* if we haven't materialized yet, just return.
*/
- if (!matstate->tuplestorestate)
+ if (!node->tuplestorestate)
return;
/*
* restore the scan to the previously marked position
*/
- tuplestore_restorepos((Tuplestorestate *) matstate->tuplestorestate);
+ tuplestore_restorepos((Tuplestorestate *) node->tuplestorestate);
}
/* ----------------------------------------------------------------
@@ -273,19 +255,17 @@ ExecMaterialRestrPos(Material *node)
* ----------------------------------------------------------------
*/
void
-ExecMaterialReScan(Material *node, ExprContext *exprCtxt, Plan *parent)
+ExecMaterialReScan(MaterialState *node, ExprContext *exprCtxt)
{
- MaterialState *matstate = node->matstate;
-
/*
* If we haven't materialized yet, just return. If outerplan' chgParam
* is not NULL then it will be re-scanned by ExecProcNode, else - no
* reason to re-scan it at all.
*/
- if (!matstate->tuplestorestate)
+ if (!node->tuplestorestate)
return;
- ExecClearTuple(matstate->csstate.cstate.cs_ResultTupleSlot);
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
/*
* If subnode is to be rescanned then we forget previous stored
@@ -293,11 +273,11 @@ ExecMaterialReScan(Material *node, ExprContext *exprCtxt, Plan *parent)
*
* Otherwise we can just rewind and rescan the stored output.
*/
- if (((Plan *) node)->lefttree->chgParam != NULL)
+ if (((PlanState *) node)->lefttree->chgParam != NULL)
{
- tuplestore_end((Tuplestorestate *) matstate->tuplestorestate);
- matstate->tuplestorestate = NULL;
+ tuplestore_end((Tuplestorestate *) node->tuplestorestate);
+ node->tuplestorestate = NULL;
}
else
- tuplestore_rescan((Tuplestorestate *) matstate->tuplestorestate);
+ tuplestore_rescan((Tuplestorestate *) node->tuplestorestate);
}
diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c
index 4237618b0e5..171738dd349 100644
--- a/src/backend/executor/nodeMergejoin.c
+++ b/src/backend/executor/nodeMergejoin.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.51 2002/09/04 20:31:18 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.52 2002/12/05 15:50:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -340,10 +340,9 @@ ExecMergeTupleDump(MergeJoinState *mergestate)
* ----------------------------------------------------------------
*/
TupleTableSlot *
-ExecMergeJoin(MergeJoin *node)
+ExecMergeJoin(MergeJoinState *node)
{
EState *estate;
- MergeJoinState *mergestate;
ScanDirection direction;
List *innerSkipQual;
List *outerSkipQual;
@@ -352,9 +351,9 @@ ExecMergeJoin(MergeJoin *node)
List *otherqual;
bool qualResult;
bool compareResult;
- Plan *innerPlan;
+ PlanState *innerPlan;
TupleTableSlot *innerTupleSlot;
- Plan *outerPlan;
+ PlanState *outerPlan;
TupleTableSlot *outerTupleSlot;
ExprContext *econtext;
bool doFillOuter;
@@ -363,17 +362,16 @@ ExecMergeJoin(MergeJoin *node)
/*
* get information from node
*/
- mergestate = node->mergestate;
- estate = node->join.plan.state;
+ estate = node->js.ps.state;
direction = estate->es_direction;
- innerPlan = innerPlan((Plan *) node);
- outerPlan = outerPlan((Plan *) node);
- econtext = mergestate->jstate.cs_ExprContext;
+ innerPlan = innerPlanState(node);
+ outerPlan = outerPlanState(node);
+ econtext = node->js.ps.ps_ExprContext;
mergeclauses = node->mergeclauses;
- joinqual = node->join.joinqual;
- otherqual = node->join.plan.qual;
+ joinqual = node->js.joinqual;
+ otherqual = node->js.ps.qual;
- switch (node->join.jointype)
+ switch (node->js.jointype)
{
case JOIN_INNER:
doFillOuter = false;
@@ -393,7 +391,7 @@ ExecMergeJoin(MergeJoin *node)
break;
default:
elog(ERROR, "ExecMergeJoin: unsupported join type %d",
- (int) node->join.jointype);
+ (int) node->js.jointype);
doFillOuter = false; /* keep compiler quiet */
doFillInner = false;
break;
@@ -401,13 +399,13 @@ ExecMergeJoin(MergeJoin *node)
if (ScanDirectionIsForward(direction))
{
- outerSkipQual = mergestate->mj_OuterSkipQual;
- innerSkipQual = mergestate->mj_InnerSkipQual;
+ outerSkipQual = node->mj_OuterSkipQual;
+ innerSkipQual = node->mj_InnerSkipQual;
}
else
{
- outerSkipQual = mergestate->mj_InnerSkipQual;
- innerSkipQual = mergestate->mj_OuterSkipQual;
+ outerSkipQual = node->mj_InnerSkipQual;
+ innerSkipQual = node->mj_OuterSkipQual;
}
/*
@@ -415,16 +413,16 @@ ExecMergeJoin(MergeJoin *node)
* join tuple (because there is a function-returning-set in the
* projection expressions). If so, try to project another one.
*/
- if (mergestate->jstate.cs_TupFromTlist)
+ if (node->js.ps.ps_TupFromTlist)
{
TupleTableSlot *result;
ExprDoneCond isDone;
- result = ExecProject(mergestate->jstate.cs_ProjInfo, &isDone);
+ result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
if (isDone == ExprMultipleResult)
return result;
/* Done with that source tuple... */
- mergestate->jstate.cs_TupFromTlist = false;
+ node->js.ps.ps_TupFromTlist = false;
}
/*
@@ -444,9 +442,9 @@ ExecMergeJoin(MergeJoin *node)
* Note: The join states are highlighted with 32-* comments for
* improved readability.
*/
- MJ_dump(mergestate);
+ MJ_dump(node);
- switch (mergestate->mj_JoinState)
+ switch (node->mj_JoinState)
{
/*
* EXEC_MJ_INITIALIZE means that this is the first time
@@ -459,8 +457,8 @@ ExecMergeJoin(MergeJoin *node)
case EXEC_MJ_INITIALIZE:
MJ_printf("ExecMergeJoin: EXEC_MJ_INITIALIZE\n");
- outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
- mergestate->mj_OuterTupleSlot = outerTupleSlot;
+ outerTupleSlot = ExecProcNode(outerPlan);
+ node->mj_OuterTupleSlot = outerTupleSlot;
if (TupIsNull(outerTupleSlot))
{
MJ_printf("ExecMergeJoin: outer subplan is empty\n");
@@ -471,16 +469,16 @@ ExecMergeJoin(MergeJoin *node)
* inner tuples. We set MatchedInner = true to
* force the ENDOUTER state to advance inner.
*/
- mergestate->mj_JoinState = EXEC_MJ_ENDOUTER;
- mergestate->mj_MatchedInner = true;
+ node->mj_JoinState = EXEC_MJ_ENDOUTER;
+ node->mj_MatchedInner = true;
break;
}
/* Otherwise we're done. */
return NULL;
}
- innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);
- mergestate->mj_InnerTupleSlot = innerTupleSlot;
+ innerTupleSlot = ExecProcNode(innerPlan);
+ node->mj_InnerTupleSlot = innerTupleSlot;
if (TupIsNull(innerTupleSlot))
{
MJ_printf("ExecMergeJoin: inner subplan is empty\n");
@@ -493,8 +491,8 @@ ExecMergeJoin(MergeJoin *node)
* state to emit this tuple before advancing
* outer.
*/
- mergestate->mj_JoinState = EXEC_MJ_ENDINNER;
- mergestate->mj_MatchedOuter = false;
+ node->mj_JoinState = EXEC_MJ_ENDINNER;
+ node->mj_MatchedOuter = false;
break;
}
/* Otherwise we're done. */
@@ -505,7 +503,7 @@ ExecMergeJoin(MergeJoin *node)
* OK, we have the initial tuples. Begin by skipping
* unmatched inner tuples.
*/
- mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_BEGIN;
+ node->mj_JoinState = EXEC_MJ_SKIPINNER_BEGIN;
break;
/*
@@ -519,9 +517,9 @@ ExecMergeJoin(MergeJoin *node)
ExecMarkPos(innerPlan);
- MarkInnerTuple(mergestate->mj_InnerTupleSlot, mergestate);
+ MarkInnerTuple(node->mj_InnerTupleSlot, node);
- mergestate->mj_JoinState = EXEC_MJ_JOINTEST;
+ node->mj_JoinState = EXEC_MJ_JOINTEST;
break;
/*
@@ -538,18 +536,18 @@ ExecMergeJoin(MergeJoin *node)
ResetExprContext(econtext);
- outerTupleSlot = mergestate->mj_OuterTupleSlot;
+ outerTupleSlot = node->mj_OuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot;
- innerTupleSlot = mergestate->mj_InnerTupleSlot;
+ innerTupleSlot = node->mj_InnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot;
qualResult = ExecQual(mergeclauses, econtext, false);
MJ_DEBUG_QUAL(mergeclauses, qualResult);
if (qualResult)
- mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
+ node->mj_JoinState = EXEC_MJ_JOINTUPLES;
else
- mergestate->mj_JoinState = EXEC_MJ_NEXTOUTER;
+ node->mj_JoinState = EXEC_MJ_NEXTOUTER;
break;
/*
@@ -560,7 +558,7 @@ ExecMergeJoin(MergeJoin *node)
case EXEC_MJ_JOINTUPLES:
MJ_printf("ExecMergeJoin: EXEC_MJ_JOINTUPLES\n");
- mergestate->mj_JoinState = EXEC_MJ_NEXTINNER;
+ node->mj_JoinState = EXEC_MJ_NEXTINNER;
/*
* Check the extra qual conditions to see if we actually
@@ -582,8 +580,8 @@ ExecMergeJoin(MergeJoin *node)
if (qualResult)
{
- mergestate->mj_MatchedOuter = true;
- mergestate->mj_MatchedInner = true;
+ node->mj_MatchedOuter = true;
+ node->mj_MatchedInner = true;
qualResult = (otherqual == NIL ||
ExecQual(otherqual, econtext, false));
@@ -601,12 +599,12 @@ ExecMergeJoin(MergeJoin *node)
MJ_printf("ExecMergeJoin: returning tuple\n");
- result = ExecProject(mergestate->jstate.cs_ProjInfo,
+ result = ExecProject(node->js.ps.ps_ProjInfo,
&isDone);
if (isDone != ExprEndResult)
{
- mergestate->jstate.cs_TupFromTlist =
+ node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult);
return result;
}
@@ -625,20 +623,20 @@ ExecMergeJoin(MergeJoin *node)
case EXEC_MJ_NEXTINNER:
MJ_printf("ExecMergeJoin: EXEC_MJ_NEXTINNER\n");
- if (doFillInner && !mergestate->mj_MatchedInner)
+ if (doFillInner && !node->mj_MatchedInner)
{
/*
* Generate a fake join tuple with nulls for the outer
* tuple, and return it if it passes the non-join
* quals.
*/
- mergestate->mj_MatchedInner = true; /* do it only once */
+ node->mj_MatchedInner = true; /* do it only once */
ResetExprContext(econtext);
- outerTupleSlot = mergestate->mj_NullOuterTupleSlot;
+ outerTupleSlot = node->mj_NullOuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot;
- innerTupleSlot = mergestate->mj_InnerTupleSlot;
+ innerTupleSlot = node->mj_InnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot;
if (ExecQual(otherqual, econtext, false))
@@ -653,12 +651,12 @@ ExecMergeJoin(MergeJoin *node)
MJ_printf("ExecMergeJoin: returning fill tuple\n");
- result = ExecProject(mergestate->jstate.cs_ProjInfo,
+ result = ExecProject(node->js.ps.ps_ProjInfo,
&isDone);
if (isDone != ExprEndResult)
{
- mergestate->jstate.cs_TupFromTlist =
+ node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult);
return result;
}
@@ -668,15 +666,15 @@ ExecMergeJoin(MergeJoin *node)
/*
* now we get the next inner tuple, if any
*/
- innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);
- mergestate->mj_InnerTupleSlot = innerTupleSlot;
+ innerTupleSlot = ExecProcNode(innerPlan);
+ node->mj_InnerTupleSlot = innerTupleSlot;
MJ_DEBUG_PROC_NODE(innerTupleSlot);
- mergestate->mj_MatchedInner = false;
+ node->mj_MatchedInner = false;
if (TupIsNull(innerTupleSlot))
- mergestate->mj_JoinState = EXEC_MJ_NEXTOUTER;
+ node->mj_JoinState = EXEC_MJ_NEXTOUTER;
else
- mergestate->mj_JoinState = EXEC_MJ_JOINTEST;
+ node->mj_JoinState = EXEC_MJ_JOINTEST;
break;
/*-------------------------------------------
@@ -701,20 +699,20 @@ ExecMergeJoin(MergeJoin *node)
case EXEC_MJ_NEXTOUTER:
MJ_printf("ExecMergeJoin: EXEC_MJ_NEXTOUTER\n");
- if (doFillOuter && !mergestate->mj_MatchedOuter)
+ if (doFillOuter && !node->mj_MatchedOuter)
{
/*
* Generate a fake join tuple with nulls for the inner
* tuple, and return it if it passes the non-join
* quals.
*/
- mergestate->mj_MatchedOuter = true; /* do it only once */
+ node->mj_MatchedOuter = true; /* do it only once */
ResetExprContext(econtext);
- outerTupleSlot = mergestate->mj_OuterTupleSlot;
+ outerTupleSlot = node->mj_OuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot;
- innerTupleSlot = mergestate->mj_NullInnerTupleSlot;
+ innerTupleSlot = node->mj_NullInnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot;
if (ExecQual(otherqual, econtext, false))
@@ -729,12 +727,12 @@ ExecMergeJoin(MergeJoin *node)
MJ_printf("ExecMergeJoin: returning fill tuple\n");
- result = ExecProject(mergestate->jstate.cs_ProjInfo,
+ result = ExecProject(node->js.ps.ps_ProjInfo,
&isDone);
if (isDone != ExprEndResult)
{
- mergestate->jstate.cs_TupFromTlist =
+ node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult);
return result;
}
@@ -744,10 +742,10 @@ ExecMergeJoin(MergeJoin *node)
/*
* now we get the next outer tuple, if any
*/
- outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
- mergestate->mj_OuterTupleSlot = outerTupleSlot;
+ outerTupleSlot = ExecProcNode(outerPlan);
+ node->mj_OuterTupleSlot = outerTupleSlot;
MJ_DEBUG_PROC_NODE(outerTupleSlot);
- mergestate->mj_MatchedOuter = false;
+ node->mj_MatchedOuter = false;
/*
* if the outer tuple is null then we are done with the
@@ -756,21 +754,21 @@ ExecMergeJoin(MergeJoin *node)
if (TupIsNull(outerTupleSlot))
{
MJ_printf("ExecMergeJoin: end of outer subplan\n");
- innerTupleSlot = mergestate->mj_InnerTupleSlot;
+ innerTupleSlot = node->mj_InnerTupleSlot;
if (doFillInner && !TupIsNull(innerTupleSlot))
{
/*
* Need to emit right-join tuples for remaining
* inner tuples.
*/
- mergestate->mj_JoinState = EXEC_MJ_ENDOUTER;
+ node->mj_JoinState = EXEC_MJ_ENDOUTER;
break;
}
/* Otherwise we're done. */
return NULL;
}
- mergestate->mj_JoinState = EXEC_MJ_TESTOUTER;
+ node->mj_JoinState = EXEC_MJ_TESTOUTER;
break;
/*--------------------------------------------------------
@@ -816,9 +814,9 @@ ExecMergeJoin(MergeJoin *node)
*/
ResetExprContext(econtext);
- outerTupleSlot = mergestate->mj_OuterTupleSlot;
+ outerTupleSlot = node->mj_OuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot;
- innerTupleSlot = mergestate->mj_MarkedTupleSlot;
+ innerTupleSlot = node->mj_MarkedTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot;
qualResult = ExecQual(mergeclauses, econtext, false);
@@ -843,7 +841,7 @@ ExecMergeJoin(MergeJoin *node)
* the extra joinquals.
*/
ExecRestrPos(innerPlan);
- mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
+ node->mj_JoinState = EXEC_MJ_JOINTUPLES;
}
else
{
@@ -862,7 +860,7 @@ ExecMergeJoin(MergeJoin *node)
* larger than our marked inner tuples. So we're done.
* ----------------
*/
- innerTupleSlot = mergestate->mj_InnerTupleSlot;
+ innerTupleSlot = node->mj_InnerTupleSlot;
if (TupIsNull(innerTupleSlot))
{
if (doFillOuter)
@@ -871,7 +869,7 @@ ExecMergeJoin(MergeJoin *node)
* Need to emit left-join tuples for remaining
* outer tuples.
*/
- mergestate->mj_JoinState = EXEC_MJ_ENDINNER;
+ node->mj_JoinState = EXEC_MJ_ENDINNER;
break;
}
/* Otherwise we're done. */
@@ -879,7 +877,7 @@ ExecMergeJoin(MergeJoin *node)
}
/* continue on to skip outer tuples */
- mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER_BEGIN;
+ node->mj_JoinState = EXEC_MJ_SKIPOUTER_BEGIN;
}
break;
@@ -913,9 +911,9 @@ ExecMergeJoin(MergeJoin *node)
*/
ResetExprContext(econtext);
- outerTupleSlot = mergestate->mj_OuterTupleSlot;
+ outerTupleSlot = node->mj_OuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot;
- innerTupleSlot = mergestate->mj_InnerTupleSlot;
+ innerTupleSlot = node->mj_InnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot;
qualResult = ExecQual(mergeclauses, econtext, false);
@@ -925,13 +923,13 @@ ExecMergeJoin(MergeJoin *node)
{
ExecMarkPos(innerPlan);
- MarkInnerTuple(innerTupleSlot, mergestate);
+ MarkInnerTuple(innerTupleSlot, node);
- mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
+ node->mj_JoinState = EXEC_MJ_JOINTUPLES;
break;
}
- mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER_TEST;
+ node->mj_JoinState = EXEC_MJ_SKIPOUTER_TEST;
break;
case EXEC_MJ_SKIPOUTER_TEST:
@@ -940,9 +938,9 @@ ExecMergeJoin(MergeJoin *node)
/*
* ok, now test the skip qualification
*/
- outerTupleSlot = mergestate->mj_OuterTupleSlot;
+ outerTupleSlot = node->mj_OuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot;
- innerTupleSlot = mergestate->mj_InnerTupleSlot;
+ innerTupleSlot = node->mj_InnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot;
compareResult = MergeCompare(mergeclauses,
@@ -957,7 +955,7 @@ ExecMergeJoin(MergeJoin *node)
*/
if (compareResult)
{
- mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER_ADVANCE;
+ node->mj_JoinState = EXEC_MJ_SKIPOUTER_ADVANCE;
break;
}
@@ -973,9 +971,9 @@ ExecMergeJoin(MergeJoin *node)
MJ_DEBUG_MERGE_COMPARE(innerSkipQual, compareResult);
if (compareResult)
- mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_BEGIN;
+ node->mj_JoinState = EXEC_MJ_SKIPINNER_BEGIN;
else
- mergestate->mj_JoinState = EXEC_MJ_JOINMARK;
+ node->mj_JoinState = EXEC_MJ_JOINMARK;
break;
/*
@@ -985,20 +983,20 @@ ExecMergeJoin(MergeJoin *node)
case EXEC_MJ_SKIPOUTER_ADVANCE:
MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPOUTER_ADVANCE\n");
- if (doFillOuter && !mergestate->mj_MatchedOuter)
+ if (doFillOuter && !node->mj_MatchedOuter)
{
/*
* Generate a fake join tuple with nulls for the inner
* tuple, and return it if it passes the non-join
* quals.
*/
- mergestate->mj_MatchedOuter = true; /* do it only once */
+ node->mj_MatchedOuter = true; /* do it only once */
ResetExprContext(econtext);
- outerTupleSlot = mergestate->mj_OuterTupleSlot;
+ outerTupleSlot = node->mj_OuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot;
- innerTupleSlot = mergestate->mj_NullInnerTupleSlot;
+ innerTupleSlot = node->mj_NullInnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot;
if (ExecQual(otherqual, econtext, false))
@@ -1013,12 +1011,12 @@ ExecMergeJoin(MergeJoin *node)
MJ_printf("ExecMergeJoin: returning fill tuple\n");
- result = ExecProject(mergestate->jstate.cs_ProjInfo,
+ result = ExecProject(node->js.ps.ps_ProjInfo,
&isDone);
if (isDone != ExprEndResult)
{
- mergestate->jstate.cs_TupFromTlist =
+ node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult);
return result;
}
@@ -1028,10 +1026,10 @@ ExecMergeJoin(MergeJoin *node)
/*
* now we get the next outer tuple, if any
*/
- outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
- mergestate->mj_OuterTupleSlot = outerTupleSlot;
+ outerTupleSlot = ExecProcNode(outerPlan);
+ node->mj_OuterTupleSlot = outerTupleSlot;
MJ_DEBUG_PROC_NODE(outerTupleSlot);
- mergestate->mj_MatchedOuter = false;
+ node->mj_MatchedOuter = false;
/*
* if the outer tuple is null then we are done with the
@@ -1040,14 +1038,14 @@ ExecMergeJoin(MergeJoin *node)
if (TupIsNull(outerTupleSlot))
{
MJ_printf("ExecMergeJoin: end of outer subplan\n");
- innerTupleSlot = mergestate->mj_InnerTupleSlot;
+ innerTupleSlot = node->mj_InnerTupleSlot;
if (doFillInner && !TupIsNull(innerTupleSlot))
{
/*
* Need to emit right-join tuples for remaining
* inner tuples.
*/
- mergestate->mj_JoinState = EXEC_MJ_ENDOUTER;
+ node->mj_JoinState = EXEC_MJ_ENDOUTER;
break;
}
/* Otherwise we're done. */
@@ -1057,7 +1055,7 @@ ExecMergeJoin(MergeJoin *node)
/*
* otherwise test the new tuple against the skip qual.
*/
- mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER_TEST;
+ node->mj_JoinState = EXEC_MJ_SKIPOUTER_TEST;
break;
/*-----------------------------------------------------------
@@ -1090,9 +1088,9 @@ ExecMergeJoin(MergeJoin *node)
*/
ResetExprContext(econtext);
- outerTupleSlot = mergestate->mj_OuterTupleSlot;
+ outerTupleSlot = node->mj_OuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot;
- innerTupleSlot = mergestate->mj_InnerTupleSlot;
+ innerTupleSlot = node->mj_InnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot;
qualResult = ExecQual(mergeclauses, econtext, false);
@@ -1102,13 +1100,13 @@ ExecMergeJoin(MergeJoin *node)
{
ExecMarkPos(innerPlan);
- MarkInnerTuple(innerTupleSlot, mergestate);
+ MarkInnerTuple(innerTupleSlot, node);
- mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES;
+ node->mj_JoinState = EXEC_MJ_JOINTUPLES;
break;
}
- mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_TEST;
+ node->mj_JoinState = EXEC_MJ_SKIPINNER_TEST;
break;
case EXEC_MJ_SKIPINNER_TEST:
@@ -1117,9 +1115,9 @@ ExecMergeJoin(MergeJoin *node)
/*
* ok, now test the skip qualification
*/
- outerTupleSlot = mergestate->mj_OuterTupleSlot;
+ outerTupleSlot = node->mj_OuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot;
- innerTupleSlot = mergestate->mj_InnerTupleSlot;
+ innerTupleSlot = node->mj_InnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot;
compareResult = MergeCompare(mergeclauses,
@@ -1134,7 +1132,7 @@ ExecMergeJoin(MergeJoin *node)
*/
if (compareResult)
{
- mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_ADVANCE;
+ node->mj_JoinState = EXEC_MJ_SKIPINNER_ADVANCE;
break;
}
@@ -1150,9 +1148,9 @@ ExecMergeJoin(MergeJoin *node)
MJ_DEBUG_MERGE_COMPARE(outerSkipQual, compareResult);
if (compareResult)
- mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER_BEGIN;
+ node->mj_JoinState = EXEC_MJ_SKIPOUTER_BEGIN;
else
- mergestate->mj_JoinState = EXEC_MJ_JOINMARK;
+ node->mj_JoinState = EXEC_MJ_JOINMARK;
break;
/*
@@ -1162,20 +1160,20 @@ ExecMergeJoin(MergeJoin *node)
case EXEC_MJ_SKIPINNER_ADVANCE:
MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPINNER_ADVANCE\n");
- if (doFillInner && !mergestate->mj_MatchedInner)
+ if (doFillInner && !node->mj_MatchedInner)
{
/*
* Generate a fake join tuple with nulls for the outer
* tuple, and return it if it passes the non-join
* quals.
*/
- mergestate->mj_MatchedInner = true; /* do it only once */
+ node->mj_MatchedInner = true; /* do it only once */
ResetExprContext(econtext);
- outerTupleSlot = mergestate->mj_NullOuterTupleSlot;
+ outerTupleSlot = node->mj_NullOuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot;
- innerTupleSlot = mergestate->mj_InnerTupleSlot;
+ innerTupleSlot = node->mj_InnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot;
if (ExecQual(otherqual, econtext, false))
@@ -1190,12 +1188,12 @@ ExecMergeJoin(MergeJoin *node)
MJ_printf("ExecMergeJoin: returning fill tuple\n");
- result = ExecProject(mergestate->jstate.cs_ProjInfo,
+ result = ExecProject(node->js.ps.ps_ProjInfo,
&isDone);
if (isDone != ExprEndResult)
{
- mergestate->jstate.cs_TupFromTlist =
+ node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult);
return result;
}
@@ -1205,10 +1203,10 @@ ExecMergeJoin(MergeJoin *node)
/*
* now we get the next inner tuple, if any
*/
- innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);
- mergestate->mj_InnerTupleSlot = innerTupleSlot;
+ innerTupleSlot = ExecProcNode(innerPlan);
+ node->mj_InnerTupleSlot = innerTupleSlot;
MJ_DEBUG_PROC_NODE(innerTupleSlot);
- mergestate->mj_MatchedInner = false;
+ node->mj_MatchedInner = false;
/*
* if the inner tuple is null then we are done with the
@@ -1217,14 +1215,14 @@ ExecMergeJoin(MergeJoin *node)
if (TupIsNull(innerTupleSlot))
{
MJ_printf("ExecMergeJoin: end of inner subplan\n");
- outerTupleSlot = mergestate->mj_OuterTupleSlot;
+ outerTupleSlot = node->mj_OuterTupleSlot;
if (doFillOuter && !TupIsNull(outerTupleSlot))
{
/*
* Need to emit left-join tuples for remaining
* outer tuples.
*/
- mergestate->mj_JoinState = EXEC_MJ_ENDINNER;
+ node->mj_JoinState = EXEC_MJ_ENDINNER;
break;
}
/* Otherwise we're done. */
@@ -1234,7 +1232,7 @@ ExecMergeJoin(MergeJoin *node)
/*
* otherwise test the new tuple against the skip qual.
*/
- mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_TEST;
+ node->mj_JoinState = EXEC_MJ_SKIPINNER_TEST;
break;
/*
@@ -1247,20 +1245,20 @@ ExecMergeJoin(MergeJoin *node)
Assert(doFillInner);
- if (!mergestate->mj_MatchedInner)
+ if (!node->mj_MatchedInner)
{
/*
* Generate a fake join tuple with nulls for the outer
* tuple, and return it if it passes the non-join
* quals.
*/
- mergestate->mj_MatchedInner = true; /* do it only once */
+ node->mj_MatchedInner = true; /* do it only once */
ResetExprContext(econtext);
- outerTupleSlot = mergestate->mj_NullOuterTupleSlot;
+ outerTupleSlot = node->mj_NullOuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot;
- innerTupleSlot = mergestate->mj_InnerTupleSlot;
+ innerTupleSlot = node->mj_InnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot;
if (ExecQual(otherqual, econtext, false))
@@ -1275,12 +1273,12 @@ ExecMergeJoin(MergeJoin *node)
MJ_printf("ExecMergeJoin: returning fill tuple\n");
- result = ExecProject(mergestate->jstate.cs_ProjInfo,
+ result = ExecProject(node->js.ps.ps_ProjInfo,
&isDone);
if (isDone != ExprEndResult)
{
- mergestate->jstate.cs_TupFromTlist =
+ node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult);
return result;
}
@@ -1290,10 +1288,10 @@ ExecMergeJoin(MergeJoin *node)
/*
* now we get the next inner tuple, if any
*/
- innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);
- mergestate->mj_InnerTupleSlot = innerTupleSlot;
+ innerTupleSlot = ExecProcNode(innerPlan);
+ node->mj_InnerTupleSlot = innerTupleSlot;
MJ_DEBUG_PROC_NODE(innerTupleSlot);
- mergestate->mj_MatchedInner = false;
+ node->mj_MatchedInner = false;
if (TupIsNull(innerTupleSlot))
{
@@ -1314,20 +1312,20 @@ ExecMergeJoin(MergeJoin *node)
Assert(doFillOuter);
- if (!mergestate->mj_MatchedOuter)
+ if (!node->mj_MatchedOuter)
{
/*
* Generate a fake join tuple with nulls for the inner
* tuple, and return it if it passes the non-join
* quals.
*/
- mergestate->mj_MatchedOuter = true; /* do it only once */
+ node->mj_MatchedOuter = true; /* do it only once */
ResetExprContext(econtext);
- outerTupleSlot = mergestate->mj_OuterTupleSlot;
+ outerTupleSlot = node->mj_OuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot;
- innerTupleSlot = mergestate->mj_NullInnerTupleSlot;
+ innerTupleSlot = node->mj_NullInnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot;
if (ExecQual(otherqual, econtext, false))
@@ -1342,12 +1340,12 @@ ExecMergeJoin(MergeJoin *node)
MJ_printf("ExecMergeJoin: returning fill tuple\n");
- result = ExecProject(mergestate->jstate.cs_ProjInfo,
+ result = ExecProject(node->js.ps.ps_ProjInfo,
&isDone);
if (isDone != ExprEndResult)
{
- mergestate->jstate.cs_TupFromTlist =
+ node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult);
return result;
}
@@ -1357,10 +1355,10 @@ ExecMergeJoin(MergeJoin *node)
/*
* now we get the next outer tuple, if any
*/
- outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
- mergestate->mj_OuterTupleSlot = outerTupleSlot;
+ outerTupleSlot = ExecProcNode(outerPlan);
+ node->mj_OuterTupleSlot = outerTupleSlot;
MJ_DEBUG_PROC_NODE(outerTupleSlot);
- mergestate->mj_MatchedOuter = false;
+ node->mj_MatchedOuter = false;
if (TupIsNull(outerTupleSlot))
{
@@ -1377,7 +1375,7 @@ ExecMergeJoin(MergeJoin *node)
*/
default:
elog(WARNING, "ExecMergeJoin: invalid join state %d, aborting",
- mergestate->mj_JoinState);
+ node->mj_JoinState);
return NULL;
}
}
@@ -1385,14 +1383,10 @@ ExecMergeJoin(MergeJoin *node)
/* ----------------------------------------------------------------
* ExecInitMergeJoin
- *
- * old comments
- * Creates the run-time state information for the node and
- * sets the relation id to contain relevant decriptors.
* ----------------------------------------------------------------
*/
-bool
-ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
+MergeJoinState *
+ExecInitMergeJoin(MergeJoin *node, EState *estate)
{
MergeJoinState *mergestate;
@@ -1400,40 +1394,52 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
"initializing node");
/*
- * assign the node's execution state and get the range table and
- * direction from it
- */
- node->join.plan.state = estate;
-
- /*
- * create new merge state for node
+ * create state structure
*/
mergestate = makeNode(MergeJoinState);
- node->mergestate = mergestate;
+ mergestate->js.ps.plan = (Plan *) node;
+ mergestate->js.ps.state = estate;
/*
* Miscellaneous initialization
*
* create expression context for node
*/
- ExecAssignExprContext(estate, &mergestate->jstate);
+ ExecAssignExprContext(estate, &mergestate->js.ps);
+
+ /*
+ * initialize child expressions
+ */
+ mergestate->js.ps.targetlist = (List *)
+ ExecInitExpr((Node *) node->join.plan.targetlist,
+ (PlanState *) mergestate);
+ mergestate->js.ps.qual = (List *)
+ ExecInitExpr((Node *) node->join.plan.qual,
+ (PlanState *) mergestate);
+ mergestate->js.jointype = node->join.jointype;
+ mergestate->js.joinqual = (List *)
+ ExecInitExpr((Node *) node->join.joinqual,
+ (PlanState *) mergestate);
+ mergestate->mergeclauses = (List *)
+ ExecInitExpr((Node *) node->mergeclauses,
+ (PlanState *) mergestate);
/*
- * initialize subplans
+ * initialize child nodes
*/
- ExecInitNode(outerPlan((Plan *) node), estate, (Plan *) node);
- ExecInitNode(innerPlan((Plan *) node), estate, (Plan *) node);
+ outerPlanState(mergestate) = ExecInitNode(outerPlan(node), estate);
+ innerPlanState(mergestate) = ExecInitNode(innerPlan(node), estate);
#define MERGEJOIN_NSLOTS 4
/*
* tuple table initialization
*/
- ExecInitResultTupleSlot(estate, &mergestate->jstate);
+ ExecInitResultTupleSlot(estate, &mergestate->js.ps);
mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate);
ExecSetSlotDescriptor(mergestate->mj_MarkedTupleSlot,
- ExecGetTupType(innerPlan((Plan *) node)),
+ ExecGetTupType(innerPlanState(mergestate)),
false);
switch (node->join.jointype)
@@ -1443,12 +1449,12 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
case JOIN_LEFT:
mergestate->mj_NullInnerTupleSlot =
ExecInitNullTupleSlot(estate,
- ExecGetTupType(innerPlan((Plan *) node)));
+ ExecGetTupType(innerPlanState(mergestate)));
break;
case JOIN_RIGHT:
mergestate->mj_NullOuterTupleSlot =
ExecInitNullTupleSlot(estate,
- ExecGetTupType(outerPlan((Plan *) node)));
+ ExecGetTupType(outerPlanState(mergestate)));
/*
* Can't handle right or full join with non-nil extra
@@ -1460,10 +1466,10 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
case JOIN_FULL:
mergestate->mj_NullOuterTupleSlot =
ExecInitNullTupleSlot(estate,
- ExecGetTupType(outerPlan((Plan *) node)));
+ ExecGetTupType(outerPlanState(mergestate)));
mergestate->mj_NullInnerTupleSlot =
ExecInitNullTupleSlot(estate,
- ExecGetTupType(innerPlan((Plan *) node)));
+ ExecGetTupType(innerPlanState(mergestate)));
/*
* Can't handle right or full join with non-nil extra
@@ -1480,8 +1486,8 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
/*
* initialize tuple type and projection info
*/
- ExecAssignResultTypeFromTL((Plan *) node, &mergestate->jstate);
- ExecAssignProjectionInfo((Plan *) node, &mergestate->jstate);
+ ExecAssignResultTypeFromTL(&mergestate->js.ps);
+ ExecAssignProjectionInfo(&mergestate->js.ps);
/*
* form merge skip qualifications
@@ -1500,7 +1506,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
* initialize join state
*/
mergestate->mj_JoinState = EXEC_MJ_INITIALIZE;
- mergestate->jstate.cs_TupFromTlist = false;
+ mergestate->js.ps.ps_TupFromTlist = false;
mergestate->mj_MatchedOuter = false;
mergestate->mj_MatchedInner = false;
mergestate->mj_OuterTupleSlot = NULL;
@@ -1512,7 +1518,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
MJ1_printf("ExecInitMergeJoin: %s\n",
"node initialized");
- return TRUE;
+ return mergestate;
}
int
@@ -1531,65 +1537,52 @@ ExecCountSlotsMergeJoin(MergeJoin *node)
* ----------------------------------------------------------------
*/
void
-ExecEndMergeJoin(MergeJoin *node)
+ExecEndMergeJoin(MergeJoinState *node)
{
- MergeJoinState *mergestate;
-
MJ1_printf("ExecEndMergeJoin: %s\n",
"ending node processing");
/*
- * get state information from the node
- */
- mergestate = node->mergestate;
-
- /*
* Free the projection info and the scan attribute info
- *
- * Note: we don't ExecFreeResultType(mergestate) because the rule manager
- * depends on the tupType returned by ExecMain(). So for now, this is
- * freed at end-transaction time. -cim 6/2/91
*/
- ExecFreeProjectionInfo(&mergestate->jstate);
- ExecFreeExprContext(&mergestate->jstate);
+ ExecFreeProjectionInfo(&node->js.ps);
+ ExecFreeExprContext(&node->js.ps);
/*
* shut down the subplans
*/
- ExecEndNode((Plan *) innerPlan((Plan *) node), (Plan *) node);
- ExecEndNode((Plan *) outerPlan((Plan *) node), (Plan *) node);
+ ExecEndNode(innerPlanState(node));
+ ExecEndNode(outerPlanState(node));
/*
* clean out the tuple table
*/
- ExecClearTuple(mergestate->jstate.cs_ResultTupleSlot);
- ExecClearTuple(mergestate->mj_MarkedTupleSlot);
+ ExecClearTuple(node->js.ps.ps_ResultTupleSlot);
+ ExecClearTuple(node->mj_MarkedTupleSlot);
MJ1_printf("ExecEndMergeJoin: %s\n",
"node processing ended");
}
void
-ExecReScanMergeJoin(MergeJoin *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanMergeJoin(MergeJoinState *node, ExprContext *exprCtxt)
{
- MergeJoinState *mergestate = node->mergestate;
-
- ExecClearTuple(mergestate->mj_MarkedTupleSlot);
+ ExecClearTuple(node->mj_MarkedTupleSlot);
- mergestate->mj_JoinState = EXEC_MJ_INITIALIZE;
- mergestate->jstate.cs_TupFromTlist = false;
- mergestate->mj_MatchedOuter = false;
- mergestate->mj_MatchedInner = false;
- mergestate->mj_OuterTupleSlot = NULL;
- mergestate->mj_InnerTupleSlot = NULL;
+ node->mj_JoinState = EXEC_MJ_INITIALIZE;
+ node->js.ps.ps_TupFromTlist = false;
+ node->mj_MatchedOuter = false;
+ node->mj_MatchedInner = false;
+ node->mj_OuterTupleSlot = NULL;
+ node->mj_InnerTupleSlot = NULL;
/*
* if chgParam of subnodes is not null then plans will be re-scanned
* by first ExecProcNode.
*/
- if (((Plan *) node)->lefttree->chgParam == NULL)
- ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);
- if (((Plan *) node)->righttree->chgParam == NULL)
- ExecReScan(((Plan *) node)->righttree, exprCtxt, (Plan *) node);
+ if (((PlanState *) node)->lefttree->chgParam == NULL)
+ ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
+ if (((PlanState *) node)->righttree->chgParam == NULL)
+ ExecReScan(((PlanState *) node)->righttree, exprCtxt);
}
diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c
index 2bd26938fcc..ae2061aa969 100644
--- a/src/backend/executor/nodeNestloop.c
+++ b/src/backend/executor/nodeNestloop.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeNestloop.c,v 1.26 2002/06/20 20:29:28 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeNestloop.c,v 1.27 2002/12/05 15:50:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -57,11 +57,10 @@
* ----------------------------------------------------------------
*/
TupleTableSlot *
-ExecNestLoop(NestLoop *node)
+ExecNestLoop(NestLoopState *node)
{
- NestLoopState *nlstate;
- Plan *innerPlan;
- Plan *outerPlan;
+ PlanState *innerPlan;
+ PlanState *outerPlan;
TupleTableSlot *outerTupleSlot;
TupleTableSlot *innerTupleSlot;
List *joinqual;
@@ -73,17 +72,16 @@ ExecNestLoop(NestLoop *node)
*/
ENL1_printf("getting info from node");
- nlstate = node->nlstate;
- joinqual = node->join.joinqual;
- otherqual = node->join.plan.qual;
- outerPlan = outerPlan((Plan *) node);
- innerPlan = innerPlan((Plan *) node);
- econtext = nlstate->jstate.cs_ExprContext;
+ joinqual = node->js.joinqual;
+ otherqual = node->js.ps.qual;
+ outerPlan = outerPlanState(node);
+ innerPlan = innerPlanState(node);
+ econtext = node->js.ps.ps_ExprContext;
/*
* get the current outer tuple
*/
- outerTupleSlot = nlstate->jstate.cs_OuterTupleSlot;
+ outerTupleSlot = node->js.ps.ps_OuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot;
/*
@@ -91,16 +89,16 @@ ExecNestLoop(NestLoop *node)
* join tuple (because there is a function-returning-set in the
* projection expressions). If so, try to project another one.
*/
- if (nlstate->jstate.cs_TupFromTlist)
+ if (node->js.ps.ps_TupFromTlist)
{
TupleTableSlot *result;
ExprDoneCond isDone;
- result = ExecProject(nlstate->jstate.cs_ProjInfo, &isDone);
+ result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
if (isDone == ExprMultipleResult)
return result;
/* Done with that source tuple... */
- nlstate->jstate.cs_TupFromTlist = false;
+ node->js.ps.ps_TupFromTlist = false;
}
/*
@@ -122,10 +120,10 @@ ExecNestLoop(NestLoop *node)
* If we don't have an outer tuple, get the next one and reset the
* inner scan.
*/
- if (nlstate->nl_NeedNewOuter)
+ if (node->nl_NeedNewOuter)
{
ENL1_printf("getting new outer tuple");
- outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
+ outerTupleSlot = ExecProcNode(outerPlan);
/*
* if there are no more outer tuples, then the join is
@@ -138,10 +136,10 @@ ExecNestLoop(NestLoop *node)
}
ENL1_printf("saving new outer tuple information");
- nlstate->jstate.cs_OuterTupleSlot = outerTupleSlot;
+ node->js.ps.ps_OuterTupleSlot = outerTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot;
- nlstate->nl_NeedNewOuter = false;
- nlstate->nl_MatchedOuter = false;
+ node->nl_NeedNewOuter = false;
+ node->nl_MatchedOuter = false;
/*
* now rescan the inner plan
@@ -153,7 +151,7 @@ ExecNestLoop(NestLoop *node)
* outer tuple (e.g. in index scans), that's why we pass our
* expr context.
*/
- ExecReScan(innerPlan, econtext, (Plan *) node);
+ ExecReScan(innerPlan, econtext);
}
/*
@@ -161,17 +159,17 @@ ExecNestLoop(NestLoop *node)
*/
ENL1_printf("getting new inner tuple");
- innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node);
+ innerTupleSlot = ExecProcNode(innerPlan);
econtext->ecxt_innertuple = innerTupleSlot;
if (TupIsNull(innerTupleSlot))
{
ENL1_printf("no inner tuple, need new outer tuple");
- nlstate->nl_NeedNewOuter = true;
+ node->nl_NeedNewOuter = true;
- if (!nlstate->nl_MatchedOuter &&
- node->join.jointype == JOIN_LEFT)
+ if (!node->nl_MatchedOuter &&
+ node->js.jointype == JOIN_LEFT)
{
/*
* We are doing an outer join and there were no join
@@ -179,7 +177,7 @@ ExecNestLoop(NestLoop *node)
* tuple with nulls for the inner tuple, and return it if
* it passes the non-join quals.
*/
- econtext->ecxt_innertuple = nlstate->nl_NullInnerTupleSlot;
+ econtext->ecxt_innertuple = node->nl_NullInnerTupleSlot;
ENL1_printf("testing qualification for outer-join tuple");
@@ -195,11 +193,11 @@ ExecNestLoop(NestLoop *node)
ENL1_printf("qualification succeeded, projecting tuple");
- result = ExecProject(nlstate->jstate.cs_ProjInfo, &isDone);
+ result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
if (isDone != ExprEndResult)
{
- nlstate->jstate.cs_TupFromTlist =
+ node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult);
return result;
}
@@ -224,7 +222,7 @@ ExecNestLoop(NestLoop *node)
if (ExecQual(joinqual, econtext, false))
{
- nlstate->nl_MatchedOuter = true;
+ node->nl_MatchedOuter = true;
if (otherqual == NIL || ExecQual(otherqual, econtext, false))
{
@@ -238,11 +236,11 @@ ExecNestLoop(NestLoop *node)
ENL1_printf("qualification succeeded, projecting tuple");
- result = ExecProject(nlstate->jstate.cs_ProjInfo, &isDone);
+ result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
if (isDone != ExprEndResult)
{
- nlstate->jstate.cs_TupFromTlist =
+ node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult);
return result;
}
@@ -260,14 +258,10 @@ ExecNestLoop(NestLoop *node)
/* ----------------------------------------------------------------
* ExecInitNestLoop
- *
- * Creates the run-time state information for the nestloop node
- * produced by the planner and initailizes inner and outer relations
- * (child nodes).
* ----------------------------------------------------------------
*/
-bool
-ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent)
+NestLoopState *
+ExecInitNestLoop(NestLoop *node, EState *estate)
{
NestLoopState *nlstate;
@@ -275,35 +269,45 @@ ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent)
"initializing node");
/*
- * assign execution state to node
- */
- node->join.plan.state = estate;
-
- /*
- * create new nest loop state
+ * create state structure
*/
nlstate = makeNode(NestLoopState);
- node->nlstate = nlstate;
+ nlstate->js.ps.plan = (Plan *) node;
+ nlstate->js.ps.state = estate;
/*
* Miscellaneous initialization
*
* create expression context for node
*/
- ExecAssignExprContext(estate, &nlstate->jstate);
+ ExecAssignExprContext(estate, &nlstate->js.ps);
/*
- * now initialize children
+ * initialize child expressions
*/
- ExecInitNode(outerPlan((Plan *) node), estate, (Plan *) node);
- ExecInitNode(innerPlan((Plan *) node), estate, (Plan *) node);
+ nlstate->js.ps.targetlist = (List *)
+ ExecInitExpr((Node *) node->join.plan.targetlist,
+ (PlanState *) nlstate);
+ nlstate->js.ps.qual = (List *)
+ ExecInitExpr((Node *) node->join.plan.qual,
+ (PlanState *) nlstate);
+ nlstate->js.jointype = node->join.jointype;
+ nlstate->js.joinqual = (List *)
+ ExecInitExpr((Node *) node->join.joinqual,
+ (PlanState *) nlstate);
+
+ /*
+ * initialize child nodes
+ */
+ outerPlanState(nlstate) = ExecInitNode(outerPlan(node), estate);
+ innerPlanState(nlstate) = ExecInitNode(innerPlan(node), estate);
#define NESTLOOP_NSLOTS 2
/*
* tuple table initialization
*/
- ExecInitResultTupleSlot(estate, &nlstate->jstate);
+ ExecInitResultTupleSlot(estate, &nlstate->js.ps);
switch (node->join.jointype)
{
@@ -312,7 +316,7 @@ ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent)
case JOIN_LEFT:
nlstate->nl_NullInnerTupleSlot =
ExecInitNullTupleSlot(estate,
- ExecGetTupType(innerPlan((Plan *) node)));
+ ExecGetTupType(innerPlanState(nlstate)));
break;
default:
elog(ERROR, "ExecInitNestLoop: unsupported join type %d",
@@ -322,20 +326,21 @@ ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent)
/*
* initialize tuple type and projection info
*/
- ExecAssignResultTypeFromTL((Plan *) node, &nlstate->jstate);
- ExecAssignProjectionInfo((Plan *) node, &nlstate->jstate);
+ ExecAssignResultTypeFromTL(&nlstate->js.ps);
+ ExecAssignProjectionInfo(&nlstate->js.ps);
/*
* finally, wipe the current outer tuple clean.
*/
- nlstate->jstate.cs_OuterTupleSlot = NULL;
- nlstate->jstate.cs_TupFromTlist = false;
+ nlstate->js.ps.ps_OuterTupleSlot = NULL;
+ nlstate->js.ps.ps_TupFromTlist = false;
nlstate->nl_NeedNewOuter = true;
nlstate->nl_MatchedOuter = false;
NL1_printf("ExecInitNestLoop: %s\n",
"node initialized");
- return TRUE;
+
+ return nlstate;
}
int
@@ -353,38 +358,27 @@ ExecCountSlotsNestLoop(NestLoop *node)
* ----------------------------------------------------------------
*/
void
-ExecEndNestLoop(NestLoop *node)
+ExecEndNestLoop(NestLoopState *node)
{
- NestLoopState *nlstate;
-
NL1_printf("ExecEndNestLoop: %s\n",
"ending node processing");
/*
- * get info from the node
- */
- nlstate = node->nlstate;
-
- /*
* Free the projection info
- *
- * Note: we don't ExecFreeResultType(nlstate) because the rule manager
- * depends on the tupType returned by ExecMain(). So for now, this is
- * freed at end-transaction time. -cim 6/2/91
*/
- ExecFreeProjectionInfo(&nlstate->jstate);
- ExecFreeExprContext(&nlstate->jstate);
+ ExecFreeProjectionInfo(&node->js.ps);
+ ExecFreeExprContext(&node->js.ps);
/*
* close down subplans
*/
- ExecEndNode(outerPlan((Plan *) node), (Plan *) node);
- ExecEndNode(innerPlan((Plan *) node), (Plan *) node);
+ ExecEndNode(outerPlanState(node));
+ ExecEndNode(innerPlanState(node));
/*
* clean out the tuple table
*/
- ExecClearTuple(nlstate->jstate.cs_ResultTupleSlot);
+ ExecClearTuple(node->js.ps.ps_ResultTupleSlot);
NL1_printf("ExecEndNestLoop: %s\n",
"node processing ended");
@@ -395,10 +389,9 @@ ExecEndNestLoop(NestLoop *node)
* ----------------------------------------------------------------
*/
void
-ExecReScanNestLoop(NestLoop *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanNestLoop(NestLoopState *node, ExprContext *exprCtxt)
{
- NestLoopState *nlstate = node->nlstate;
- Plan *outerPlan = outerPlan((Plan *) node);
+ PlanState *outerPlan = outerPlanState(node);
/*
* If outerPlan->chgParam is not null then plan will be automatically
@@ -408,11 +401,11 @@ ExecReScanNestLoop(NestLoop *node, ExprContext *exprCtxt, Plan *parent)
* run-time keys...
*/
if (outerPlan->chgParam == NULL)
- ExecReScan(outerPlan, exprCtxt, (Plan *) node);
+ ExecReScan(outerPlan, exprCtxt);
/* let outerPlan to free its result tuple ... */
- nlstate->jstate.cs_OuterTupleSlot = NULL;
- nlstate->jstate.cs_TupFromTlist = false;
- nlstate->nl_NeedNewOuter = true;
- nlstate->nl_MatchedOuter = false;
+ node->js.ps.ps_OuterTupleSlot = NULL;
+ node->js.ps.ps_TupFromTlist = false;
+ node->nl_NeedNewOuter = true;
+ node->nl_MatchedOuter = false;
}
diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c
index d9d1608a81d..f14fd01c424 100644
--- a/src/backend/executor/nodeResult.c
+++ b/src/backend/executor/nodeResult.c
@@ -34,7 +34,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeResult.c,v 1.21 2002/06/20 20:29:28 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeResult.c,v 1.22 2002/12/05 15:50:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -60,34 +60,29 @@
* ----------------------------------------------------------------
*/
TupleTableSlot *
-ExecResult(Result *node)
+ExecResult(ResultState *node)
{
- ResultState *resstate;
TupleTableSlot *outerTupleSlot;
TupleTableSlot *resultSlot;
- Plan *outerPlan;
+ PlanState *outerPlan;
ExprContext *econtext;
ExprDoneCond isDone;
- /*
- * initialize the result node's state
- */
- resstate = node->resstate;
- econtext = resstate->cstate.cs_ExprContext;
+ econtext = node->ps.ps_ExprContext;
/*
* check constant qualifications like (2 > 1), if not already done
*/
- if (resstate->rs_checkqual)
+ if (node->rs_checkqual)
{
bool qualResult = ExecQual((List *) node->resconstantqual,
econtext,
false);
- resstate->rs_checkqual = false;
- if (qualResult == false)
+ node->rs_checkqual = false;
+ if (!qualResult)
{
- resstate->rs_done = true;
+ node->rs_done = true;
return NULL;
}
}
@@ -97,13 +92,13 @@ ExecResult(Result *node)
* scan tuple (because there is a function-returning-set in the
* projection expressions). If so, try to project another one.
*/
- if (resstate->cstate.cs_TupFromTlist)
+ if (node->ps.ps_TupFromTlist)
{
- resultSlot = ExecProject(resstate->cstate.cs_ProjInfo, &isDone);
+ resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
if (isDone == ExprMultipleResult)
return resultSlot;
/* Done with that source tuple... */
- resstate->cstate.cs_TupFromTlist = false;
+ node->ps.ps_TupFromTlist = false;
}
/*
@@ -119,9 +114,9 @@ ExecResult(Result *node)
* called, OR that we failed the constant qual check. Either way, now
* we are through.
*/
- while (!resstate->rs_done)
+ while (!node->rs_done)
{
- outerPlan = outerPlan(node);
+ outerPlan = outerPlanState(node);
if (outerPlan != NULL)
{
@@ -129,12 +124,12 @@ ExecResult(Result *node)
* retrieve tuples from the outer plan until there are no
* more.
*/
- outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
+ outerTupleSlot = ExecProcNode(outerPlan);
if (TupIsNull(outerTupleSlot))
return NULL;
- resstate->cstate.cs_OuterTupleSlot = outerTupleSlot;
+ node->ps.ps_OuterTupleSlot = outerTupleSlot;
/*
* XXX gross hack. use outer tuple as scan tuple for
@@ -149,7 +144,7 @@ ExecResult(Result *node)
* if we don't have an outer plan, then we are just generating
* the results from a constant target list. Do it only once.
*/
- resstate->rs_done = true;
+ node->rs_done = true;
}
/*
@@ -157,11 +152,11 @@ ExecResult(Result *node)
* unless the projection produces an empty set, in which case we
* must loop back to see if there are more outerPlan tuples.
*/
- resultSlot = ExecProject(resstate->cstate.cs_ProjInfo, &isDone);
+ resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
if (isDone != ExprEndResult)
{
- resstate->cstate.cs_TupFromTlist = (isDone == ExprMultipleResult);
+ node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
return resultSlot;
}
}
@@ -177,42 +172,51 @@ ExecResult(Result *node)
* (child nodes).
* ----------------------------------------------------------------
*/
-bool
-ExecInitResult(Result *node, EState *estate, Plan *parent)
+ResultState *
+ExecInitResult(Result *node, EState *estate)
{
ResultState *resstate;
/*
- * assign execution state to node
- */
- node->plan.state = estate;
-
- /*
- * create new ResultState for node
+ * create state structure
*/
resstate = makeNode(ResultState);
+ resstate->ps.plan = (Plan *) node;
+ resstate->ps.state = estate;
+
resstate->rs_done = false;
resstate->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
- node->resstate = resstate;
/*
* Miscellaneous initialization
*
* create expression context for node
*/
- ExecAssignExprContext(estate, &resstate->cstate);
+ ExecAssignExprContext(estate, &resstate->ps);
#define RESULT_NSLOTS 1
/*
* tuple table initialization
*/
- ExecInitResultTupleSlot(estate, &resstate->cstate);
+ ExecInitResultTupleSlot(estate, &resstate->ps);
/*
- * then initialize children
+ * initialize child expressions
*/
- ExecInitNode(outerPlan(node), estate, (Plan *) node);
+ resstate->ps.targetlist = (List *)
+ ExecInitExpr((Node *) node->plan.targetlist,
+ (PlanState *) resstate);
+ resstate->ps.qual = (List *)
+ ExecInitExpr((Node *) node->plan.qual,
+ (PlanState *) resstate);
+ resstate->resconstantqual = ExecInitExpr(node->resconstantqual,
+ (PlanState *) resstate);
+
+ /*
+ * initialize child nodes
+ */
+ outerPlanState(resstate) = ExecInitNode(outerPlan(node), estate);
/*
* we don't use inner plan
@@ -222,10 +226,10 @@ ExecInitResult(Result *node, EState *estate, Plan *parent)
/*
* initialize tuple type and projection info
*/
- ExecAssignResultTypeFromTL((Plan *) node, &resstate->cstate);
- ExecAssignProjectionInfo((Plan *) node, &resstate->cstate);
+ ExecAssignResultTypeFromTL(&resstate->ps);
+ ExecAssignProjectionInfo(&resstate->ps);
- return TRUE;
+ return resstate;
}
int
@@ -241,49 +245,37 @@ ExecCountSlotsResult(Result *node)
* ----------------------------------------------------------------
*/
void
-ExecEndResult(Result *node)
+ExecEndResult(ResultState *node)
{
- ResultState *resstate;
-
- resstate = node->resstate;
-
/*
* Free the projection info
- *
- * Note: we don't ExecFreeResultType(resstate) because the rule manager
- * depends on the tupType returned by ExecMain(). So for now, this is
- * freed at end-transaction time. -cim 6/2/91
*/
- ExecFreeProjectionInfo(&resstate->cstate);
- ExecFreeExprContext(&resstate->cstate);
+ ExecFreeProjectionInfo(&node->ps);
+ ExecFreeExprContext(&node->ps);
/*
- * shut down subplans
+ * clean out the tuple table
*/
- ExecEndNode(outerPlan(node), (Plan *) node);
+ ExecClearTuple(node->ps.ps_ResultTupleSlot);
/*
- * clean out the tuple table
+ * shut down subplans
*/
- ExecClearTuple(resstate->cstate.cs_ResultTupleSlot);
- pfree(resstate);
- node->resstate = NULL; /* XXX - new for us - er1p */
+ ExecEndNode(outerPlanState(node));
}
void
-ExecReScanResult(Result *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanResult(ResultState *node, ExprContext *exprCtxt)
{
- ResultState *resstate = node->resstate;
-
- resstate->rs_done = false;
- resstate->cstate.cs_TupFromTlist = false;
- resstate->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
+ node->rs_done = false;
+ node->ps.ps_TupFromTlist = false;
+ node->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
/*
* if chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode.
*/
- if (((Plan *) node)->lefttree &&
- ((Plan *) node)->lefttree->chgParam == NULL)
- ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node);
+ if (((PlanState *) node)->lefttree &&
+ ((PlanState *) node)->lefttree->chgParam == NULL)
+ ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
}
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index b6848d6c4b3..e19098fba23 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.38 2002/11/30 05:21:01 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.39 2002/12/05 15:50:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -29,9 +29,8 @@
#include "executor/nodeSeqscan.h"
#include "parser/parsetree.h"
-static Oid InitScanRelation(SeqScan *node, EState *estate,
- CommonScanState *scanstate);
-static TupleTableSlot *SeqNext(SeqScan *node);
+static void InitScanRelation(SeqScanState *node, EState *estate);
+static TupleTableSlot *SeqNext(SeqScanState *node);
/* ----------------------------------------------------------------
* Scan Support
@@ -44,11 +43,11 @@ static TupleTableSlot *SeqNext(SeqScan *node);
* ----------------------------------------------------------------
*/
static TupleTableSlot *
-SeqNext(SeqScan *node)
+SeqNext(SeqScanState *node)
{
HeapTuple tuple;
HeapScanDesc scandesc;
- CommonScanState *scanstate;
+ Index scanrelid;
EState *estate;
ScanDirection direction;
TupleTableSlot *slot;
@@ -56,11 +55,11 @@ SeqNext(SeqScan *node)
/*
* get information from the estate and scan state
*/
- estate = node->plan.state;
- scanstate = node->scanstate;
- scandesc = scanstate->css_currentScanDesc;
+ estate = node->ps.state;
+ scandesc = node->ss_currentScanDesc;
+ scanrelid = ((SeqScan *) node->ps.plan)->scanrelid;
direction = estate->es_direction;
- slot = scanstate->css_ScanTupleSlot;
+ slot = node->ss_ScanTupleSlot;
/*
* Check if we are evaluating PlanQual for tuple of this relation.
@@ -69,13 +68,13 @@ SeqNext(SeqScan *node)
* switching in Init/ReScan plan...
*/
if (estate->es_evTuple != NULL &&
- estate->es_evTuple[node->scanrelid - 1] != NULL)
+ estate->es_evTuple[scanrelid - 1] != NULL)
{
ExecClearTuple(slot);
- if (estate->es_evTupleNull[node->scanrelid - 1])
+ if (estate->es_evTupleNull[scanrelid - 1])
return slot; /* return empty slot */
- ExecStoreTuple(estate->es_evTuple[node->scanrelid - 1],
+ ExecStoreTuple(estate->es_evTuple[scanrelid - 1],
slot, InvalidBuffer, false);
/*
@@ -85,7 +84,7 @@ SeqNext(SeqScan *node)
*/
/* Flag for the next call that no more tuples */
- estate->es_evTupleNull[node->scanrelid - 1] = true;
+ estate->es_evTupleNull[scanrelid - 1] = true;
return (slot);
}
@@ -124,12 +123,12 @@ SeqNext(SeqScan *node)
*/
TupleTableSlot *
-ExecSeqScan(SeqScan *node)
+ExecSeqScan(SeqScanState *node)
{
/*
* use SeqNext as access method
*/
- return ExecScan(node, (ExecScanAccessMtd) SeqNext);
+ return ExecScan((ScanState *) node, (ExecScanAccessMtd) SeqNext);
}
/* ----------------------------------------------------------------
@@ -139,9 +138,8 @@ ExecSeqScan(SeqScan *node)
* subplans of scans.
* ----------------------------------------------------------------
*/
-static Oid
-InitScanRelation(SeqScan *node, EState *estate,
- CommonScanState *scanstate)
+static void
+InitScanRelation(SeqScanState *node, EState *estate)
{
Index relid;
List *rangeTable;
@@ -156,7 +154,7 @@ InitScanRelation(SeqScan *node, EState *estate,
*
* We acquire AccessShareLock for the duration of the scan.
*/
- relid = node->scanrelid;
+ relid = ((SeqScan *) node->ps.plan)->scanrelid;
rangeTable = estate->es_range_table;
rtentry = rt_fetch(relid, rangeTable);
reloid = rtentry->relid;
@@ -168,12 +166,10 @@ InitScanRelation(SeqScan *node, EState *estate,
0,
NULL);
- scanstate->css_currentRelation = currentRelation;
- scanstate->css_currentScanDesc = currentScanDesc;
+ node->ss_currentRelation = currentRelation;
+ node->ss_currentScanDesc = currentScanDesc;
- ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false);
-
- return reloid;
+ ExecAssignScanType(node, RelationGetDescr(currentRelation), false);
}
@@ -181,59 +177,64 @@ InitScanRelation(SeqScan *node, EState *estate,
* ExecInitSeqScan
* ----------------------------------------------------------------
*/
-bool
-ExecInitSeqScan(SeqScan *node, EState *estate, Plan *parent)
+SeqScanState *
+ExecInitSeqScan(SeqScan *node, EState *estate)
{
- CommonScanState *scanstate;
- Oid reloid;
+ SeqScanState *scanstate;
/*
* Once upon a time it was possible to have an outerPlan of a SeqScan,
* but not any more.
*/
- Assert(outerPlan((Plan *) node) == NULL);
- Assert(innerPlan((Plan *) node) == NULL);
-
- /*
- * assign the node's execution state
- */
- node->plan.state = estate;
+ Assert(outerPlan(node) == NULL);
+ Assert(innerPlan(node) == NULL);
/*
- * create new CommonScanState for node
+ * create state structure
*/
- scanstate = makeNode(CommonScanState);
- node->scanstate = scanstate;
+ scanstate = makeNode(SeqScanState);
+ scanstate->ps.plan = (Plan *) node;
+ scanstate->ps.state = estate;
/*
* Miscellaneous initialization
*
* create expression context for node
*/
- ExecAssignExprContext(estate, &scanstate->cstate);
+ ExecAssignExprContext(estate, &scanstate->ps);
+
+ /*
+ * initialize child expressions
+ */
+ scanstate->ps.targetlist = (List *)
+ ExecInitExpr((Node *) node->plan.targetlist,
+ (PlanState *) scanstate);
+ scanstate->ps.qual = (List *)
+ ExecInitExpr((Node *) node->plan.qual,
+ (PlanState *) scanstate);
#define SEQSCAN_NSLOTS 2
/*
* tuple table initialization
*/
- ExecInitResultTupleSlot(estate, &scanstate->cstate);
+ ExecInitResultTupleSlot(estate, &scanstate->ps);
ExecInitScanTupleSlot(estate, scanstate);
/*
* initialize scan relation
*/
- reloid = InitScanRelation(node, estate, scanstate);
+ InitScanRelation(scanstate, estate);
- scanstate->cstate.cs_TupFromTlist = false;
+ scanstate->ps.ps_TupFromTlist = false;
/*
* initialize tuple type
*/
- ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);
- ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate);
+ ExecAssignResultTypeFromTL(&scanstate->ps);
+ ExecAssignProjectionInfo(&scanstate->ps);
- return TRUE;
+ return scanstate;
}
int
@@ -251,28 +252,22 @@ ExecCountSlotsSeqScan(SeqScan *node)
* ----------------------------------------------------------------
*/
void
-ExecEndSeqScan(SeqScan *node)
+ExecEndSeqScan(SeqScanState *node)
{
- CommonScanState *scanstate;
Relation relation;
HeapScanDesc scanDesc;
/*
* get information from node
*/
- scanstate = node->scanstate;
- relation = scanstate->css_currentRelation;
- scanDesc = scanstate->css_currentScanDesc;
+ relation = node->ss_currentRelation;
+ scanDesc = node->ss_currentScanDesc;
/*
* Free the projection info and the scan attribute info
- *
- * Note: we don't ExecFreeResultType(scanstate) because the rule manager
- * depends on the tupType returned by ExecMain(). So for now, this is
- * freed at end-transaction time. -cim 6/2/91
*/
- ExecFreeProjectionInfo(&scanstate->cstate);
- ExecFreeExprContext(&scanstate->cstate);
+ ExecFreeProjectionInfo(&node->ps);
+ ExecFreeExprContext(&node->ps);
/*
* close heap scan
@@ -280,6 +275,12 @@ ExecEndSeqScan(SeqScan *node)
heap_endscan(scanDesc);
/*
+ * clean out the tuple table
+ */
+ ExecClearTuple(node->ps.ps_ResultTupleSlot);
+ ExecClearTuple(node->ss_ScanTupleSlot);
+
+ /*
* close the heap relation.
*
* Currently, we do not release the AccessShareLock acquired by
@@ -288,12 +289,6 @@ ExecEndSeqScan(SeqScan *node)
* locking, however.)
*/
heap_close(relation, NoLock);
-
- /*
- * clean out the tuple table
- */
- ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
- ExecClearTuple(scanstate->css_ScanTupleSlot);
}
/* ----------------------------------------------------------------
@@ -308,24 +303,24 @@ ExecEndSeqScan(SeqScan *node)
* ----------------------------------------------------------------
*/
void
-ExecSeqReScan(SeqScan *node, ExprContext *exprCtxt, Plan *parent)
+ExecSeqReScan(SeqScanState *node, ExprContext *exprCtxt)
{
- CommonScanState *scanstate;
EState *estate;
+ Index scanrelid;
HeapScanDesc scan;
- scanstate = node->scanstate;
- estate = node->plan.state;
+ estate = node->ps.state;
+ scanrelid = ((SeqScan *) node->ps.plan)->scanrelid;
/* If this is re-scanning of PlanQual ... */
if (estate->es_evTuple != NULL &&
- estate->es_evTuple[node->scanrelid - 1] != NULL)
+ estate->es_evTuple[scanrelid - 1] != NULL)
{
- estate->es_evTupleNull[node->scanrelid - 1] = false;
+ estate->es_evTupleNull[scanrelid - 1] = false;
return;
}
- scan = scanstate->css_currentScanDesc;
+ scan = node->ss_currentScanDesc;
heap_rescan(scan, /* scan desc */
NULL); /* new scan keys */
@@ -338,13 +333,11 @@ ExecSeqReScan(SeqScan *node, ExprContext *exprCtxt, Plan *parent)
* ----------------------------------------------------------------
*/
void
-ExecSeqMarkPos(SeqScan *node)
+ExecSeqMarkPos(SeqScanState *node)
{
- CommonScanState *scanstate;
HeapScanDesc scan;
- scanstate = node->scanstate;
- scan = scanstate->css_currentScanDesc;
+ scan = node->ss_currentScanDesc;
heap_markpos(scan);
}
@@ -355,12 +348,10 @@ ExecSeqMarkPos(SeqScan *node)
* ----------------------------------------------------------------
*/
void
-ExecSeqRestrPos(SeqScan *node)
+ExecSeqRestrPos(SeqScanState *node)
{
- CommonScanState *scanstate;
HeapScanDesc scan;
- scanstate = node->scanstate;
- scan = scanstate->css_currentScanDesc;
+ scan = node->ss_currentScanDesc;
heap_restrpos(scan);
}
diff --git a/src/backend/executor/nodeSetOp.c b/src/backend/executor/nodeSetOp.c
index 3d1cf2c8efa..a81a4a29d91 100644
--- a/src/backend/executor/nodeSetOp.c
+++ b/src/backend/executor/nodeSetOp.c
@@ -21,7 +21,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeSetOp.c,v 1.6 2002/06/20 20:29:28 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSetOp.c,v 1.7 2002/12/05 15:50:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -44,28 +44,27 @@
* ----------------------------------------------------------------
*/
TupleTableSlot * /* return: a tuple or NULL */
-ExecSetOp(SetOp *node)
+ExecSetOp(SetOpState *node)
{
- SetOpState *setopstate;
+ SetOp *plannode = (SetOp *) node->ps.plan;
TupleTableSlot *resultTupleSlot;
- Plan *outerPlan;
+ PlanState *outerPlan;
TupleDesc tupDesc;
/*
* get information from the node
*/
- setopstate = node->setopstate;
- outerPlan = outerPlan((Plan *) node);
- resultTupleSlot = setopstate->cstate.cs_ResultTupleSlot;
- tupDesc = ExecGetResultType(&setopstate->cstate);
+ outerPlan = outerPlanState(node);
+ resultTupleSlot = node->ps.ps_ResultTupleSlot;
+ tupDesc = ExecGetResultType(&node->ps);
/*
* If the previously-returned tuple needs to be returned more than
* once, keep returning it.
*/
- if (setopstate->numOutput > 0)
+ if (node->numOutput > 0)
{
- setopstate->numOutput--;
+ node->numOutput--;
return resultTupleSlot;
}
@@ -88,15 +87,15 @@ ExecSetOp(SetOp *node)
/*
* fetch a tuple from the outer subplan, unless we already did.
*/
- if (setopstate->cstate.cs_OuterTupleSlot == NULL &&
- !setopstate->subplan_done)
+ if (node->ps.ps_OuterTupleSlot == NULL &&
+ !node->subplan_done)
{
- setopstate->cstate.cs_OuterTupleSlot =
- ExecProcNode(outerPlan, (Plan *) node);
- if (TupIsNull(setopstate->cstate.cs_OuterTupleSlot))
- setopstate->subplan_done = true;
+ node->ps.ps_OuterTupleSlot =
+ ExecProcNode(outerPlan);
+ if (TupIsNull(node->ps.ps_OuterTupleSlot))
+ node->subplan_done = true;
}
- inputTupleSlot = setopstate->cstate.cs_OuterTupleSlot;
+ inputTupleSlot = node->ps.ps_OuterTupleSlot;
if (TupIsNull(resultTupleSlot))
{
@@ -104,18 +103,18 @@ ExecSetOp(SetOp *node)
* First of group: save a copy in result slot, and reset
* duplicate-counters for new group.
*/
- if (setopstate->subplan_done)
+ if (node->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;
+ node->numLeft = 0;
+ node->numRight = 0;
endOfGroup = false;
}
- else if (setopstate->subplan_done)
+ else if (node->subplan_done)
{
/*
* Reached end of input, so finish processing final group
@@ -131,9 +130,9 @@ ExecSetOp(SetOp *node)
if (execTuplesMatch(inputTupleSlot->val,
resultTupleSlot->val,
tupDesc,
- node->numCols, node->dupColIdx,
- setopstate->eqfunctions,
- setopstate->tempContext))
+ plannode->numCols, plannode->dupColIdx,
+ node->eqfunctions,
+ node->tempContext))
endOfGroup = false;
else
endOfGroup = true;
@@ -146,37 +145,37 @@ ExecSetOp(SetOp *node)
* Decide how many copies (if any) to emit. This logic is
* straight from the SQL92 specification.
*/
- switch (node->cmd)
+ switch (plannode->cmd)
{
case SETOPCMD_INTERSECT:
- if (setopstate->numLeft > 0 && setopstate->numRight > 0)
- setopstate->numOutput = 1;
+ if (node->numLeft > 0 && node->numRight > 0)
+ node->numOutput = 1;
else
- setopstate->numOutput = 0;
+ node->numOutput = 0;
break;
case SETOPCMD_INTERSECT_ALL:
- setopstate->numOutput =
- (setopstate->numLeft < setopstate->numRight) ?
- setopstate->numLeft : setopstate->numRight;
+ node->numOutput =
+ (node->numLeft < node->numRight) ?
+ node->numLeft : node->numRight;
break;
case SETOPCMD_EXCEPT:
- if (setopstate->numLeft > 0 && setopstate->numRight == 0)
- setopstate->numOutput = 1;
+ if (node->numLeft > 0 && node->numRight == 0)
+ node->numOutput = 1;
else
- setopstate->numOutput = 0;
+ node->numOutput = 0;
break;
case SETOPCMD_EXCEPT_ALL:
- setopstate->numOutput =
- (setopstate->numLeft < setopstate->numRight) ?
- 0 : (setopstate->numLeft - setopstate->numRight);
+ node->numOutput =
+ (node->numLeft < node->numRight) ?
+ 0 : (node->numLeft - node->numRight);
break;
default:
elog(ERROR, "ExecSetOp: bogus command code %d",
- (int) node->cmd);
+ (int) plannode->cmd);
break;
}
/* Fall out of for-loop if we have tuples to emit */
- if (setopstate->numOutput > 0)
+ if (node->numOutput > 0)
break;
/* Else flag that we have no current tuple, and loop around */
ExecClearTuple(resultTupleSlot);
@@ -191,16 +190,16 @@ ExecSetOp(SetOp *node)
bool isNull;
flag = DatumGetInt32(heap_getattr(inputTupleSlot->val,
- node->flagColIdx,
+ plannode->flagColIdx,
tupDesc,
&isNull));
Assert(!isNull);
if (flag)
- setopstate->numRight++;
+ node->numRight++;
else
- setopstate->numLeft++;
+ node->numLeft++;
/* Set flag to fetch a new input tuple, and loop around */
- setopstate->cstate.cs_OuterTupleSlot = NULL;
+ node->ps.ps_OuterTupleSlot = NULL;
}
}
@@ -208,8 +207,8 @@ ExecSetOp(SetOp *node)
* If we fall out of loop, then we need to emit at least one copy of
* resultTuple.
*/
- Assert(setopstate->numOutput > 0);
- setopstate->numOutput--;
+ Assert(node->numOutput > 0);
+ node->numOutput--;
return resultTupleSlot;
}
@@ -220,23 +219,19 @@ ExecSetOp(SetOp *node)
* the node's subplan.
* ----------------------------------------------------------------
*/
-bool /* return: initialization status */
-ExecInitSetOp(SetOp *node, EState *estate, Plan *parent)
+SetOpState *
+ExecInitSetOp(SetOp *node, EState *estate)
{
SetOpState *setopstate;
- Plan *outerPlan;
-
- /*
- * assign execution state to node
- */
- node->plan.state = estate;
/*
- * create new SetOpState for node
+ * create state structure
*/
setopstate = makeNode(SetOpState);
- node->setopstate = setopstate;
- setopstate->cstate.cs_OuterTupleSlot = NULL;
+ setopstate->ps.plan = (Plan *) node;
+ setopstate->ps.state = estate;
+
+ setopstate->ps.ps_OuterTupleSlot = NULL;
setopstate->subplan_done = false;
setopstate->numOutput = 0;
@@ -259,30 +254,29 @@ ExecInitSetOp(SetOp *node, EState *estate, Plan *parent)
/*
* Tuple table initialization
*/
- ExecInitResultTupleSlot(estate, &setopstate->cstate);
+ ExecInitResultTupleSlot(estate, &setopstate->ps);
/*
* then initialize outer plan
*/
- outerPlan = outerPlan((Plan *) node);
- ExecInitNode(outerPlan, estate, (Plan *) node);
+ outerPlanState(setopstate) = ExecInitNode(outerPlan(node), estate);
/*
* setop nodes do no projections, so initialize projection info for
* this node appropriately
*/
- ExecAssignResultTypeFromOuterPlan((Plan *) node, &setopstate->cstate);
- setopstate->cstate.cs_ProjInfo = NULL;
+ ExecAssignResultTypeFromOuterPlan(&setopstate->ps);
+ setopstate->ps.ps_ProjInfo = NULL;
/*
* Precompute fmgr lookup data for inner loop
*/
setopstate->eqfunctions =
- execTuplesMatchPrepare(ExecGetResultType(&setopstate->cstate),
+ execTuplesMatchPrepare(ExecGetResultType(&setopstate->ps),
node->numCols,
node->dupColIdx);
- return TRUE;
+ return setopstate;
}
int
@@ -301,34 +295,30 @@ ExecCountSlotsSetOp(SetOp *node)
* ----------------------------------------------------------------
*/
void
-ExecEndSetOp(SetOp *node)
+ExecEndSetOp(SetOpState *node)
{
- SetOpState *setopstate = node->setopstate;
-
- ExecEndNode(outerPlan((Plan *) node), (Plan *) node);
+ /* clean up tuple table */
+ ExecClearTuple(node->ps.ps_ResultTupleSlot);
+ node->ps.ps_OuterTupleSlot = NULL;
- MemoryContextDelete(setopstate->tempContext);
+ ExecEndNode(outerPlanState(node));
- /* clean up tuple table */
- ExecClearTuple(setopstate->cstate.cs_ResultTupleSlot);
- setopstate->cstate.cs_OuterTupleSlot = NULL;
+ MemoryContextDelete(node->tempContext);
}
void
-ExecReScanSetOp(SetOp *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanSetOp(SetOpState *node, ExprContext *exprCtxt)
{
- SetOpState *setopstate = node->setopstate;
-
- ExecClearTuple(setopstate->cstate.cs_ResultTupleSlot);
- setopstate->cstate.cs_OuterTupleSlot = NULL;
- setopstate->subplan_done = false;
- setopstate->numOutput = 0;
+ ExecClearTuple(node->ps.ps_ResultTupleSlot);
+ node->ps.ps_OuterTupleSlot = NULL;
+ node->subplan_done = false;
+ node->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);
+ if (((PlanState *) node)->lefttree->chgParam == NULL)
+ ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
}
diff --git a/src/backend/executor/nodeSort.c b/src/backend/executor/nodeSort.c
index 05f36427beb..e1b4db7a51d 100644
--- a/src/backend/executor/nodeSort.c
+++ b/src/backend/executor/nodeSort.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeSort.c,v 1.40 2002/11/13 00:39:47 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSort.c,v 1.41 2002/12/05 15:50:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -88,10 +88,9 @@ ExtractSortKeys(Sort *sortnode,
* ----------------------------------------------------------------
*/
TupleTableSlot *
-ExecSort(Sort *node)
+ExecSort(SortState *node)
{
EState *estate;
- SortState *sortstate;
ScanDirection dir;
Tuplesortstate *tuplesortstate;
HeapTuple heapTuple;
@@ -104,10 +103,9 @@ ExecSort(Sort *node)
SO1_printf("ExecSort: %s\n",
"entering routine");
- sortstate = node->sortstate;
- estate = node->plan.state;
+ estate = node->ss.ps.state;
dir = estate->es_direction;
- tuplesortstate = (Tuplesortstate *) sortstate->tuplesortstate;
+ tuplesortstate = (Tuplesortstate *) node->tuplesortstate;
/*
* If first time through, read all tuples from outer plan and pass
@@ -115,9 +113,10 @@ ExecSort(Sort *node)
* tuplesort.
*/
- if (!sortstate->sort_Done)
+ if (!node->sort_Done)
{
- Plan *outerNode;
+ Sort *plannode = (Sort *) node->ss.ps.plan;
+ PlanState *outerNode;
TupleDesc tupDesc;
Oid *sortOperators;
AttrNumber *attNums;
@@ -127,8 +126,7 @@ ExecSort(Sort *node)
/*
* Want to scan subplan in the forward direction while creating
- * the sorted data. (Does setting my direction actually affect
- * the subplan? I bet this is useless code...)
+ * the sorted data.
*/
estate->es_direction = ForwardScanDirection;
@@ -138,15 +136,15 @@ ExecSort(Sort *node)
SO1_printf("ExecSort: %s\n",
"calling tuplesort_begin");
- outerNode = outerPlan((Plan *) node);
+ outerNode = outerPlanState(node);
tupDesc = ExecGetTupType(outerNode);
- ExtractSortKeys(node, &sortOperators, &attNums);
+ ExtractSortKeys(plannode, &sortOperators, &attNums);
- tuplesortstate = tuplesort_begin_heap(tupDesc, node->keycount,
+ tuplesortstate = tuplesort_begin_heap(tupDesc, plannode->keycount,
sortOperators, attNums,
true /* randomAccess */ );
- sortstate->tuplesortstate = (void *) tuplesortstate;
+ node->tuplesortstate = (void *) tuplesortstate;
pfree(sortOperators);
pfree(attNums);
@@ -157,7 +155,7 @@ ExecSort(Sort *node)
for (;;)
{
- slot = ExecProcNode(outerNode, (Plan *) node);
+ slot = ExecProcNode(outerNode);
if (TupIsNull(slot))
break;
@@ -178,12 +176,12 @@ ExecSort(Sort *node)
/*
* make sure the tuple descriptor is up to date (is this needed?)
*/
- ExecAssignResultType(&sortstate->csstate.cstate, tupDesc, false);
+ ExecAssignResultType(&node->ss.ps, tupDesc, false);
/*
* finally set the sorted flag to true
*/
- sortstate->sort_Done = true;
+ node->sort_Done = true;
SO1_printf("ExecSort: %s\n", "sorting done");
}
@@ -198,7 +196,7 @@ ExecSort(Sort *node)
ScanDirectionIsForward(dir),
&should_free);
- slot = sortstate->csstate.cstate.cs_ResultTupleSlot;
+ slot = node->ss.ps.ps_ResultTupleSlot;
return ExecStoreTuple(heapTuple, slot, InvalidBuffer, should_free);
}
@@ -209,29 +207,24 @@ ExecSort(Sort *node)
* produced by the planner and initailizes its outer subtree.
* ----------------------------------------------------------------
*/
-bool
-ExecInitSort(Sort *node, EState *estate, Plan *parent)
+SortState *
+ExecInitSort(Sort *node, EState *estate)
{
SortState *sortstate;
- Plan *outerPlan;
SO1_printf("ExecInitSort: %s\n",
"initializing sort node");
/*
- * assign the node's execution state
- */
- node->plan.state = estate;
-
- /*
* create state structure
*/
sortstate = makeNode(SortState);
+ sortstate->ss.ps.plan = (Plan *) node;
+ sortstate->ss.ps.state = estate;
+
sortstate->sort_Done = false;
sortstate->tuplesortstate = NULL;
- node->sortstate = sortstate;
-
/*
* Miscellaneous initialization
*
@@ -246,27 +239,26 @@ ExecInitSort(Sort *node, EState *estate, Plan *parent)
*
* sort nodes only return scan tuples from their sorted relation.
*/
- ExecInitResultTupleSlot(estate, &sortstate->csstate.cstate);
- ExecInitScanTupleSlot(estate, &sortstate->csstate);
+ ExecInitResultTupleSlot(estate, &sortstate->ss.ps);
+ ExecInitScanTupleSlot(estate, &sortstate->ss);
/*
* initializes child nodes
*/
- outerPlan = outerPlan((Plan *) node);
- ExecInitNode(outerPlan, estate, (Plan *) node);
+ outerPlanState(sortstate) = ExecInitNode(outerPlan(node), estate);
/*
* initialize tuple type. no need to initialize projection info
* because this node doesn't do projections.
*/
- ExecAssignResultTypeFromOuterPlan((Plan *) node, &sortstate->csstate.cstate);
- ExecAssignScanTypeFromOuterPlan((Plan *) node, &sortstate->csstate);
- sortstate->csstate.cstate.cs_ProjInfo = NULL;
+ ExecAssignResultTypeFromOuterPlan(&sortstate->ss.ps);
+ ExecAssignScanTypeFromOuterPlan(&sortstate->ss);
+ sortstate->ss.ps.ps_ProjInfo = NULL;
SO1_printf("ExecInitSort: %s\n",
"sort node initialized");
- return TRUE;
+ return sortstate;
}
int
@@ -282,39 +274,27 @@ ExecCountSlotsSort(Sort *node)
* ----------------------------------------------------------------
*/
void
-ExecEndSort(Sort *node)
+ExecEndSort(SortState *node)
{
- SortState *sortstate;
- Plan *outerPlan;
-
- /*
- * get info from the sort state
- */
SO1_printf("ExecEndSort: %s\n",
"shutting down sort node");
- sortstate = node->sortstate;
-
/*
- * shut down the subplan
+ * clean out the tuple table
*/
- outerPlan = outerPlan((Plan *) node);
- ExecEndNode(outerPlan, (Plan *) node);
+ ExecClearTuple(node->ss.ss_ScanTupleSlot);
/*
- * clean out the tuple table
+ * shut down the subplan
*/
- ExecClearTuple(sortstate->csstate.css_ScanTupleSlot);
+ ExecEndNode(outerPlanState(node));
/*
* Release tuplesort resources
*/
- if (sortstate->tuplesortstate != NULL)
- tuplesort_end((Tuplesortstate *) sortstate->tuplesortstate);
- sortstate->tuplesortstate = NULL;
-
- pfree(sortstate);
- node->sortstate = NULL;
+ if (node->tuplesortstate != NULL)
+ tuplesort_end((Tuplesortstate *) node->tuplesortstate);
+ node->tuplesortstate = NULL;
SO1_printf("ExecEndSort: %s\n",
"sort node shutdown");
@@ -327,17 +307,15 @@ ExecEndSort(Sort *node)
* ----------------------------------------------------------------
*/
void
-ExecSortMarkPos(Sort *node)
+ExecSortMarkPos(SortState *node)
{
- SortState *sortstate = node->sortstate;
-
/*
* if we haven't sorted yet, just return
*/
- if (!sortstate->sort_Done)
+ if (!node->sort_Done)
return;
- tuplesort_markpos((Tuplesortstate *) sortstate->tuplesortstate);
+ tuplesort_markpos((Tuplesortstate *) node->tuplesortstate);
}
/* ----------------------------------------------------------------
@@ -347,36 +325,32 @@ ExecSortMarkPos(Sort *node)
* ----------------------------------------------------------------
*/
void
-ExecSortRestrPos(Sort *node)
+ExecSortRestrPos(SortState *node)
{
- SortState *sortstate = node->sortstate;
-
/*
* if we haven't sorted yet, just return.
*/
- if (!sortstate->sort_Done)
+ if (!node->sort_Done)
return;
/*
* restore the scan to the previously marked position
*/
- tuplesort_restorepos((Tuplesortstate *) sortstate->tuplesortstate);
+ tuplesort_restorepos((Tuplesortstate *) node->tuplesortstate);
}
void
-ExecReScanSort(Sort *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanSort(SortState *node, ExprContext *exprCtxt)
{
- SortState *sortstate = node->sortstate;
-
/*
* If we haven't sorted yet, just return. If outerplan' chgParam is
* not NULL then it will be re-scanned by ExecProcNode, else - no
* reason to re-scan it at all.
*/
- if (!sortstate->sort_Done)
+ if (!node->sort_Done)
return;
- ExecClearTuple(sortstate->csstate.cstate.cs_ResultTupleSlot);
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
/*
* If subnode is to be rescanned then we forget previous sort results;
@@ -384,12 +358,12 @@ ExecReScanSort(Sort *node, ExprContext *exprCtxt, Plan *parent)
*
* Otherwise we can just rewind and rescan the sorted output.
*/
- if (((Plan *) node)->lefttree->chgParam != NULL)
+ if (((PlanState *) node)->lefttree->chgParam != NULL)
{
- sortstate->sort_Done = false;
- tuplesort_end((Tuplesortstate *) sortstate->tuplesortstate);
- sortstate->tuplesortstate = NULL;
+ node->sort_Done = false;
+ tuplesort_end((Tuplesortstate *) node->tuplesortstate);
+ node->tuplesortstate = NULL;
}
else
- tuplesort_rescan((Tuplesortstate *) sortstate->tuplesortstate);
+ tuplesort_rescan((Tuplesortstate *) node->tuplesortstate);
}
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index 73ff6370fbc..195634c1289 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.34 2002/11/26 03:01:57 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.35 2002/12/05 15:50:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -27,14 +27,15 @@
/* ----------------------------------------------------------------
* ExecSubPlan(node)
- *
* ----------------------------------------------------------------
*/
Datum
-ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull)
+ExecSubPlan(SubPlanState *node, List *pvar,
+ ExprContext *econtext, bool *isNull)
{
- Plan *plan = node->plan;
- SubLink *sublink = node->sublink;
+ PlanState *planstate = node->planstate;
+ SubPlan *subplan = (SubPlan *) node->ps.plan;
+ SubLink *sublink = subplan->sublink;
SubLinkType subLinkType = sublink->subLinkType;
bool useor = sublink->useor;
MemoryContext oldcontext;
@@ -49,15 +50,15 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull)
*/
oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
- if (node->setParam != NIL)
+ if (subplan->setParam != NIL)
elog(ERROR, "ExecSubPlan: can't set parent params from subquery");
/*
* Set Params of this plan from parent plan correlation Vars
*/
- if (node->parParam != NIL)
+ if (subplan->parParam != NIL)
{
- foreach(lst, node->parParam)
+ foreach(lst, subplan->parParam)
{
ParamExecData *prm;
@@ -69,11 +70,12 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull)
NULL);
pvar = lnext(pvar);
}
- plan->chgParam = nconc(plan->chgParam, listCopy(node->parParam));
+ planstate->chgParam = nconc(planstate->chgParam,
+ listCopy(subplan->parParam));
}
Assert(pvar == NIL);
- ExecReScan(plan, NULL, NULL);
+ ExecReScan(planstate, NULL);
/*
* For all sublink types except EXPR_SUBLINK, the result is boolean as
@@ -96,9 +98,9 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull)
result = BoolGetDatum(subLinkType == ALL_SUBLINK);
*isNull = false;
- for (slot = ExecProcNode(plan, NULL);
+ for (slot = ExecProcNode(planstate);
!TupIsNull(slot);
- slot = ExecProcNode(plan, NULL))
+ slot = ExecProcNode(planstate))
{
HeapTuple tup = slot->val;
TupleDesc tdesc = slot->ttc_tupleDescriptor;
@@ -283,13 +285,37 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull)
/* ----------------------------------------------------------------
* ExecInitSubPlan
- *
* ----------------------------------------------------------------
*/
-bool
-ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent)
+SubPlanState *
+ExecInitSubPlan(SubPlan *node, EState *estate)
{
- EState *sp_estate = CreateExecutorState();
+ SubPlanState *subplanstate;
+ EState *sp_estate;
+
+ /*
+ * Do access checking on the rangetable entries in the subquery.
+ * Here, we assume the subquery is a SELECT.
+ */
+ ExecCheckRTPerms(node->rtable, CMD_SELECT);
+
+ /*
+ * create state structure
+ */
+ subplanstate = makeNode(SubPlanState);
+ subplanstate->ps.plan = (Plan *) node;
+ subplanstate->ps.state = estate;
+
+ subplanstate->needShutdown = false;
+ subplanstate->curTuple = NULL;
+
+ /* XXX temporary hack */
+ node->pstate = subplanstate;
+
+ /*
+ * create an EState for the subplan
+ */
+ sp_estate = CreateExecutorState();
sp_estate->es_range_table = node->rtable;
sp_estate->es_param_list_info = estate->es_param_list_info;
@@ -297,14 +323,14 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent)
sp_estate->es_tupleTable =
ExecCreateTupleTable(ExecCountSlotsNode(node->plan) + 10);
sp_estate->es_snapshot = estate->es_snapshot;
+ sp_estate->es_instrument = estate->es_instrument;
- node->needShutdown = false;
- node->curTuple = NULL;
-
- if (!ExecInitNode(node->plan, sp_estate, parent))
- return false;
+ /*
+ * Start up the subplan
+ */
+ subplanstate->planstate = ExecInitNode(node->plan, sp_estate);
- node->needShutdown = true; /* now we need to shutdown the subplan */
+ subplanstate->needShutdown = true; /* now we need to shutdown the subplan */
/*
* If this plan is un-correlated or undirect correlated one and want
@@ -318,7 +344,7 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent)
{
ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
- prm->execPlan = node;
+ prm->execPlan = subplanstate;
}
/*
@@ -328,7 +354,7 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent)
*/
}
- return true;
+ return subplanstate;
}
/* ----------------------------------------------------------------
@@ -345,10 +371,12 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent)
* ----------------------------------------------------------------
*/
void
-ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
+ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
{
- Plan *plan = node->plan;
- SubLink *sublink = node->sublink;
+ PlanState *planstate = node->planstate;
+ SubPlan *subplan = (SubPlan *) node->ps.plan;
+ SubLink *sublink = subplan->sublink;
+ EState *estate = node->ps.state;
MemoryContext oldcontext;
TupleTableSlot *slot;
List *lst;
@@ -364,12 +392,12 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
sublink->subLinkType == ALL_SUBLINK)
elog(ERROR, "ExecSetParamPlan: ANY/ALL subselect unsupported");
- if (plan->chgParam != NULL)
- ExecReScan(plan, NULL, NULL);
+ if (planstate->chgParam != NULL)
+ ExecReScan(planstate, NULL);
- for (slot = ExecProcNode(plan, NULL);
+ for (slot = ExecProcNode(planstate);
!TupIsNull(slot);
- slot = ExecProcNode(plan, NULL))
+ slot = ExecProcNode(planstate))
{
HeapTuple tup = slot->val;
TupleDesc tdesc = slot->ttc_tupleDescriptor;
@@ -377,7 +405,7 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
if (sublink->subLinkType == EXISTS_SUBLINK)
{
- ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(node->setParam)]);
+ ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(subplan->setParam)]);
prm->execPlan = NULL;
prm->value = BoolGetDatum(true);
@@ -404,9 +432,9 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
heap_freetuple(node->curTuple);
node->curTuple = tup;
- foreach(lst, node->setParam)
+ foreach(lst, subplan->setParam)
{
- ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(lst)]);
+ ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
prm->execPlan = NULL;
prm->value = heap_getattr(tup, i, tdesc, &(prm->isnull));
@@ -418,7 +446,7 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
{
if (sublink->subLinkType == EXISTS_SUBLINK)
{
- ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(node->setParam)]);
+ ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(subplan->setParam)]);
prm->execPlan = NULL;
prm->value = BoolGetDatum(false);
@@ -426,9 +454,9 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
}
else
{
- foreach(lst, node->setParam)
+ foreach(lst, subplan->setParam)
{
- ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(lst)]);
+ ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
prm->execPlan = NULL;
prm->value = (Datum) 0;
@@ -437,9 +465,9 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
}
}
- if (plan->extParam == NULL) /* un-correlated ... */
+ if (planstate->plan->extParam == NULL) /* un-correlated ... */
{
- ExecEndNode(plan, NULL);
+ ExecEndNode(planstate);
node->needShutdown = false;
}
@@ -451,11 +479,11 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
* ----------------------------------------------------------------
*/
void
-ExecEndSubPlan(SubPlan *node)
+ExecEndSubPlan(SubPlanState *node)
{
if (node->needShutdown)
{
- ExecEndNode(node->plan, NULL);
+ ExecEndNode(node->planstate);
node->needShutdown = false;
}
if (node->curTuple)
@@ -466,33 +494,34 @@ ExecEndSubPlan(SubPlan *node)
}
void
-ExecReScanSetParamPlan(SubPlan *node, Plan *parent)
+ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent)
{
- Plan *plan = node->plan;
+ PlanState *planstate = node->planstate;
+ SubPlan *subplan = (SubPlan *) node->ps.plan;
+ EState *estate = node->ps.state;
List *lst;
- if (node->parParam != NULL)
+ if (subplan->parParam != NULL)
elog(ERROR, "ExecReScanSetParamPlan: direct correlated subquery unsupported, yet");
- if (node->setParam == NULL)
+ if (subplan->setParam == NULL)
elog(ERROR, "ExecReScanSetParamPlan: setParam list is NULL");
- if (plan->extParam == NULL)
+ if (planstate->plan->extParam == NULL)
elog(ERROR, "ExecReScanSetParamPlan: extParam list of plan is NULL");
/*
* Don't actual re-scan: ExecSetParamPlan does re-scan if
- * node->plan->chgParam is not NULL... ExecReScan (plan, NULL, NULL);
+ * subplan->plan->chgParam is not NULL... ExecReScan (planstate, NULL);
*/
/*
* Mark this subplan's output parameters as needing recalculation
*/
- foreach(lst, node->setParam)
+ foreach(lst, subplan->setParam)
{
- ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(lst)]);
+ ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
prm->execPlan = node;
}
- parent->chgParam = nconc(parent->chgParam, listCopy(node->setParam));
-
+ parent->chgParam = nconc(parent->chgParam, listCopy(subplan->setParam));
}
diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c
index 982dd0236ca..ba0ed8635b7 100644
--- a/src/backend/executor/nodeSubqueryscan.c
+++ b/src/backend/executor/nodeSubqueryscan.c
@@ -12,7 +12,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.13 2002/06/20 20:29:28 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.14 2002/12/05 15:50:33 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -35,7 +35,7 @@
#include "parser/parsetree.h"
#include "tcop/pquery.h"
-static TupleTableSlot *SubqueryNext(SubqueryScan *node);
+static TupleTableSlot *SubqueryNext(SubqueryScanState *node);
/* ----------------------------------------------------------------
* Scan Support
@@ -48,9 +48,8 @@ static TupleTableSlot *SubqueryNext(SubqueryScan *node);
* ----------------------------------------------------------------
*/
static TupleTableSlot *
-SubqueryNext(SubqueryScan *node)
+SubqueryNext(SubqueryScanState *node)
{
- SubqueryScanState *subquerystate;
EState *estate;
ScanDirection direction;
TupleTableSlot *slot;
@@ -58,8 +57,7 @@ SubqueryNext(SubqueryScan *node)
/*
* get information from the estate and scan state
*/
- estate = node->scan.plan.state;
- subquerystate = (SubqueryScanState *) node->scan.scanstate;
+ estate = node->ss.ps.state;
direction = estate->es_direction;
/*
@@ -70,11 +68,11 @@ SubqueryNext(SubqueryScan *node)
/*
* get the next tuple from the sub-query
*/
- subquerystate->sss_SubEState->es_direction = direction;
+ node->sss_SubEState->es_direction = direction;
- slot = ExecProcNode(node->subplan, (Plan *) node);
+ slot = ExecProcNode(node->subplan);
- subquerystate->csstate.css_ScanTupleSlot = slot;
+ node->ss.ss_ScanTupleSlot = slot;
return slot;
}
@@ -90,20 +88,20 @@ SubqueryNext(SubqueryScan *node)
*/
TupleTableSlot *
-ExecSubqueryScan(SubqueryScan *node)
+ExecSubqueryScan(SubqueryScanState *node)
{
/*
* use SubqueryNext as access method
*/
- return ExecScan(&node->scan, (ExecScanAccessMtd) SubqueryNext);
+ return ExecScan(&node->ss, (ExecScanAccessMtd) SubqueryNext);
}
/* ----------------------------------------------------------------
* ExecInitSubqueryScan
* ----------------------------------------------------------------
*/
-bool
-ExecInitSubqueryScan(SubqueryScan *node, EState *estate, Plan *parent)
+SubqueryScanState *
+ExecInitSubqueryScan(SubqueryScan *node, EState *estate)
{
SubqueryScanState *subquerystate;
RangeTblEntry *rte;
@@ -112,33 +110,39 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, Plan *parent)
/*
* SubqueryScan should not have any "normal" children.
*/
- Assert(outerPlan((Plan *) node) == NULL);
- Assert(innerPlan((Plan *) node) == NULL);
+ Assert(outerPlan(node) == NULL);
+ Assert(innerPlan(node) == NULL);
/*
- * assign the node's execution state
- */
- node->scan.plan.state = estate;
-
- /*
- * create new SubqueryScanState for node
+ * create state structure
*/
subquerystate = makeNode(SubqueryScanState);
- node->scan.scanstate = (CommonScanState *) subquerystate;
+ subquerystate->ss.ps.plan = (Plan *) node;
+ subquerystate->ss.ps.state = estate;
/*
* Miscellaneous initialization
*
* create expression context for node
*/
- ExecAssignExprContext(estate, &subquerystate->csstate.cstate);
+ ExecAssignExprContext(estate, &subquerystate->ss.ps);
+
+ /*
+ * initialize child expressions
+ */
+ subquerystate->ss.ps.targetlist = (List *)
+ ExecInitExpr((Node *) node->scan.plan.targetlist,
+ (PlanState *) subquerystate);
+ subquerystate->ss.ps.qual = (List *)
+ ExecInitExpr((Node *) node->scan.plan.qual,
+ (PlanState *) subquerystate);
#define SUBQUERYSCAN_NSLOTS 1
/*
* tuple table initialization
*/
- ExecInitResultTupleSlot(estate, &subquerystate->csstate.cstate);
+ ExecInitResultTupleSlot(estate, &subquerystate->ss.ps);
/*
* initialize subquery
@@ -157,20 +161,20 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, Plan *parent)
sp_estate->es_tupleTable =
ExecCreateTupleTable(ExecCountSlotsNode(node->subplan) + 10);
sp_estate->es_snapshot = estate->es_snapshot;
+ sp_estate->es_instrument = estate->es_instrument;
- if (!ExecInitNode(node->subplan, sp_estate, (Plan *) node))
- return false;
+ subquerystate->subplan = ExecInitNode(node->subplan, sp_estate);
- subquerystate->csstate.css_ScanTupleSlot = NULL;
- subquerystate->csstate.cstate.cs_TupFromTlist = false;
+ subquerystate->ss.ss_ScanTupleSlot = NULL;
+ subquerystate->ss.ps.ps_TupFromTlist = false;
/*
* initialize tuple type
*/
- ExecAssignResultTypeFromTL((Plan *) node, &subquerystate->csstate.cstate);
- ExecAssignProjectionInfo((Plan *) node, &subquerystate->csstate.cstate);
+ ExecAssignResultTypeFromTL(&subquerystate->ss.ps);
+ ExecAssignProjectionInfo(&subquerystate->ss.ps);
- return TRUE;
+ return subquerystate;
}
int
@@ -191,42 +195,31 @@ ExecCountSlotsSubqueryScan(SubqueryScan *node)
* ----------------------------------------------------------------
*/
void
-ExecEndSubqueryScan(SubqueryScan *node)
+ExecEndSubqueryScan(SubqueryScanState *node)
{
- SubqueryScanState *subquerystate;
-
/*
- * get information from node
+ * Free the projection info and the scan attribute info
*/
- subquerystate = (SubqueryScanState *) node->scan.scanstate;
+ ExecFreeProjectionInfo(&node->ss.ps);
+ ExecFreeExprContext(&node->ss.ps);
/*
- * Free the projection info and the scan attribute info
- *
- * Note: we don't ExecFreeResultType(subquerystate) because the rule
- * manager depends on the tupType returned by ExecMain(). So for now,
- * this is freed at end-transaction time. -cim 6/2/91
+ * clean out the upper tuple table
*/
- ExecFreeProjectionInfo(&subquerystate->csstate.cstate);
- ExecFreeExprContext(&subquerystate->csstate.cstate);
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
/*
* close down subquery
*/
- ExecEndNode(node->subplan, (Plan *) node);
+ ExecEndNode(node->subplan);
/*
* clean up subquery's tuple table
*/
- subquerystate->csstate.css_ScanTupleSlot = NULL;
- ExecDropTupleTable(subquerystate->sss_SubEState->es_tupleTable, true);
+ node->ss.ss_ScanTupleSlot = NULL;
+ ExecDropTupleTable(node->sss_SubEState->es_tupleTable, true);
/* XXX we seem to be leaking the sub-EState... */
-
- /*
- * clean out the upper tuple table
- */
- ExecClearTuple(subquerystate->csstate.cstate.cs_ResultTupleSlot);
}
/* ----------------------------------------------------------------
@@ -236,27 +229,25 @@ ExecEndSubqueryScan(SubqueryScan *node)
* ----------------------------------------------------------------
*/
void
-ExecSubqueryReScan(SubqueryScan *node, ExprContext *exprCtxt, Plan *parent)
+ExecSubqueryReScan(SubqueryScanState *node, ExprContext *exprCtxt)
{
- SubqueryScanState *subquerystate;
EState *estate;
- subquerystate = (SubqueryScanState *) node->scan.scanstate;
- estate = node->scan.plan.state;
+ estate = node->ss.ps.state;
/*
* ExecReScan doesn't know about my subplan, so I have to do
* changed-parameter signaling myself.
*/
- if (node->scan.plan.chgParam != NULL)
- SetChangedParamList(node->subplan, node->scan.plan.chgParam);
+ if (node->ss.ps.chgParam != NULL)
+ SetChangedParamList(node->subplan, node->ss.ps.chgParam);
/*
* if chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode.
*/
if (node->subplan->chgParam == NULL)
- ExecReScan(node->subplan, NULL, (Plan *) node);
+ ExecReScan(node->subplan, NULL);
- subquerystate->csstate.css_ScanTupleSlot = NULL;
+ node->ss.ss_ScanTupleSlot = NULL;
}
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index 0fb7c6df4a8..53b3c26d35a 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.27 2002/11/30 05:21:01 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.28 2002/12/05 15:50:34 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -30,7 +30,7 @@
#include "parser/parsetree.h"
static int TidListCreate(List *, ExprContext *, ItemPointerData[]);
-static TupleTableSlot *TidNext(TidScan *node);
+static TupleTableSlot *TidNext(TidScanState *node);
static int
TidListCreate(List *evalList, ExprContext *econtext, ItemPointerData tidList[])
@@ -65,19 +65,17 @@ TidListCreate(List *evalList, ExprContext *econtext, ItemPointerData tidList[])
* ----------------------------------------------------------------
*/
static TupleTableSlot *
-TidNext(TidScan *node)
+TidNext(TidScanState *node)
{
EState *estate;
- CommonScanState *scanstate;
- TidScanState *tidstate;
ScanDirection direction;
Snapshot snapshot;
Relation heapRelation;
HeapTuple tuple;
TupleTableSlot *slot;
+ Index scanrelid;
Buffer buffer = InvalidBuffer;
int numTids;
-
bool bBackward;
int tidNumber;
ItemPointerData *tidList;
@@ -85,15 +83,14 @@ TidNext(TidScan *node)
/*
* extract necessary information from tid scan node
*/
- estate = node->scan.plan.state;
+ estate = node->ss.ps.state;
direction = estate->es_direction;
snapshot = estate->es_snapshot;
- scanstate = node->scan.scanstate;
- tidstate = node->tidstate;
- heapRelation = scanstate->css_currentRelation;
- numTids = tidstate->tss_NumTids;
- tidList = tidstate->tss_TidList;
- slot = scanstate->css_ScanTupleSlot;
+ heapRelation = node->ss.ss_currentRelation;
+ numTids = node->tss_NumTids;
+ tidList = node->tss_TidList;
+ slot = node->ss.ss_ScanTupleSlot;
+ scanrelid = ((TidScan *) node->ss.ps.plan)->scan.scanrelid;
/*
* Check if we are evaluating PlanQual for tuple of this relation.
@@ -102,10 +99,10 @@ TidNext(TidScan *node)
* switching in Init/ReScan plan...
*/
if (estate->es_evTuple != NULL &&
- estate->es_evTuple[node->scan.scanrelid - 1] != NULL)
+ estate->es_evTuple[scanrelid - 1] != NULL)
{
ExecClearTuple(slot);
- if (estate->es_evTupleNull[node->scan.scanrelid - 1])
+ if (estate->es_evTupleNull[scanrelid - 1])
return slot; /* return empty slot */
/*
@@ -113,15 +110,15 @@ TidNext(TidScan *node)
* list? In runtime-key case this is not certain, is it?
*/
- ExecStoreTuple(estate->es_evTuple[node->scan.scanrelid - 1],
+ ExecStoreTuple(estate->es_evTuple[scanrelid - 1],
slot, InvalidBuffer, false);
/* Flag for the next call that no more tuples */
- estate->es_evTupleNull[node->scan.scanrelid - 1] = true;
+ estate->es_evTupleNull[scanrelid - 1] = true;
return (slot);
}
- tuple = &(tidstate->tss_htup);
+ tuple = &(node->tss_htup);
/*
* ok, now that we have what we need, fetch an tid tuple. if scanning
@@ -131,26 +128,26 @@ TidNext(TidScan *node)
bBackward = ScanDirectionIsBackward(direction);
if (bBackward)
{
- tidNumber = numTids - tidstate->tss_TidPtr - 1;
+ tidNumber = numTids - node->tss_TidPtr - 1;
if (tidNumber < 0)
{
tidNumber = 0;
- tidstate->tss_TidPtr = numTids - 1;
+ node->tss_TidPtr = numTids - 1;
}
}
else
{
- if ((tidNumber = tidstate->tss_TidPtr) < 0)
+ if ((tidNumber = node->tss_TidPtr) < 0)
{
tidNumber = 0;
- tidstate->tss_TidPtr = 0;
+ node->tss_TidPtr = 0;
}
}
while (tidNumber < numTids)
{
bool slot_is_valid = false;
- tuple->t_self = tidList[tidstate->tss_TidPtr];
+ tuple->t_self = tidList[node->tss_TidPtr];
if (heap_fetch(heapRelation, snapshot, tuple, &buffer, false, NULL))
{
bool prev_matches = false;
@@ -181,7 +178,7 @@ TidNext(TidScan *node)
* do this by passing the tuple through ExecQual and look for
* failure with all previous qualifications.
*/
- for (prev_tid = 0; prev_tid < tidstate->tss_TidPtr;
+ for (prev_tid = 0; prev_tid < node->tss_TidPtr;
prev_tid++)
{
if (ItemPointerEquals(&tidList[prev_tid], &tuple->t_self))
@@ -197,9 +194,9 @@ TidNext(TidScan *node)
}
tidNumber++;
if (bBackward)
- tidstate->tss_TidPtr--;
+ node->tss_TidPtr--;
else
- tidstate->tss_TidPtr++;
+ node->tss_TidPtr++;
if (slot_is_valid)
return slot;
}
@@ -231,12 +228,12 @@ TidNext(TidScan *node)
* ----------------------------------------------------------------
*/
TupleTableSlot *
-ExecTidScan(TidScan *node)
+ExecTidScan(TidScanState *node)
{
/*
* use TidNext as access method
*/
- return ExecScan(&node->scan, (ExecScanAccessMtd) TidNext);
+ return ExecScan(&node->ss, (ExecScanAccessMtd) TidNext);
}
/* ----------------------------------------------------------------
@@ -244,42 +241,30 @@ ExecTidScan(TidScan *node)
* ----------------------------------------------------------------
*/
void
-ExecTidReScan(TidScan *node, ExprContext *exprCtxt, Plan *parent)
+ExecTidReScan(TidScanState *node, ExprContext *exprCtxt)
{
EState *estate;
- TidScanState *tidstate;
ItemPointerData *tidList;
+ Index scanrelid;
- estate = node->scan.plan.state;
- tidstate = node->tidstate;
- tidList = tidstate->tss_TidList;
+ estate = node->ss.ps.state;
+ tidList = node->tss_TidList;
+ scanrelid = ((TidScan *) node->ss.ps.plan)->scan.scanrelid;
/* If we are being passed an outer tuple, save it for runtime key calc */
if (exprCtxt != NULL)
- node->scan.scanstate->cstate.cs_ExprContext->ecxt_outertuple =
+ node->ss.ps.ps_ExprContext->ecxt_outertuple =
exprCtxt->ecxt_outertuple;
- /* do runtime calc of target TIDs, if needed */
- if (node->needRescan)
- tidstate->tss_NumTids =
- TidListCreate(node->tideval,
- node->scan.scanstate->cstate.cs_ExprContext,
- tidList);
-
/* If this is re-scanning of PlanQual ... */
if (estate->es_evTuple != NULL &&
- estate->es_evTuple[node->scan.scanrelid - 1] != NULL)
+ estate->es_evTuple[scanrelid - 1] != NULL)
{
- estate->es_evTupleNull[node->scan.scanrelid - 1] = false;
+ estate->es_evTupleNull[scanrelid - 1] = false;
return;
}
- tidstate->tss_TidPtr = -1;
-
- /*
- * perhaps return something meaningful
- */
- return;
+ node->tss_TidPtr = -1;
}
/* ----------------------------------------------------------------
@@ -290,18 +275,13 @@ ExecTidReScan(TidScan *node, ExprContext *exprCtxt, Plan *parent)
* ----------------------------------------------------------------
*/
void
-ExecEndTidScan(TidScan *node)
+ExecEndTidScan(TidScanState *node)
{
- CommonScanState *scanstate;
- TidScanState *tidstate;
-
/*
* extract information from the node
*/
- scanstate = node->scan.scanstate;
- tidstate = node->tidstate;
- if (tidstate && tidstate->tss_TidList)
- pfree(tidstate->tss_TidList);
+ if (node && node->tss_TidList)
+ pfree(node->tss_TidList);
/*
* Free the projection info and the scan attribute info
@@ -310,8 +290,14 @@ ExecEndTidScan(TidScan *node)
* depends on the tupType returned by ExecMain(). So for now, this is
* freed at end-transaction time. -cim 6/2/91
*/
- ExecFreeProjectionInfo(&scanstate->cstate);
- ExecFreeExprContext(&scanstate->cstate);
+ ExecFreeProjectionInfo(&node->ss.ps);
+ ExecFreeExprContext(&node->ss.ps);
+
+ /*
+ * clear out tuple table slots
+ */
+ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
+ ExecClearTuple(node->ss.ss_ScanTupleSlot);
/*
* close the heap relation.
@@ -320,13 +306,7 @@ ExecEndTidScan(TidScan *node)
* ExecInitTidScan. This lock should be held till end of transaction.
* (There is a faction that considers this too much locking, however.)
*/
- heap_close(scanstate->css_currentRelation, NoLock);
-
- /*
- * clear out tuple table slots
- */
- ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
- ExecClearTuple(scanstate->css_ScanTupleSlot);
+ heap_close(node->ss.ss_currentRelation, NoLock);
}
/* ----------------------------------------------------------------
@@ -337,12 +317,9 @@ ExecEndTidScan(TidScan *node)
* ----------------------------------------------------------------
*/
void
-ExecTidMarkPos(TidScan *node)
+ExecTidMarkPos(TidScanState *node)
{
- TidScanState *tidstate;
-
- tidstate = node->tidstate;
- tidstate->tss_MarkTidPtr = tidstate->tss_TidPtr;
+ node->tss_MarkTidPtr = node->tss_TidPtr;
}
/* ----------------------------------------------------------------
@@ -355,12 +332,9 @@ ExecTidMarkPos(TidScan *node)
* ----------------------------------------------------------------
*/
void
-ExecTidRestrPos(TidScan *node)
+ExecTidRestrPos(TidScanState *node)
{
- TidScanState *tidstate;
-
- tidstate = node->tidstate;
- tidstate->tss_TidPtr = tidstate->tss_MarkTidPtr;
+ node->tss_TidPtr = node->tss_MarkTidPtr;
}
/* ----------------------------------------------------------------
@@ -374,11 +348,10 @@ ExecTidRestrPos(TidScan *node)
* estate: the execution state initialized in InitPlan.
* ----------------------------------------------------------------
*/
-bool
-ExecInitTidScan(TidScan *node, EState *estate, Plan *parent)
+TidScanState *
+ExecInitTidScan(TidScan *node, EState *estate)
{
TidScanState *tidstate;
- CommonScanState *scanstate;
ItemPointerData *tidList;
int numTids;
int tidPtr;
@@ -390,56 +363,50 @@ ExecInitTidScan(TidScan *node, EState *estate, Plan *parent)
List *execParam = NIL;
/*
- * assign execution state to node
+ * create state structure
*/
- node->scan.plan.state = estate;
+ tidstate = makeNode(TidScanState);
+ tidstate->ss.ps.plan = (Plan *) node;
+ tidstate->ss.ps.state = estate;
/*
- * Part 1) initialize scan state
+ * Miscellaneous initialization
*
- * create new CommonScanState for node
+ * create expression context for node
*/
- scanstate = makeNode(CommonScanState);
- node->scan.scanstate = scanstate;
+ ExecAssignExprContext(estate, &tidstate->ss.ps);
/*
- * Miscellaneous initialization
- *
- * create expression context for node
+ * initialize child expressions
*/
- ExecAssignExprContext(estate, &scanstate->cstate);
+ tidstate->ss.ps.targetlist = (List *)
+ ExecInitExpr((Node *) node->scan.plan.targetlist,
+ (PlanState *) tidstate);
+ tidstate->ss.ps.qual = (List *)
+ ExecInitExpr((Node *) node->scan.plan.qual,
+ (PlanState *) tidstate);
#define TIDSCAN_NSLOTS 2
/*
* tuple table initialization
*/
- ExecInitResultTupleSlot(estate, &scanstate->cstate);
- ExecInitScanTupleSlot(estate, scanstate);
+ ExecInitResultTupleSlot(estate, &tidstate->ss.ps);
+ ExecInitScanTupleSlot(estate, &tidstate->ss);
/*
* initialize projection info. result type comes from scan desc
* below..
*/
- ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate);
-
- /*
- * Part 2) initialize tid scan state
- *
- * create new TidScanState for node
- */
- tidstate = makeNode(TidScanState);
- node->tidstate = tidstate;
+ ExecAssignProjectionInfo(&tidstate->ss.ps);
/*
* get the tid node information
*/
tidList = (ItemPointerData *) palloc(length(node->tideval) * sizeof(ItemPointerData));
- numTids = 0;
- if (!node->needRescan)
- numTids = TidListCreate(node->tideval,
- scanstate->cstate.cs_ExprContext,
- tidList);
+ numTids = TidListCreate(node->tideval,
+ tidstate->ss.ps.ps_ExprContext,
+ tidList);
tidPtr = -1;
CXT1_printf("ExecInitTidScan: context is %d\n", CurrentMemoryContext);
@@ -465,25 +432,25 @@ ExecInitTidScan(TidScan *node, EState *estate, Plan *parent)
currentRelation = heap_open(reloid, AccessShareLock);
- scanstate->css_currentRelation = currentRelation;
- scanstate->css_currentScanDesc = NULL; /* no heap scan here */
+ tidstate->ss.ss_currentRelation = currentRelation;
+ tidstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */
/*
* get the scan type from the relation descriptor.
*/
- ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false);
- ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);
+ ExecAssignScanType(&tidstate->ss, RelationGetDescr(currentRelation), false);
+ ExecAssignResultTypeFromTL(&tidstate->ss.ps);
/*
* if there are some PARAM_EXEC in skankeys then force tid rescan on
* first scan.
*/
- ((Plan *) node)->chgParam = execParam;
+ tidstate->ss.ps.chgParam = execParam;
/*
* all done.
*/
- return TRUE;
+ return tidstate;
}
int
diff --git a/src/backend/executor/nodeUnique.c b/src/backend/executor/nodeUnique.c
index b71403de0b8..88b08061f99 100644
--- a/src/backend/executor/nodeUnique.c
+++ b/src/backend/executor/nodeUnique.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeUnique.c,v 1.34 2002/06/20 20:29:28 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeUnique.c,v 1.35 2002/12/05 15:50:34 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -21,7 +21,6 @@
* NOTES
* Assumes tuples returned from subplan arrive in
* sorted order.
- *
*/
#include "postgres.h"
@@ -39,21 +38,20 @@
* ----------------------------------------------------------------
*/
TupleTableSlot * /* return: a tuple or NULL */
-ExecUnique(Unique *node)
+ExecUnique(UniqueState *node)
{
- UniqueState *uniquestate;
+ Unique *plannode = (Unique *) node->ps.plan;
TupleTableSlot *resultTupleSlot;
TupleTableSlot *slot;
- Plan *outerPlan;
+ PlanState *outerPlan;
TupleDesc tupDesc;
/*
* get information from the node
*/
- uniquestate = node->uniquestate;
- outerPlan = outerPlan((Plan *) node);
- resultTupleSlot = uniquestate->cstate.cs_ResultTupleSlot;
- tupDesc = ExecGetResultType(&uniquestate->cstate);
+ outerPlan = outerPlanState(node);
+ resultTupleSlot = node->ps.ps_ResultTupleSlot;
+ tupDesc = ExecGetResultType(&node->ps);
/*
* now loop, returning only non-duplicate tuples. We assume that the
@@ -64,14 +62,14 @@ ExecUnique(Unique *node)
/*
* fetch a tuple from the outer subplan
*/
- slot = ExecProcNode(outerPlan, (Plan *) node);
+ slot = ExecProcNode(outerPlan);
if (TupIsNull(slot))
return NULL;
/*
* Always return the first tuple from the subplan.
*/
- if (uniquestate->priorTuple == NULL)
+ if (node->priorTuple == NULL)
break;
/*
@@ -79,11 +77,11 @@ ExecUnique(Unique *node)
* match. If so then we loop back and fetch another new tuple
* from the subplan.
*/
- if (!execTuplesMatch(slot->val, uniquestate->priorTuple,
+ if (!execTuplesMatch(slot->val, node->priorTuple,
tupDesc,
- node->numCols, node->uniqColIdx,
- uniquestate->eqfunctions,
- uniquestate->tempContext))
+ plannode->numCols, plannode->uniqColIdx,
+ node->eqfunctions,
+ node->tempContext))
break;
}
@@ -99,11 +97,11 @@ ExecUnique(Unique *node)
* handling in execMain.c). We assume that the caller will no longer
* be interested in the current tuple after he next calls us.
*/
- if (uniquestate->priorTuple != NULL)
- heap_freetuple(uniquestate->priorTuple);
- uniquestate->priorTuple = heap_copytuple(slot->val);
+ if (node->priorTuple != NULL)
+ heap_freetuple(node->priorTuple);
+ node->priorTuple = heap_copytuple(slot->val);
- ExecStoreTuple(uniquestate->priorTuple,
+ ExecStoreTuple(node->priorTuple,
resultTupleSlot,
InvalidBuffer,
false); /* tuple does not belong to slot */
@@ -118,22 +116,18 @@ ExecUnique(Unique *node)
* the node's subplan.
* ----------------------------------------------------------------
*/
-bool /* return: initialization status */
-ExecInitUnique(Unique *node, EState *estate, Plan *parent)
+UniqueState *
+ExecInitUnique(Unique *node, EState *estate)
{
UniqueState *uniquestate;
- Plan *outerPlan;
/*
- * assign execution state to node
- */
- node->plan.state = estate;
-
- /*
- * create new UniqueState for node
+ * create state structure
*/
uniquestate = makeNode(UniqueState);
- node->uniquestate = uniquestate;
+ uniquestate->ps.plan = (Plan *) node;
+ uniquestate->ps.state = estate;
+
uniquestate->priorTuple = NULL;
/*
@@ -155,30 +149,29 @@ ExecInitUnique(Unique *node, EState *estate, Plan *parent)
/*
* Tuple table initialization
*/
- ExecInitResultTupleSlot(estate, &uniquestate->cstate);
+ ExecInitResultTupleSlot(estate, &uniquestate->ps);
/*
* then initialize outer plan
*/
- outerPlan = outerPlan((Plan *) node);
- ExecInitNode(outerPlan, estate, (Plan *) node);
+ outerPlanState(uniquestate) = ExecInitNode(outerPlan(node), estate);
/*
* unique nodes do no projections, so initialize projection info for
* this node appropriately
*/
- ExecAssignResultTypeFromOuterPlan((Plan *) node, &uniquestate->cstate);
- uniquestate->cstate.cs_ProjInfo = NULL;
+ ExecAssignResultTypeFromOuterPlan(&uniquestate->ps);
+ uniquestate->ps.ps_ProjInfo = NULL;
/*
* Precompute fmgr lookup data for inner loop
*/
uniquestate->eqfunctions =
- execTuplesMatchPrepare(ExecGetResultType(&uniquestate->cstate),
+ execTuplesMatchPrepare(ExecGetResultType(&uniquestate->ps),
node->numCols,
node->uniqColIdx);
- return TRUE;
+ return uniquestate;
}
int
@@ -197,41 +190,36 @@ ExecCountSlotsUnique(Unique *node)
* ----------------------------------------------------------------
*/
void
-ExecEndUnique(Unique *node)
+ExecEndUnique(UniqueState *node)
{
- UniqueState *uniquestate = node->uniquestate;
-
- ExecEndNode(outerPlan((Plan *) node), (Plan *) node);
-
- MemoryContextDelete(uniquestate->tempContext);
-
/* clean up tuple table */
- ExecClearTuple(uniquestate->cstate.cs_ResultTupleSlot);
- if (uniquestate->priorTuple != NULL)
+ ExecClearTuple(node->ps.ps_ResultTupleSlot);
+ if (node->priorTuple != NULL)
{
- heap_freetuple(uniquestate->priorTuple);
- uniquestate->priorTuple = NULL;
+ heap_freetuple(node->priorTuple);
+ node->priorTuple = NULL;
}
+
+ ExecEndNode(outerPlanState(node));
+
+ MemoryContextDelete(node->tempContext);
}
void
-ExecReScanUnique(Unique *node, ExprContext *exprCtxt, Plan *parent)
+ExecReScanUnique(UniqueState *node, ExprContext *exprCtxt)
{
- UniqueState *uniquestate = node->uniquestate;
-
- ExecClearTuple(uniquestate->cstate.cs_ResultTupleSlot);
- if (uniquestate->priorTuple != NULL)
+ ExecClearTuple(node->ps.ps_ResultTupleSlot);
+ if (node->priorTuple != NULL)
{
- heap_freetuple(uniquestate->priorTuple);
- uniquestate->priorTuple = NULL;
+ heap_freetuple(node->priorTuple);
+ node->priorTuple = NULL;
}
/*
* 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);
-
+ if (((PlanState *) node)->lefttree->chgParam == NULL)
+ ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
}
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 6e897e423eb..147becf6ed8 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.78 2002/11/13 00:39:47 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.79 2002/12/05 15:50:34 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -33,7 +33,7 @@ static int _SPI_connected = -1;
static int _SPI_curid = -1;
static int _SPI_execute(char *src, int tcount, _SPI_plan *plan);
-static int _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount);
+static int _SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount);
static int _SPI_execute_plan(_SPI_plan *plan,
Datum *Values, char *Nulls, int tcount);
@@ -705,9 +705,8 @@ SPI_cursor_open(char *name, void *plan, Datum *Values, char *Nulls)
List *ptlist = spiplan->ptlist;
Query *queryTree;
Plan *planTree;
+ ParamListInfo paramLI;
QueryDesc *queryDesc;
- EState *eState;
- TupleDesc attinfo;
MemoryContext oldcontext;
Portal portal;
char portalname[64];
@@ -774,28 +773,21 @@ SPI_cursor_open(char *name, void *plan, Datum *Values, char *Nulls)
queryTree->into->relname = pstrdup(name);
queryTree->isBinary = false;
- /* Create the QueryDesc object and the executor state */
- queryDesc = CreateQueryDesc(queryTree, planTree, SPI, NULL);
- eState = CreateExecutorState();
-
- /* If the plan has parameters, put them into the executor state */
+ /* If the plan has parameters, set them up */
if (spiplan->nargs > 0)
{
- ParamListInfo paramLI;
-
paramLI = (ParamListInfo) palloc0((spiplan->nargs + 1) *
- sizeof(ParamListInfoData));
+ sizeof(ParamListInfoData));
- eState->es_param_list_info = paramLI;
- for (k = 0; k < spiplan->nargs; paramLI++, k++)
+ for (k = 0; k < spiplan->nargs; k++)
{
- paramLI->kind = PARAM_NUM;
- paramLI->id = k + 1;
- paramLI->isnull = (Nulls && Nulls[k] == 'n');
- if (paramLI->isnull)
+ paramLI[k].kind = PARAM_NUM;
+ paramLI[k].id = k + 1;
+ paramLI[k].isnull = (Nulls && Nulls[k] == 'n');
+ if (paramLI[k].isnull)
{
/* nulls just copy */
- paramLI->value = Values[k];
+ paramLI[k].value = Values[k];
}
else
{
@@ -805,20 +797,24 @@ SPI_cursor_open(char *name, void *plan, Datum *Values, char *Nulls)
get_typlenbyval(spiplan->argtypes[k],
&paramTypLen, &paramTypByVal);
- paramLI->value = datumCopy(Values[k],
- paramTypByVal, paramTypLen);
+ paramLI[k].value = datumCopy(Values[k],
+ paramTypByVal, paramTypLen);
}
}
- paramLI->kind = PARAM_INVALID;
+ paramLI[k].kind = PARAM_INVALID;
}
else
- eState->es_param_list_info = NULL;
+ paramLI = NULL;
+
+ /* Create the QueryDesc object */
+ queryDesc = CreateQueryDesc(queryTree, planTree, SPI, NULL,
+ paramLI, false);
/* Start the executor */
- attinfo = ExecutorStart(queryDesc, eState);
+ ExecutorStart(queryDesc);
- /* Put all the objects into the portal */
- PortalSetQuery(portal, queryDesc, attinfo, eState, PortalCleanup);
+ /* Arrange to shut down the executor if portal is dropped */
+ PortalSetQuery(portal, queryDesc, PortalCleanup);
/* Switch back to the callers memory context */
MemoryContextSwitchTo(oldcontext);
@@ -1042,7 +1038,6 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
Plan *planTree;
bool canSetResult;
QueryDesc *qdesc;
- EState *state;
planTree = pg_plan_query(queryTree);
plan_list = lappend(plan_list, planTree);
@@ -1089,9 +1084,9 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
else if (plan == NULL)
{
qdesc = CreateQueryDesc(queryTree, planTree,
- canSetResult ? SPI : None, NULL);
- state = CreateExecutorState();
- res = _SPI_pquery(qdesc, state, canSetResult ? tcount : 0);
+ canSetResult ? SPI : None,
+ NULL, NULL, false);
+ res = _SPI_pquery(qdesc, true, canSetResult ? tcount : 0);
if (res < 0)
return res;
CommandCounterIncrement();
@@ -1099,8 +1094,9 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
else
{
qdesc = CreateQueryDesc(queryTree, planTree,
- canSetResult ? SPI : None, NULL);
- res = _SPI_pquery(qdesc, NULL, 0);
+ canSetResult ? SPI : None,
+ NULL, NULL, false);
+ res = _SPI_pquery(qdesc, false, 0);
if (res < 0)
return res;
}
@@ -1152,7 +1148,6 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount)
Plan *planTree;
bool canSetResult;
QueryDesc *qdesc;
- EState *state;
planTree = lfirst(plan_list);
plan_list = lnext(plan_list);
@@ -1183,30 +1178,31 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount)
}
else
{
- qdesc = CreateQueryDesc(queryTree, planTree,
- canSetResult ? SPI : None, NULL);
- state = CreateExecutorState();
+ ParamListInfo paramLI;
+
if (nargs > 0)
{
- ParamListInfo paramLI;
int k;
paramLI = (ParamListInfo)
palloc0((nargs + 1) * sizeof(ParamListInfoData));
- state->es_param_list_info = paramLI;
- for (k = 0; k < plan->nargs; paramLI++, k++)
+ for (k = 0; k < plan->nargs; k++)
{
- paramLI->kind = PARAM_NUM;
- paramLI->id = k + 1;
- paramLI->isnull = (Nulls && Nulls[k] == 'n');
- paramLI->value = Values[k];
+ paramLI[k].kind = PARAM_NUM;
+ paramLI[k].id = k + 1;
+ paramLI[k].isnull = (Nulls && Nulls[k] == 'n');
+ paramLI[k].value = Values[k];
}
- paramLI->kind = PARAM_INVALID;
+ paramLI[k].kind = PARAM_INVALID;
}
else
- state->es_param_list_info = NULL;
- res = _SPI_pquery(qdesc, state, canSetResult ? tcount : 0);
+ paramLI = NULL;
+
+ qdesc = CreateQueryDesc(queryTree, planTree,
+ canSetResult ? SPI : None,
+ NULL, paramLI, false);
+ res = _SPI_pquery(qdesc, true, canSetResult ? tcount : 0);
if (res < 0)
return res;
CommandCounterIncrement();
@@ -1218,7 +1214,7 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount)
}
static int
-_SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
+_SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount)
{
Query *parseTree = queryDesc->parsetree;
int operation = queryDesc->operation;
@@ -1262,7 +1258,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
return SPI_ERROR_OPUNKNOWN;
}
- if (state == NULL) /* plan preparation, don't execute */
+ if (!runit) /* plan preparation, don't execute */
return res;
#ifdef SPI_EXECUTOR_STATS
@@ -1270,20 +1266,20 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
ResetUsage();
#endif
- ExecutorStart(queryDesc, state);
+ ExecutorStart(queryDesc);
/*
* Don't work currently --- need to rearrange callers so that we
- * prepare the portal before doing CreateExecutorState() etc. See
+ * prepare the portal before doing ExecutorStart() etc. See
* pquery.c for the correct order of operations.
*/
if (isRetrieveIntoPortal)
elog(FATAL, "SPI_select: retrieve into portal not implemented");
- ExecutorRun(queryDesc, state, ForwardScanDirection, (long) tcount);
+ ExecutorRun(queryDesc, ForwardScanDirection, (long) tcount);
- _SPI_current->processed = state->es_processed;
- save_lastoid = state->es_lastoid;
+ _SPI_current->processed = queryDesc->estate->es_processed;
+ save_lastoid = queryDesc->estate->es_lastoid;
if (operation == CMD_SELECT && queryDesc->dest == SPI)
{
@@ -1291,7 +1287,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
elog(FATAL, "SPI_select: # of processed tuples check failed");
}
- ExecutorEnd(queryDesc, state);
+ ExecutorEnd(queryDesc);
#ifdef SPI_EXECUTOR_STATS
if (ShowExecutorStats)
@@ -1342,7 +1338,7 @@ _SPI_cursor_operation(Portal portal, bool forward, int count,
oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
querydesc = PortalGetQueryDesc(portal);
- estate = PortalGetState(portal);
+ estate = querydesc->estate;
/* Save the queries command destination and set it to SPI (for fetch) */
/* or None (for move) */
@@ -1357,7 +1353,7 @@ _SPI_cursor_operation(Portal portal, bool forward, int count,
else
direction = ForwardScanDirection;
- ExecutorRun(querydesc, estate, direction, (long) count);
+ ExecutorRun(querydesc, direction, (long) count);
if (estate->es_processed > 0)
portal->atStart = false; /* OK to back up now */
@@ -1371,7 +1367,7 @@ _SPI_cursor_operation(Portal portal, bool forward, int count,
else
direction = BackwardScanDirection;
- ExecutorRun(querydesc, estate, direction, (long) count);
+ ExecutorRun(querydesc, direction, (long) count);
if (estate->es_processed > 0)
portal->atEnd = false; /* OK to go forward now */