Commit 1fd0c59e authored by Tom Lane's avatar Tom Lane

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.
parent 0f3b83ed
This diff is collapsed.
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.4 2002/11/13 00:44:08 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.5 2002/12/05 15:50:30 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -23,6 +23,10 @@
/*
* PortalCleanup
*
* Clean up a portal when it's dropped. Since this mainly exists to run
* ExecutorEnd(), it should not be set as the cleanup hook until we have
* called ExecutorStart() on the portal's query.
*/
void
PortalCleanup(Portal portal)
......@@ -43,7 +47,7 @@ PortalCleanup(Portal portal)
/*
* tell the executor to shutdown the query
*/
ExecutorEnd(PortalGetQueryDesc(portal), PortalGetState(portal));
ExecutorEnd(PortalGetQueryDesc(portal));
/*
* switch back to previous context
......@@ -116,7 +120,7 @@ PerformPortalFetch(char *name,
oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
queryDesc = PortalGetQueryDesc(portal);
estate = PortalGetState(portal);
estate = queryDesc->estate;
/*
* If the requested destination is not the same as the query's
......@@ -158,7 +162,7 @@ PerformPortalFetch(char *name,
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 */
......@@ -172,7 +176,7 @@ PerformPortalFetch(char *name,
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 */
......
......@@ -6,7 +6,7 @@
* Copyright (c) 2002, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/prepare.c,v 1.8 2002/11/15 00:47:22 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/prepare.c,v 1.9 2002/12/05 15:50:30 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -49,7 +49,7 @@ static void InitQueryHashTable(void);
static void StoreQuery(const char *stmt_name, List *query_list,
List *plan_list, List *argtype_list);
static QueryHashEntry *FetchQuery(const char *plan_name);
static void RunQuery(QueryDesc *qdesc, EState *state);
static void RunQuery(QueryDesc *qdesc);
/*
......@@ -151,15 +151,12 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest)
else
{
QueryDesc *qdesc;
EState *state;
if (log_executor_stats)
ResetUsage();
qdesc = CreateQueryDesc(query, plan, outputDest, NULL);
state = CreateExecutorState();
state->es_param_list_info = paramLI;
qdesc = CreateQueryDesc(query, plan, outputDest, NULL,
paramLI, false);
if (stmt->into)
{
......@@ -170,7 +167,7 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest)
qdesc->dest = None;
}
RunQuery(qdesc, state);
RunQuery(qdesc);
if (log_executor_stats)
ShowUsage("EXECUTOR STATISTICS");
......@@ -334,15 +331,11 @@ FetchQueryParams(const char *plan_name)
* Actually execute a prepared query.
*/
static void
RunQuery(QueryDesc *qdesc, EState *state)
RunQuery(QueryDesc *qdesc)
{
TupleDesc tupdesc;
tupdesc = ExecutorStart(qdesc, state);
ExecutorRun(qdesc, state, state->es_direction, 0L);
ExecutorEnd(qdesc, state);
ExecutorStart(qdesc);
ExecutorRun(qdesc, ForwardScanDirection, 0L);
ExecutorEnd(qdesc);
}
/*
......
$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)
---------------------------------------------
......
......@@ -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)
......
This diff is collapsed.
This diff is collapsed.
......@@ -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
* ----------------------------------------------------------------
......
......@@ -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;
}
}
......
......@@ -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;
}
/* ----------------
......
......@@ -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))
......
......@@ -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)
......@@ -481,6 +469,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.
*/
......@@ -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)
......
This diff is collapsed.
......@@ -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);
}
......@@ -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);
}
......
......@@ -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);
}
/*****************************************************************************
......
......@@ -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);
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment