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 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 @@ ...@@ -23,6 +23,10 @@
/* /*
* PortalCleanup * 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 void
PortalCleanup(Portal portal) PortalCleanup(Portal portal)
...@@ -43,7 +47,7 @@ PortalCleanup(Portal portal) ...@@ -43,7 +47,7 @@ PortalCleanup(Portal portal)
/* /*
* tell the executor to shutdown the query * tell the executor to shutdown the query
*/ */
ExecutorEnd(PortalGetQueryDesc(portal), PortalGetState(portal)); ExecutorEnd(PortalGetQueryDesc(portal));
/* /*
* switch back to previous context * switch back to previous context
...@@ -116,7 +120,7 @@ PerformPortalFetch(char *name, ...@@ -116,7 +120,7 @@ PerformPortalFetch(char *name,
oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal)); oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
queryDesc = PortalGetQueryDesc(portal); queryDesc = PortalGetQueryDesc(portal);
estate = PortalGetState(portal); estate = queryDesc->estate;
/* /*
* If the requested destination is not the same as the query's * If the requested destination is not the same as the query's
...@@ -158,7 +162,7 @@ PerformPortalFetch(char *name, ...@@ -158,7 +162,7 @@ PerformPortalFetch(char *name,
else else
direction = ForwardScanDirection; direction = ForwardScanDirection;
ExecutorRun(queryDesc, estate, direction, (long) count); ExecutorRun(queryDesc, direction, (long) count);
if (estate->es_processed > 0) if (estate->es_processed > 0)
portal->atStart = false; /* OK to back up now */ portal->atStart = false; /* OK to back up now */
...@@ -172,7 +176,7 @@ PerformPortalFetch(char *name, ...@@ -172,7 +176,7 @@ PerformPortalFetch(char *name,
else else
direction = BackwardScanDirection; direction = BackwardScanDirection;
ExecutorRun(queryDesc, estate, direction, (long) count); ExecutorRun(queryDesc, direction, (long) count);
if (estate->es_processed > 0) if (estate->es_processed > 0)
portal->atEnd = false; /* OK to go forward now */ portal->atEnd = false; /* OK to go forward now */
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Copyright (c) 2002, PostgreSQL Global Development Group * Copyright (c) 2002, PostgreSQL Global Development Group
* *
* IDENTIFICATION * 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); ...@@ -49,7 +49,7 @@ static void InitQueryHashTable(void);
static void StoreQuery(const char *stmt_name, List *query_list, static void StoreQuery(const char *stmt_name, List *query_list,
List *plan_list, List *argtype_list); List *plan_list, List *argtype_list);
static QueryHashEntry *FetchQuery(const char *plan_name); 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) ...@@ -151,15 +151,12 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest)
else else
{ {
QueryDesc *qdesc; QueryDesc *qdesc;
EState *state;
if (log_executor_stats) if (log_executor_stats)
ResetUsage(); ResetUsage();
qdesc = CreateQueryDesc(query, plan, outputDest, NULL); qdesc = CreateQueryDesc(query, plan, outputDest, NULL,
state = CreateExecutorState(); paramLI, false);
state->es_param_list_info = paramLI;
if (stmt->into) if (stmt->into)
{ {
...@@ -170,7 +167,7 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest) ...@@ -170,7 +167,7 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest)
qdesc->dest = None; qdesc->dest = None;
} }
RunQuery(qdesc, state); RunQuery(qdesc);
if (log_executor_stats) if (log_executor_stats)
ShowUsage("EXECUTOR STATISTICS"); ShowUsage("EXECUTOR STATISTICS");
...@@ -334,15 +331,11 @@ FetchQueryParams(const char *plan_name) ...@@ -334,15 +331,11 @@ FetchQueryParams(const char *plan_name)
* Actually execute a prepared query. * Actually execute a prepared query.
*/ */
static void static void
RunQuery(QueryDesc *qdesc, EState *state) RunQuery(QueryDesc *qdesc)
{ {
TupleDesc tupdesc; ExecutorStart(qdesc);
ExecutorRun(qdesc, ForwardScanDirection, 0L);
tupdesc = ExecutorStart(qdesc, state); ExecutorEnd(qdesc);
ExecutorRun(qdesc, state, state->es_direction, 0L);
ExecutorEnd(qdesc, state);
} }
/* /*
......
$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 The Postgres Executor
--------------------- ---------------------
...@@ -39,6 +39,27 @@ delivered by the plan tree. ...@@ -39,6 +39,27 @@ delivered by the plan tree.
XXX a great deal more documentation needs to be written here... 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) EvalPlanQual (READ COMMITTED update checking)
--------------------------------------------- ---------------------------------------------
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 @@ ...@@ -19,12 +19,12 @@
#include "executor/instrument.h" #include "executor/instrument.h"
#include "executor/nodeAgg.h" #include "executor/nodeAgg.h"
#include "executor/nodeAppend.h" #include "executor/nodeAppend.h"
#include "executor/nodeFunctionscan.h"
#include "executor/nodeGroup.h" #include "executor/nodeGroup.h"
#include "executor/nodeGroup.h" #include "executor/nodeGroup.h"
#include "executor/nodeHash.h" #include "executor/nodeHash.h"
#include "executor/nodeHashjoin.h" #include "executor/nodeHashjoin.h"
#include "executor/nodeIndexscan.h" #include "executor/nodeIndexscan.h"
#include "executor/nodeTidscan.h"
#include "executor/nodeLimit.h" #include "executor/nodeLimit.h"
#include "executor/nodeMaterial.h" #include "executor/nodeMaterial.h"
#include "executor/nodeMergejoin.h" #include "executor/nodeMergejoin.h"
...@@ -35,45 +35,45 @@ ...@@ -35,45 +35,45 @@
#include "executor/nodeSort.h" #include "executor/nodeSort.h"
#include "executor/nodeSubplan.h" #include "executor/nodeSubplan.h"
#include "executor/nodeSubqueryscan.h" #include "executor/nodeSubqueryscan.h"
#include "executor/nodeFunctionscan.h" #include "executor/nodeTidscan.h"
#include "executor/nodeUnique.h" #include "executor/nodeUnique.h"
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecReScan * ExecReScan
* *
* XXX this should be extended to cope with all the node types..
*
* takes the new expression context as an argument, so that * takes the new expression context as an argument, so that
* index scans needn't have their scan keys updated separately * index scans needn't have their scan keys updated separately
* - marcel 09/20/94 * - marcel 09/20/94
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent) ExecReScan(PlanState *node, ExprContext *exprCtxt)
{ {
/* If collecting timing stats, update them */
if (node->instrument) if (node->instrument)
InstrEndLoop(node->instrument); InstrEndLoop(node->instrument);
if (node->chgParam != NULL) /* Wow! */ /* If we have changed parameters, propagate that info */
if (node->chgParam != NIL)
{ {
List *lst; List *lst;
foreach(lst, node->initPlan) 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 */ * locParam */
SetChangedParamList(splan, node->chgParam); SetChangedParamList(splan, node->chgParam);
if (splan->chgParam != NULL) if (splan->chgParam != NIL)
ExecReScanSetParamPlan((SubPlan *) lfirst(lst), node); ExecReScanSetParamPlan((SubPlanState *) lfirst(lst), node);
} }
foreach(lst, node->subPlan) 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); SetChangedParamList(splan, node->chgParam);
} }
/* Well. Now set chgParam for left/right trees. */ /* Well. Now set chgParam for left/right trees. */
...@@ -85,76 +85,76 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent) ...@@ -85,76 +85,76 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
switch (nodeTag(node)) switch (nodeTag(node))
{ {
case T_SeqScan: case T_ResultState:
ExecSeqReScan((SeqScan *) node, exprCtxt, parent); ExecReScanResult((ResultState *) node, exprCtxt);
break; break;
case T_IndexScan: case T_AppendState:
ExecIndexReScan((IndexScan *) node, exprCtxt, parent); ExecReScanAppend((AppendState *) node, exprCtxt);
break; break;
case T_TidScan: case T_SeqScanState:
ExecTidReScan((TidScan *) node, exprCtxt, parent); ExecSeqReScan((SeqScanState *) node, exprCtxt);
break; break;
case T_SubqueryScan: case T_IndexScanState:
ExecSubqueryReScan((SubqueryScan *) node, exprCtxt, parent); ExecIndexReScan((IndexScanState *) node, exprCtxt);
break; break;
case T_FunctionScan: case T_TidScanState:
ExecFunctionReScan((FunctionScan *) node, exprCtxt, parent); ExecTidReScan((TidScanState *) node, exprCtxt);
break; break;
case T_Material: case T_SubqueryScanState:
ExecMaterialReScan((Material *) node, exprCtxt, parent); ExecSubqueryReScan((SubqueryScanState *) node, exprCtxt);
break; break;
case T_NestLoop: case T_FunctionScanState:
ExecReScanNestLoop((NestLoop *) node, exprCtxt, parent); ExecFunctionReScan((FunctionScanState *) node, exprCtxt);
break; break;
case T_HashJoin: case T_NestLoopState:
ExecReScanHashJoin((HashJoin *) node, exprCtxt, parent); ExecReScanNestLoop((NestLoopState *) node, exprCtxt);
break; break;
case T_Hash: case T_MergeJoinState:
ExecReScanHash((Hash *) node, exprCtxt, parent); ExecReScanMergeJoin((MergeJoinState *) node, exprCtxt);
break; break;
case T_Agg: case T_HashJoinState:
ExecReScanAgg((Agg *) node, exprCtxt, parent); ExecReScanHashJoin((HashJoinState *) node, exprCtxt);
break; break;
case T_Group: case T_MaterialState:
ExecReScanGroup((Group *) node, exprCtxt, parent); ExecMaterialReScan((MaterialState *) node, exprCtxt);
break; break;
case T_Result: case T_SortState:
ExecReScanResult((Result *) node, exprCtxt, parent); ExecReScanSort((SortState *) node, exprCtxt);
break; break;
case T_Unique: case T_GroupState:
ExecReScanUnique((Unique *) node, exprCtxt, parent); ExecReScanGroup((GroupState *) node, exprCtxt);
break; break;
case T_SetOp: case T_AggState:
ExecReScanSetOp((SetOp *) node, exprCtxt, parent); ExecReScanAgg((AggState *) node, exprCtxt);
break; break;
case T_Limit: case T_UniqueState:
ExecReScanLimit((Limit *) node, exprCtxt, parent); ExecReScanUnique((UniqueState *) node, exprCtxt);
break; break;
case T_Sort: case T_HashState:
ExecReScanSort((Sort *) node, exprCtxt, parent); ExecReScanHash((HashState *) node, exprCtxt);
break; break;
case T_MergeJoin: case T_SetOpState:
ExecReScanMergeJoin((MergeJoin *) node, exprCtxt, parent); ExecReScanSetOp((SetOpState *) node, exprCtxt);
break; break;
case T_Append: case T_LimitState:
ExecReScanAppend((Append *) node, exprCtxt, parent); ExecReScanLimit((LimitState *) node, exprCtxt);
break; break;
default: default:
...@@ -163,10 +163,10 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent) ...@@ -163,10 +163,10 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
return; return;
} }
if (node->chgParam != NULL) if (node->chgParam != NIL)
{ {
freeList(node->chgParam); freeList(node->chgParam);
node->chgParam = NULL; node->chgParam = NIL;
} }
} }
...@@ -176,37 +176,37 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent) ...@@ -176,37 +176,37 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent)
* Marks the current scan position. * Marks the current scan position.
*/ */
void void
ExecMarkPos(Plan *node) ExecMarkPos(PlanState *node)
{ {
switch (nodeTag(node)) switch (nodeTag(node))
{ {
case T_SeqScan: case T_SeqScanState:
ExecSeqMarkPos((SeqScan *) node); ExecSeqMarkPos((SeqScanState *) node);
break; break;
case T_IndexScan: case T_IndexScanState:
ExecIndexMarkPos((IndexScan *) node); ExecIndexMarkPos((IndexScanState *) node);
break; break;
case T_TidScan: case T_TidScanState:
ExecTidMarkPos((TidScan *) node); ExecTidMarkPos((TidScanState *) node);
break; break;
case T_FunctionScan: case T_FunctionScanState:
ExecFunctionMarkPos((FunctionScan *) node); ExecFunctionMarkPos((FunctionScanState *) node);
break; break;
case T_Material: case T_MaterialState:
ExecMaterialMarkPos((Material *) node); ExecMaterialMarkPos((MaterialState *) node);
break; break;
case T_Sort: case T_SortState:
ExecSortMarkPos((Sort *) node); ExecSortMarkPos((SortState *) node);
break; break;
default: default:
/* don't make hard error unless caller asks to restore... */ /* 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)); nodeTag(node));
break; break;
} }
...@@ -218,32 +218,32 @@ ExecMarkPos(Plan *node) ...@@ -218,32 +218,32 @@ ExecMarkPos(Plan *node)
* restores the scan position previously saved with ExecMarkPos() * restores the scan position previously saved with ExecMarkPos()
*/ */
void void
ExecRestrPos(Plan *node) ExecRestrPos(PlanState *node)
{ {
switch (nodeTag(node)) switch (nodeTag(node))
{ {
case T_SeqScan: case T_SeqScanState:
ExecSeqRestrPos((SeqScan *) node); ExecSeqRestrPos((SeqScanState *) node);
break; break;
case T_IndexScan: case T_IndexScanState:
ExecIndexRestrPos((IndexScan *) node); ExecIndexRestrPos((IndexScanState *) node);
break; break;
case T_TidScan: case T_TidScanState:
ExecTidRestrPos((TidScan *) node); ExecTidRestrPos((TidScanState *) node);
break; break;
case T_FunctionScan: case T_FunctionScanState:
ExecFunctionRestrPos((FunctionScan *) node); ExecFunctionRestrPos((FunctionScanState *) node);
break; break;
case T_Material: case T_MaterialState:
ExecMaterialRestrPos((Material *) node); ExecMaterialRestrPos((MaterialState *) node);
break; break;
case T_Sort: case T_SortState:
ExecSortRestrPos((Sort *) node); ExecSortRestrPos((SortState *) node);
break; break;
default: default:
...@@ -258,6 +258,7 @@ ExecRestrPos(Plan *node) ...@@ -258,6 +258,7 @@ ExecRestrPos(Plan *node)
* *
* XXX Ideally, all plan node types would support mark/restore, and this * 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. * 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 bool
ExecSupportsMarkRestore(NodeTag plantype) ExecSupportsMarkRestore(NodeTag plantype)
......
This diff is collapsed.
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -1766,7 +1766,8 @@ ExecEvalExpr(Node *expression,
isNull, isDone); isNull, isDone);
break; break;
case SUBPLAN_EXPR: 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, expr->args, econtext,
isNull); isNull);
break; break;
...@@ -1850,6 +1851,169 @@ ExecEvalExprSwitchContext(Node *expression, ...@@ -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 * ExecQual / ExecTargetList / ExecProject
* ---------------------------------------------------------------- * ----------------------------------------------------------------
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* *
* *
* IDENTIFICATION * 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 @@ ...@@ -44,10 +44,9 @@
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
TupleTableSlot * TupleTableSlot *
ExecScan(Scan *node, ExecScan(ScanState *node,
ExecScanAccessMtd accessMtd) /* function returning a tuple */ ExecScanAccessMtd accessMtd) /* function returning a tuple */
{ {
CommonScanState *scanstate;
EState *estate; EState *estate;
ExprContext *econtext; ExprContext *econtext;
List *qual; List *qual;
...@@ -57,23 +56,22 @@ ExecScan(Scan *node, ...@@ -57,23 +56,22 @@ ExecScan(Scan *node,
/* /*
* Fetch data from node * Fetch data from node
*/ */
estate = node->plan.state; estate = node->ps.state;
scanstate = node->scanstate; econtext = node->ps.ps_ExprContext;
econtext = scanstate->cstate.cs_ExprContext; qual = node->ps.qual;
qual = node->plan.qual;
/* /*
* Check to see if we're still projecting out tuples from a previous * Check to see if we're still projecting out tuples from a previous
* scan tuple (because there is a function-returning-set in the * scan tuple (because there is a function-returning-set in the
* projection expressions). If so, try to project another one. * 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) if (isDone == ExprMultipleResult)
return resultSlot; return resultSlot;
/* Done with that source tuple... */ /* Done with that source tuple... */
scanstate->cstate.cs_TupFromTlist = false; node->ps.ps_TupFromTlist = false;
} }
/* /*
...@@ -104,7 +102,7 @@ ExecScan(Scan *node, ...@@ -104,7 +102,7 @@ ExecScan(Scan *node,
if (TupIsNull(slot)) if (TupIsNull(slot))
{ {
return ExecStoreTuple(NULL, return ExecStoreTuple(NULL,
scanstate->cstate.cs_ProjInfo->pi_slot, node->ps.ps_ProjInfo->pi_slot,
InvalidBuffer, InvalidBuffer,
true); true);
} }
...@@ -130,10 +128,10 @@ ExecScan(Scan *node, ...@@ -130,10 +128,10 @@ ExecScan(Scan *node,
* return it --- unless we find we can project no tuples from * return it --- unless we find we can project no tuples from
* this scan tuple, in which case continue scan. * 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) if (isDone != ExprEndResult)
{ {
scanstate->cstate.cs_TupFromTlist = (isDone == ExprMultipleResult); node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
return resultSlot; return resultSlot;
} }
} }
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* *
* *
* IDENTIFICATION * 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 */ ...@@ -483,11 +483,11 @@ ExecSetSlotDescriptorIsNew(TupleTableSlot *slot, /* slot to change */
* ---------------- * ----------------
*/ */
void void
ExecInitResultTupleSlot(EState *estate, CommonState *commonstate) ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
{ {
INIT_SLOT_DEFS; INIT_SLOT_DEFS;
INIT_SLOT_ALLOC; INIT_SLOT_ALLOC;
commonstate->cs_ResultTupleSlot = slot; planstate->ps_ResultTupleSlot = slot;
} }
/* ---------------- /* ----------------
...@@ -495,11 +495,11 @@ ExecInitResultTupleSlot(EState *estate, CommonState *commonstate) ...@@ -495,11 +495,11 @@ ExecInitResultTupleSlot(EState *estate, CommonState *commonstate)
* ---------------- * ----------------
*/ */
void void
ExecInitScanTupleSlot(EState *estate, CommonScanState *commonscanstate) ExecInitScanTupleSlot(EState *estate, ScanState *scanstate)
{ {
INIT_SLOT_DEFS; INIT_SLOT_DEFS;
INIT_SLOT_ALLOC; INIT_SLOT_ALLOC;
commonscanstate->css_ScanTupleSlot = slot; scanstate->ss_ScanTupleSlot = slot;
} }
/* ---------------- /* ----------------
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -142,7 +142,7 @@ DisplayTupleCount(FILE *statfp)
* ---------------- * ----------------
*/ */
void void
ExecAssignExprContext(EState *estate, CommonState *commonstate) ExecAssignExprContext(EState *estate, PlanState *planstate)
{ {
ExprContext *econtext = makeNode(ExprContext); ExprContext *econtext = makeNode(ExprContext);
...@@ -166,7 +166,7 @@ ExecAssignExprContext(EState *estate, CommonState *commonstate) ...@@ -166,7 +166,7 @@ ExecAssignExprContext(EState *estate, CommonState *commonstate)
econtext->ecxt_aggnulls = NULL; econtext->ecxt_aggnulls = NULL;
econtext->ecxt_callbacks = NULL; econtext->ecxt_callbacks = NULL;
commonstate->cs_ExprContext = econtext; planstate->ps_ExprContext = econtext;
} }
/* ---------------- /* ----------------
...@@ -259,10 +259,10 @@ MakePerTupleExprContext(EState *estate) ...@@ -259,10 +259,10 @@ MakePerTupleExprContext(EState *estate)
* ---------------- * ----------------
*/ */
void void
ExecAssignResultType(CommonState *commonstate, ExecAssignResultType(PlanState *planstate,
TupleDesc tupDesc, bool shouldFree) TupleDesc tupDesc, bool shouldFree)
{ {
TupleTableSlot *slot = commonstate->cs_ResultTupleSlot; TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
ExecSetSlotDescriptor(slot, tupDesc, shouldFree); ExecSetSlotDescriptor(slot, tupDesc, shouldFree);
} }
...@@ -272,15 +272,15 @@ ExecAssignResultType(CommonState *commonstate, ...@@ -272,15 +272,15 @@ ExecAssignResultType(CommonState *commonstate,
* ---------------- * ----------------
*/ */
void void
ExecAssignResultTypeFromOuterPlan(Plan *node, CommonState *commonstate) ExecAssignResultTypeFromOuterPlan(PlanState *planstate)
{ {
Plan *outerPlan; PlanState *outerPlan;
TupleDesc tupDesc; TupleDesc tupDesc;
outerPlan = outerPlan(node); outerPlan = outerPlanState(planstate);
tupDesc = ExecGetTupType(outerPlan); tupDesc = ExecGetTupType(outerPlan);
ExecAssignResultType(commonstate, tupDesc, false); ExecAssignResultType(planstate, tupDesc, false);
} }
/* ---------------- /* ----------------
...@@ -288,7 +288,7 @@ ExecAssignResultTypeFromOuterPlan(Plan *node, CommonState *commonstate) ...@@ -288,7 +288,7 @@ ExecAssignResultTypeFromOuterPlan(Plan *node, CommonState *commonstate)
* ---------------- * ----------------
*/ */
void void
ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate) ExecAssignResultTypeFromTL(PlanState *planstate)
{ {
ResultRelInfo *ri; ResultRelInfo *ri;
bool hasoid = false; bool hasoid = false;
...@@ -311,7 +311,7 @@ ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate) ...@@ -311,7 +311,7 @@ ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate)
* each of the child plans of the topmost Append plan. So, this is * each of the child plans of the topmost Append plan. So, this is
* ugly but it works, for now ... * ugly but it works, for now ...
*/ */
ri = node->state->es_result_relation_info; ri = planstate->state->es_result_relation_info;
if (ri != NULL) if (ri != NULL)
{ {
Relation rel = ri->ri_RelationDesc; Relation rel = ri->ri_RelationDesc;
...@@ -320,8 +320,13 @@ ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate) ...@@ -320,8 +320,13 @@ ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate)
hasoid = rel->rd_rel->relhasoids; 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) ...@@ -329,9 +334,9 @@ ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate)
* ---------------- * ----------------
*/ */
TupleDesc TupleDesc
ExecGetResultType(CommonState *commonstate) ExecGetResultType(PlanState *planstate)
{ {
TupleTableSlot *slot = commonstate->cs_ResultTupleSlot; TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
return slot->ttc_tupleDescriptor; return slot->ttc_tupleDescriptor;
} }
...@@ -342,23 +347,23 @@ ExecGetResultType(CommonState *commonstate) ...@@ -342,23 +347,23 @@ ExecGetResultType(CommonState *commonstate)
* ---------------- * ----------------
*/ */
void void
ExecAssignProjectionInfo(Plan *node, CommonState *commonstate) ExecAssignProjectionInfo(PlanState *planstate)
{ {
ProjectionInfo *projInfo; ProjectionInfo *projInfo;
List *targetList; List *targetList;
int len; int len;
targetList = node->targetlist; targetList = planstate->targetlist;
len = ExecTargetListLength(targetList); len = ExecTargetListLength(targetList);
projInfo = makeNode(ProjectionInfo); projInfo = makeNode(ProjectionInfo);
projInfo->pi_targetlist = targetList; projInfo->pi_targetlist = targetList;
projInfo->pi_len = len; projInfo->pi_len = len;
projInfo->pi_tupValue = (len <= 0) ? NULL : (Datum *) palloc(sizeof(Datum) * len); projInfo->pi_tupValue = (len <= 0) ? NULL : (Datum *) palloc(sizeof(Datum) * len);
projInfo->pi_exprContext = commonstate->cs_ExprContext; projInfo->pi_exprContext = planstate->ps_ExprContext;
projInfo->pi_slot = commonstate->cs_ResultTupleSlot; projInfo->pi_slot = planstate->ps_ResultTupleSlot;
commonstate->cs_ProjInfo = projInfo; planstate->ps_ProjInfo = projInfo;
} }
...@@ -367,7 +372,7 @@ ExecAssignProjectionInfo(Plan *node, CommonState *commonstate) ...@@ -367,7 +372,7 @@ ExecAssignProjectionInfo(Plan *node, CommonState *commonstate)
* ---------------- * ----------------
*/ */
void void
ExecFreeProjectionInfo(CommonState *commonstate) ExecFreeProjectionInfo(PlanState *planstate)
{ {
ProjectionInfo *projInfo; ProjectionInfo *projInfo;
...@@ -375,7 +380,7 @@ ExecFreeProjectionInfo(CommonState *commonstate) ...@@ -375,7 +380,7 @@ ExecFreeProjectionInfo(CommonState *commonstate)
* get projection info. if NULL then this node has none so we just * get projection info. if NULL then this node has none so we just
* return. * return.
*/ */
projInfo = commonstate->cs_ProjInfo; projInfo = planstate->ps_ProjInfo;
if (projInfo == NULL) if (projInfo == NULL)
return; return;
...@@ -386,7 +391,7 @@ ExecFreeProjectionInfo(CommonState *commonstate) ...@@ -386,7 +391,7 @@ ExecFreeProjectionInfo(CommonState *commonstate)
pfree(projInfo->pi_tupValue); pfree(projInfo->pi_tupValue);
pfree(projInfo); pfree(projInfo);
commonstate->cs_ProjInfo = NULL; planstate->ps_ProjInfo = NULL;
} }
/* ---------------- /* ----------------
...@@ -394,7 +399,7 @@ ExecFreeProjectionInfo(CommonState *commonstate) ...@@ -394,7 +399,7 @@ ExecFreeProjectionInfo(CommonState *commonstate)
* ---------------- * ----------------
*/ */
void void
ExecFreeExprContext(CommonState *commonstate) ExecFreeExprContext(PlanState *planstate)
{ {
ExprContext *econtext; ExprContext *econtext;
...@@ -402,7 +407,7 @@ ExecFreeExprContext(CommonState *commonstate) ...@@ -402,7 +407,7 @@ ExecFreeExprContext(CommonState *commonstate)
* get expression context. if NULL then this node has none so we just * get expression context. if NULL then this node has none so we just
* return. * return.
*/ */
econtext = commonstate->cs_ExprContext; econtext = planstate->ps_ExprContext;
if (econtext == NULL) if (econtext == NULL)
return; return;
...@@ -416,7 +421,7 @@ ExecFreeExprContext(CommonState *commonstate) ...@@ -416,7 +421,7 @@ ExecFreeExprContext(CommonState *commonstate)
*/ */
MemoryContextDelete(econtext->ecxt_per_tuple_memory); MemoryContextDelete(econtext->ecxt_per_tuple_memory);
pfree(econtext); pfree(econtext);
commonstate->cs_ExprContext = NULL; planstate->ps_ExprContext = NULL;
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -434,9 +439,9 @@ ExecFreeExprContext(CommonState *commonstate) ...@@ -434,9 +439,9 @@ ExecFreeExprContext(CommonState *commonstate)
* ---------------- * ----------------
*/ */
TupleDesc TupleDesc
ExecGetScanType(CommonScanState *csstate) ExecGetScanType(ScanState *scanstate)
{ {
TupleTableSlot *slot = csstate->css_ScanTupleSlot; TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
return slot->ttc_tupleDescriptor; return slot->ttc_tupleDescriptor;
} }
...@@ -446,10 +451,10 @@ ExecGetScanType(CommonScanState *csstate) ...@@ -446,10 +451,10 @@ ExecGetScanType(CommonScanState *csstate)
* ---------------- * ----------------
*/ */
void void
ExecAssignScanType(CommonScanState *csstate, ExecAssignScanType(ScanState *scanstate,
TupleDesc tupDesc, bool shouldFree) TupleDesc tupDesc, bool shouldFree)
{ {
TupleTableSlot *slot = csstate->css_ScanTupleSlot; TupleTableSlot *slot = scanstate->ss_ScanTupleSlot;
ExecSetSlotDescriptor(slot, tupDesc, shouldFree); ExecSetSlotDescriptor(slot, tupDesc, shouldFree);
} }
...@@ -459,15 +464,15 @@ ExecAssignScanType(CommonScanState *csstate, ...@@ -459,15 +464,15 @@ ExecAssignScanType(CommonScanState *csstate,
* ---------------- * ----------------
*/ */
void void
ExecAssignScanTypeFromOuterPlan(Plan *node, CommonScanState *csstate) ExecAssignScanTypeFromOuterPlan(ScanState *scanstate)
{ {
Plan *outerPlan; PlanState *outerPlan;
TupleDesc tupDesc; TupleDesc tupDesc;
outerPlan = outerPlan(node); outerPlan = outerPlanState(scanstate);
tupDesc = ExecGetTupType(outerPlan); tupDesc = ExecGetTupType(outerPlan);
ExecAssignScanType(csstate, tupDesc, false); ExecAssignScanType(scanstate, tupDesc, false);
} }
...@@ -718,7 +723,7 @@ ExecInsertIndexTuples(TupleTableSlot *slot, ...@@ -718,7 +723,7 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
} }
void void
SetChangedParamList(Plan *node, List *newchg) SetChangedParamList(PlanState *node, List *newchg)
{ {
List *nl; List *nl;
...@@ -727,8 +732,8 @@ SetChangedParamList(Plan *node, List *newchg) ...@@ -727,8 +732,8 @@ SetChangedParamList(Plan *node, List *newchg)
int paramId = lfirsti(nl); int paramId = lfirsti(nl);
/* if this node doesn't depend on a param ... */ /* if this node doesn't depend on a param ... */
if (!intMember(paramId, node->extParam) && if (!intMember(paramId, node->plan->extParam) &&
!intMember(paramId, node->locParam)) !intMember(paramId, node->plan->locParam))
continue; continue;
/* if this param is already in list of changed ones ... */ /* if this param is already in list of changed ones ... */
if (intMember(paramId, node->chgParam)) if (intMember(paramId, node->chgParam))
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 @@ ...@@ -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 typedef enum
{ {
...@@ -37,10 +39,11 @@ typedef enum ...@@ -37,10 +39,11 @@ typedef enum
typedef struct local_es typedef struct local_es
{ {
QueryDesc *qd;
EState *estate;
struct local_es *next; struct local_es *next;
ExecStatus status; ExecStatus status;
Query *query;
Plan *plan;
QueryDesc *qd; /* null unless status == RUN */
} execution_state; } execution_state;
#define LAST_POSTQUEL_COMMAND(es) ((es)->next == (execution_state *) NULL) #define LAST_POSTQUEL_COMMAND(es) ((es)->next == (execution_state *) NULL)
...@@ -62,6 +65,8 @@ typedef struct ...@@ -62,6 +65,8 @@ typedef struct
* we end execution of the function and * we end execution of the function and
* free stuff */ * free stuff */
ParamListInfo paramLI; /* Param list representing current args */
/* head of linked list of execution_state records */ /* head of linked list of execution_state records */
execution_state *func_state; execution_state *func_state;
} SQLFunctionCache; } SQLFunctionCache;
...@@ -73,10 +78,11 @@ typedef SQLFunctionCache *SQLFunctionCachePtr; ...@@ -73,10 +78,11 @@ typedef SQLFunctionCache *SQLFunctionCachePtr;
static execution_state *init_execution_state(char *src, static execution_state *init_execution_state(char *src,
Oid *argOidVect, int nargs); Oid *argOidVect, int nargs);
static void init_sql_fcache(FmgrInfo *finfo); 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 TupleTableSlot *postquel_getnext(execution_state *es);
static void postquel_end(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, static Datum postquel_execute(execution_state *es,
FunctionCallInfo fcinfo, FunctionCallInfo fcinfo,
SQLFunctionCachePtr fcache); SQLFunctionCachePtr fcache);
...@@ -101,7 +107,6 @@ init_execution_state(char *src, Oid *argOidVect, int nargs) ...@@ -101,7 +107,6 @@ init_execution_state(char *src, Oid *argOidVect, int nargs)
Query *queryTree = lfirst(qtl_item); Query *queryTree = lfirst(qtl_item);
Plan *planTree; Plan *planTree;
execution_state *newes; execution_state *newes;
EState *estate;
planTree = pg_plan_query(queryTree); planTree = pg_plan_query(queryTree);
...@@ -113,29 +118,9 @@ init_execution_state(char *src, Oid *argOidVect, int nargs) ...@@ -113,29 +118,9 @@ init_execution_state(char *src, Oid *argOidVect, int nargs)
newes->next = NULL; newes->next = NULL;
newes->status = F_EXEC_START; newes->status = F_EXEC_START;
newes->qd = CreateQueryDesc(queryTree, planTree, None, NULL); newes->query = queryTree;
newes->estate = estate = CreateExecutorState(); newes->plan = planTree;
newes->qd = NULL;
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;
preves = newes; preves = newes;
} }
...@@ -219,6 +204,10 @@ init_sql_fcache(FmgrInfo *finfo) ...@@ -219,6 +204,10 @@ init_sql_fcache(FmgrInfo *finfo)
else else
fcache->funcSlot = NULL; fcache->funcSlot = NULL;
/*
* Parse and plan the queries. We need the argument info to pass
* to the parser.
*/
nargs = procedureStruct->pronargs; nargs = procedureStruct->pronargs;
if (nargs > 0) if (nargs > 0)
...@@ -252,15 +241,18 @@ init_sql_fcache(FmgrInfo *finfo) ...@@ -252,15 +241,18 @@ init_sql_fcache(FmgrInfo *finfo)
static void static void
postquel_start(execution_state *es) postquel_start(execution_state *es, SQLFunctionCachePtr fcache)
{ {
/* Assert(es->qd == NULL);
* Do nothing for utility commands. (create, destroy...) DZ - es->qd = CreateQueryDesc(es->query, es->plan,
* 30-8-1996 None, NULL,
*/ fcache->paramLI, false);
if (es->qd->operation == CMD_UTILITY)
return; /* Utility commands don't need Executor. */
ExecutorStart(es->qd, es->estate); if (es->qd->operation != CMD_UTILITY)
ExecutorStart(es->qd);
es->status = F_EXEC_RUN;
} }
static TupleTableSlot * static TupleTableSlot *
...@@ -282,40 +274,52 @@ postquel_getnext(execution_state *es) ...@@ -282,40 +274,52 @@ postquel_getnext(execution_state *es)
/* If it's not the last command, just run it to completion */ /* If it's not the last command, just run it to completion */
count = (LAST_POSTQUEL_COMMAND(es)) ? 1L : 0L; count = (LAST_POSTQUEL_COMMAND(es)) ? 1L : 0L;
return ExecutorRun(es->qd, es->estate, ForwardScanDirection, count); return ExecutorRun(es->qd, ForwardScanDirection, count);
} }
static void static void
postquel_end(execution_state *es) postquel_end(execution_state *es)
{ {
/* /* Utility commands don't need Executor. */
* Do nothing for utility commands. (create, destroy...) DZ - if (es->qd->operation != CMD_UTILITY)
* 30-8-1996 ExecutorEnd(es->qd);
*/
if (es->qd->operation == CMD_UTILITY) pfree(es->qd);
return; es->qd = NULL;
ExecutorEnd(es->qd, es->estate);
es->status = F_EXEC_DONE;
} }
/* Build ParamListInfo array representing current arguments */
static void static void
postquel_sub_params(execution_state *es, FunctionCallInfo fcinfo) postquel_sub_params(SQLFunctionCachePtr fcache,
FunctionCallInfo fcinfo)
{ {
EState *estate;
ParamListInfo paramLI; ParamListInfo paramLI;
int nargs = fcinfo->nargs;
estate = es->estate; if (nargs > 0)
paramLI = estate->es_param_list_info;
while (paramLI->kind != PARAM_INVALID)
{ {
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[i].kind = PARAM_NUM;
paramLI->value = fcinfo->arg[paramLI->id - 1]; paramLI[i].id = i + 1;
paramLI->isnull = fcinfo->argnull[paramLI->id - 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 * static TupleTableSlot *
...@@ -359,27 +363,14 @@ postquel_execute(execution_state *es, ...@@ -359,27 +363,14 @@ postquel_execute(execution_state *es,
TupleTableSlot *slot; TupleTableSlot *slot;
Datum value; 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) if (es->status == F_EXEC_START)
{ postquel_start(es, fcache);
postquel_start(es);
es->status = F_EXEC_RUN;
}
slot = postquel_getnext(es); slot = postquel_getnext(es);
if (TupIsNull(slot)) if (TupIsNull(slot))
{ {
postquel_end(es); postquel_end(es);
es->status = F_EXEC_DONE;
fcinfo->isnull = true; fcinfo->isnull = true;
/* /*
...@@ -438,10 +429,7 @@ postquel_execute(execution_state *es, ...@@ -438,10 +429,7 @@ postquel_execute(execution_state *es,
* execution now. * execution now.
*/ */
if (!fcinfo->flinfo->fn_retset) if (!fcinfo->flinfo->fn_retset)
{
postquel_end(es); postquel_end(es);
es->status = F_EXEC_DONE;
}
return value; return value;
} }
...@@ -471,7 +459,7 @@ fmgr_sql(PG_FUNCTION_ARGS) ...@@ -471,7 +459,7 @@ fmgr_sql(PG_FUNCTION_ARGS)
oldcontext = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt); 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; fcache = (SQLFunctionCachePtr) fcinfo->flinfo->fn_extra;
if (fcache == NULL) if (fcache == NULL)
...@@ -481,6 +469,13 @@ fmgr_sql(PG_FUNCTION_ARGS) ...@@ -481,6 +469,13 @@ fmgr_sql(PG_FUNCTION_ARGS)
} }
es = fcache->func_state; 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. * Find first unfinished query in function.
*/ */
...@@ -506,7 +501,7 @@ fmgr_sql(PG_FUNCTION_ARGS) ...@@ -506,7 +501,7 @@ fmgr_sql(PG_FUNCTION_ARGS)
if (es == (execution_state *) NULL) 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; es = fcache->func_state;
while (es) while (es)
......
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 @@ ...@@ -62,30 +62,27 @@
#include "executor/nodeAppend.h" #include "executor/nodeAppend.h"
#include "parser/parsetree.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 * exec_append_initialize_next
* *
* Sets up the append node state (i.e. the append state node) * Sets up the append state node for the "next" scan.
* for the "next" scan.
* *
* Returns t iff there is a "next" scan to process. * Returns t iff there is a "next" scan to process.
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static bool static bool
exec_append_initialize_next(Append *node) exec_append_initialize_next(AppendState *appendstate)
{ {
EState *estate; EState *estate;
AppendState *appendstate;
int whichplan; int whichplan;
/* /*
* get information from the append node * get information from the append node
*/ */
estate = node->plan.state; estate = appendstate->ps.state;
appendstate = node->appendstate;
whichplan = appendstate->as_whichplan; whichplan = appendstate->as_whichplan;
if (whichplan < appendstate->as_firstplan) if (whichplan < appendstate->as_firstplan)
...@@ -116,7 +113,7 @@ exec_append_initialize_next(Append *node) ...@@ -116,7 +113,7 @@ exec_append_initialize_next(Append *node)
* If we are controlling the target relation, select the proper * If we are controlling the target relation, select the proper
* active ResultRelInfo and junk filter for this target. * active ResultRelInfo and junk filter for this target.
*/ */
if (node->isTarget) if (((Append *) appendstate->ps.plan)->isTarget)
{ {
Assert(whichplan < estate->es_num_result_relations); Assert(whichplan < estate->es_num_result_relations);
estate->es_result_relation_info = estate->es_result_relation_info =
...@@ -132,9 +129,7 @@ exec_append_initialize_next(Append *node) ...@@ -132,9 +129,7 @@ exec_append_initialize_next(Append *node)
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecInitAppend * ExecInitAppend
* *
* Begins all of the subscans of the append node, storing the * Begin all of the subscans of the append node.
* scan structures in the 'initialized' vector of the append-state
* structure.
* *
* (This is potentially wasteful, since the entire result of the * (This is potentially wasteful, since the entire result of the
* append node may not be scanned, but this way all of the * append node may not be scanned, but this way all of the
...@@ -146,36 +141,31 @@ exec_append_initialize_next(Append *node) ...@@ -146,36 +141,31 @@ exec_append_initialize_next(Append *node)
* subplan that corresponds to the target relation being checked. * subplan that corresponds to the target relation being checked.
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
bool AppendState *
ExecInitAppend(Append *node, EState *estate, Plan *parent) ExecInitAppend(Append *node, EState *estate)
{ {
AppendState *appendstate; AppendState *appendstate = makeNode(AppendState);
PlanState **appendplanstates;
int nplans; int nplans;
List *appendplans;
bool *initialized;
int i; int i;
Plan *initNode; Plan *initNode;
CXT1_printf("ExecInitAppend: context is %d\n", CurrentMemoryContext); 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; appendplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *));
nplans = length(appendplans);
initialized = (bool *) palloc0(nplans * sizeof(bool));
/* /*
* create new AppendState for our append node * 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_nplans = nplans;
appendstate->as_initialized = initialized;
node->appendstate = appendstate;
/* /*
* Do we want to scan just one subplan? (Special case for * Do we want to scan just one subplan? (Special case for
...@@ -212,36 +202,36 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent) ...@@ -212,36 +202,36 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent)
* append nodes still have Result slots, which hold pointers to * append nodes still have Result slots, which hold pointers to
* tuples, so we have to initialize them. * 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 * 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 * estate->es_result_relation_info correctly while we initialize each
* sub-plan; ExecAssignResultTypeFromTL depends on that! * sub-plan; ExecAssignResultTypeFromTL depends on that!
*/ */
for (i = appendstate->as_firstplan; i <= appendstate->as_lastplan; i++) for (i = appendstate->as_firstplan; i <= appendstate->as_lastplan; i++)
{ {
appendstate->as_whichplan = i; appendstate->as_whichplan = i;
exec_append_initialize_next(node); exec_append_initialize_next(appendstate);
initNode = (Plan *) nth(i, appendplans); initNode = (Plan *) nth(i, node->appendplans);
initialized[i] = ExecInitNode(initNode, estate, (Plan *) node); appendplanstates[i] = ExecInitNode(initNode, estate);
} }
/* /*
* initialize tuple type * initialize tuple type
*/ */
ExecAssignResultTypeFromTL((Plan *) node, &appendstate->cstate); ExecAssignResultTypeFromTL(&appendstate->ps);
appendstate->cstate.cs_ProjInfo = NULL; appendstate->ps.ps_ProjInfo = NULL;
/* /*
* return the result from the first subplan's initialization * return the result from the first subplan's initialization
*/ */
appendstate->as_whichplan = appendstate->as_firstplan; appendstate->as_whichplan = appendstate->as_firstplan;
exec_append_initialize_next(node); exec_append_initialize_next(appendstate);
return TRUE; return appendstate;
} }
int int
...@@ -264,13 +254,11 @@ ExecCountSlotsAppend(Append *node) ...@@ -264,13 +254,11 @@ ExecCountSlotsAppend(Append *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
TupleTableSlot * TupleTableSlot *
ExecProcAppend(Append *node) ExecProcAppend(AppendState *node)
{ {
EState *estate; EState *estate;
AppendState *appendstate;
int whichplan; int whichplan;
List *appendplans; PlanState *subnode;
Plan *subnode;
TupleTableSlot *result; TupleTableSlot *result;
TupleTableSlot *result_slot; TupleTableSlot *result_slot;
ScanDirection direction; ScanDirection direction;
...@@ -278,25 +266,20 @@ ExecProcAppend(Append *node) ...@@ -278,25 +266,20 @@ ExecProcAppend(Append *node)
/* /*
* get information from the node * get information from the node
*/ */
appendstate = node->appendstate; estate = node->ps.state;
estate = node->plan.state;
direction = estate->es_direction; direction = estate->es_direction;
appendplans = node->appendplans; whichplan = node->as_whichplan;
whichplan = appendstate->as_whichplan; result_slot = node->ps.ps_ResultTupleSlot;
result_slot = appendstate->cstate.cs_ResultTupleSlot;
/* /*
* figure out which subplan we are currently processing * figure out which subplan we are currently processing
*/ */
subnode = (Plan *) nth(whichplan, appendplans); subnode = node->appendplans[whichplan];
if (subnode == NULL)
elog(DEBUG1, "ExecProcAppend: subnode is NULL");
/* /*
* get a tuple from the subplan * get a tuple from the subplan
*/ */
result = ExecProcNode(subnode, (Plan *) node); result = ExecProcNode(subnode);
if (!TupIsNull(result)) if (!TupIsNull(result))
{ {
...@@ -316,9 +299,9 @@ ExecProcAppend(Append *node) ...@@ -316,9 +299,9 @@ ExecProcAppend(Append *node)
* try processing again (recursively) * try processing again (recursively)
*/ */
if (ScanDirectionIsForward(direction)) if (ScanDirectionIsForward(direction))
appendstate->as_whichplan++; node->as_whichplan++;
else else
appendstate->as_whichplan--; node->as_whichplan--;
/* /*
* return something from next node or an empty slot if all of our * return something from next node or an empty slot if all of our
...@@ -343,65 +326,56 @@ ExecProcAppend(Append *node) ...@@ -343,65 +326,56 @@ ExecProcAppend(Append *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecEndAppend(Append *node) ExecEndAppend(AppendState *node)
{ {
EState *estate; PlanState **appendplans;
AppendState *appendstate;
int nplans; int nplans;
List *appendplans;
bool *initialized;
int i; int i;
/* /*
* get information from the node * get information from the node
*/ */
appendstate = node->appendstate;
estate = node->plan.state;
appendplans = node->appendplans; appendplans = node->appendplans;
nplans = appendstate->as_nplans; nplans = node->as_nplans;
initialized = appendstate->as_initialized;
/* /*
* shut down each of the subscans * shut down each of the subscans (that we've initialized)
*/ */
for (i = 0; i < nplans; i++) for (i = 0; i < nplans; i++)
{ {
if (initialized[i]) if (appendplans[i])
ExecEndNode((Plan *) nth(i, appendplans), (Plan *) node); ExecEndNode(appendplans[i]);
} }
} }
void void
ExecReScanAppend(Append *node, ExprContext *exprCtxt, Plan *parent) ExecReScanAppend(AppendState *node, ExprContext *exprCtxt)
{ {
AppendState *appendstate = node->appendstate;
int i; int i;
for (i = appendstate->as_firstplan; i <= appendstate->as_lastplan; i++) for (i = node->as_firstplan; i <= node->as_lastplan; i++)
{ {
Plan *subnode; PlanState *subnode = node->appendplans[i];
subnode = (Plan *) nth(i, node->appendplans);
/* /*
* ExecReScan doesn't know about my subplans, so I have to do * ExecReScan doesn't know about my subplans, so I have to do
* changed-parameter signaling myself. * changed-parameter signaling myself.
*/ */
if (node->plan.chgParam != NULL) if (node->ps.chgParam != NIL)
SetChangedParamList(subnode, node->plan.chgParam); SetChangedParamList(subnode, node->ps.chgParam);
/* /*
* if chgParam of subnode is not null then plan will be re-scanned * if chgParam of subnode is not null then plan will be re-scanned
* by first ExecProcNode. * by first ExecProcNode.
*/ */
if (subnode->chgParam == NULL) if (subnode->chgParam == NIL)
{ {
/* make sure estate is correct for this subnode (needed??) */ /* make sure estate is correct for this subnode (needed??) */
appendstate->as_whichplan = i; node->as_whichplan = i;
exec_append_initialize_next(node); 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); exec_append_initialize_next(node);
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 @@ ...@@ -34,7 +34,7 @@
#include "utils/lsyscache.h" #include "utils/lsyscache.h"
static TupleTableSlot *FunctionNext(FunctionScan *node); static TupleTableSlot *FunctionNext(FunctionScanState *node);
static bool tupledesc_mismatch(TupleDesc tupdesc1, TupleDesc tupdesc2); static bool tupledesc_mismatch(TupleDesc tupdesc1, TupleDesc tupdesc2);
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -48,24 +48,22 @@ static bool tupledesc_mismatch(TupleDesc tupdesc1, TupleDesc tupdesc2); ...@@ -48,24 +48,22 @@ static bool tupledesc_mismatch(TupleDesc tupdesc1, TupleDesc tupdesc2);
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static TupleTableSlot * static TupleTableSlot *
FunctionNext(FunctionScan *node) FunctionNext(FunctionScanState *node)
{ {
TupleTableSlot *slot; TupleTableSlot *slot;
EState *estate; EState *estate;
ScanDirection direction; ScanDirection direction;
Tuplestorestate *tuplestorestate; Tuplestorestate *tuplestorestate;
FunctionScanState *scanstate;
bool should_free; bool should_free;
HeapTuple heapTuple; HeapTuple heapTuple;
/* /*
* get information from the estate and scan state * get information from the estate and scan state
*/ */
scanstate = (FunctionScanState *) node->scan.scanstate; estate = node->ss.ps.state;
estate = node->scan.plan.state;
direction = estate->es_direction; direction = estate->es_direction;
tuplestorestate = scanstate->tuplestorestate; tuplestorestate = node->tuplestorestate;
/* /*
* If first time through, read all tuples from function and put them * If first time through, read all tuples from function and put them
...@@ -74,13 +72,13 @@ FunctionNext(FunctionScan *node) ...@@ -74,13 +72,13 @@ FunctionNext(FunctionScan *node)
*/ */
if (tuplestorestate == NULL) if (tuplestorestate == NULL)
{ {
ExprContext *econtext = scanstate->csstate.cstate.cs_ExprContext; ExprContext *econtext = node->ss.ps.ps_ExprContext;
TupleDesc funcTupdesc; TupleDesc funcTupdesc;
scanstate->tuplestorestate = tuplestorestate = node->tuplestorestate = tuplestorestate =
ExecMakeTableFunctionResult(scanstate->funcexpr, ExecMakeTableFunctionResult(node->funcexpr,
econtext, econtext,
scanstate->tupdesc, node->tupdesc,
&funcTupdesc); &funcTupdesc);
/* /*
...@@ -89,14 +87,14 @@ FunctionNext(FunctionScan *node) ...@@ -89,14 +87,14 @@ FunctionNext(FunctionScan *node)
* well do it always. * well do it always.
*/ */
if (funcTupdesc && 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"); 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. * Get the next tuple from tuplestore. Return NULL if no more tuples.
*/ */
slot = scanstate->csstate.css_ScanTupleSlot; slot = node->ss.ss_ScanTupleSlot;
if (tuplestorestate) if (tuplestorestate)
heapTuple = tuplestore_getheaptuple(tuplestorestate, heapTuple = tuplestore_getheaptuple(tuplestorestate,
ScanDirectionIsForward(direction), ScanDirectionIsForward(direction),
...@@ -121,20 +119,20 @@ FunctionNext(FunctionScan *node) ...@@ -121,20 +119,20 @@ FunctionNext(FunctionScan *node)
*/ */
TupleTableSlot * TupleTableSlot *
ExecFunctionScan(FunctionScan *node) ExecFunctionScan(FunctionScanState *node)
{ {
/* /*
* use FunctionNext as access method * use FunctionNext as access method
*/ */
return ExecScan(&node->scan, (ExecScanAccessMtd) FunctionNext); return ExecScan(&node->ss, (ExecScanAccessMtd) FunctionNext);
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecInitFunctionScan * ExecInitFunctionScan
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
bool FunctionScanState *
ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent) ExecInitFunctionScan(FunctionScan *node, EState *estate)
{ {
FunctionScanState *scanstate; FunctionScanState *scanstate;
RangeTblEntry *rte; RangeTblEntry *rte;
...@@ -145,34 +143,40 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent) ...@@ -145,34 +143,40 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent)
/* /*
* FunctionScan should not have any children. * FunctionScan should not have any children.
*/ */
Assert(outerPlan((Plan *) node) == NULL); Assert(outerPlan(node) == NULL);
Assert(innerPlan((Plan *) node) == NULL); Assert(innerPlan(node) == NULL);
/*
* assign the node's execution state
*/
node->scan.plan.state = estate;
/* /*
* create new ScanState for node * create new ScanState for node
*/ */
scanstate = makeNode(FunctionScanState); scanstate = makeNode(FunctionScanState);
node->scan.scanstate = &scanstate->csstate; scanstate->ss.ps.plan = (Plan *) node;
scanstate->ss.ps.state = estate;
/* /*
* Miscellaneous initialization * Miscellaneous initialization
* *
* create expression context for node * create expression context for node
*/ */
ExecAssignExprContext(estate, &scanstate->csstate.cstate); ExecAssignExprContext(estate, &scanstate->ss.ps);
#define FUNCTIONSCAN_NSLOTS 2 #define FUNCTIONSCAN_NSLOTS 2
/* /*
* tuple table initialization * tuple table initialization
*/ */
ExecInitResultTupleSlot(estate, &scanstate->csstate.cstate); ExecInitResultTupleSlot(estate, &scanstate->ss.ps);
ExecInitScanTupleSlot(estate, &scanstate->csstate); 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 * get info about function
...@@ -230,7 +234,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent) ...@@ -230,7 +234,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent)
elog(ERROR, "Unknown kind of return type specified for function"); elog(ERROR, "Unknown kind of return type specified for function");
scanstate->tupdesc = tupdesc; scanstate->tupdesc = tupdesc;
ExecSetSlotDescriptor(scanstate->csstate.css_ScanTupleSlot, ExecSetSlotDescriptor(scanstate->ss.ss_ScanTupleSlot,
tupdesc, false); tupdesc, false);
/* /*
...@@ -239,15 +243,15 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent) ...@@ -239,15 +243,15 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent)
scanstate->tuplestorestate = NULL; scanstate->tuplestorestate = NULL;
scanstate->funcexpr = rte->funcexpr; scanstate->funcexpr = rte->funcexpr;
scanstate->csstate.cstate.cs_TupFromTlist = false; scanstate->ss.ps.ps_TupFromTlist = false;
/* /*
* initialize tuple type * initialize tuple type
*/ */
ExecAssignResultTypeFromTL((Plan *) node, &scanstate->csstate.cstate); ExecAssignResultTypeFromTL(&scanstate->ss.ps);
ExecAssignProjectionInfo((Plan *) node, &scanstate->csstate.cstate); ExecAssignProjectionInfo(&scanstate->ss.ps);
return TRUE; return scanstate;
} }
int int
...@@ -265,39 +269,26 @@ ExecCountSlotsFunctionScan(FunctionScan *node) ...@@ -265,39 +269,26 @@ ExecCountSlotsFunctionScan(FunctionScan *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void 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 * 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); ExecFreeProjectionInfo(&node->ss.ps);
ExecFreeExprContext(&scanstate->csstate.cstate); ExecFreeExprContext(&node->ss.ps);
/* /*
* clean out the tuple table * clean out the tuple table
*/ */
ExecClearTuple(scanstate->csstate.cstate.cs_ResultTupleSlot); ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecClearTuple(scanstate->csstate.css_ScanTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot);
/* /*
* Release tuplestore resources * Release tuplestore resources
*/ */
if (scanstate->tuplestorestate != NULL) if (node->tuplestorestate != NULL)
tuplestore_end(scanstate->tuplestorestate); tuplestore_end(node->tuplestorestate);
scanstate->tuplestorestate = NULL; node->tuplestorestate = NULL;
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -307,19 +298,15 @@ ExecEndFunctionScan(FunctionScan *node) ...@@ -307,19 +298,15 @@ ExecEndFunctionScan(FunctionScan *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecFunctionMarkPos(FunctionScan *node) ExecFunctionMarkPos(FunctionScanState *node)
{ {
FunctionScanState *scanstate;
scanstate = (FunctionScanState *) node->scan.scanstate;
/* /*
* if we haven't materialized yet, just return. * if we haven't materialized yet, just return.
*/ */
if (!scanstate->tuplestorestate) if (!node->tuplestorestate)
return; return;
tuplestore_markpos(scanstate->tuplestorestate); tuplestore_markpos(node->tuplestorestate);
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -329,19 +316,15 @@ ExecFunctionMarkPos(FunctionScan *node) ...@@ -329,19 +316,15 @@ ExecFunctionMarkPos(FunctionScan *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecFunctionRestrPos(FunctionScan *node) ExecFunctionRestrPos(FunctionScanState *node)
{ {
FunctionScanState *scanstate;
scanstate = (FunctionScanState *) node->scan.scanstate;
/* /*
* if we haven't materialized yet, just return. * if we haven't materialized yet, just return.
*/ */
if (!scanstate->tuplestorestate) if (!node->tuplestorestate)
return; return;
tuplestore_restorepos(scanstate->tuplestorestate); tuplestore_restorepos(node->tuplestorestate);
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -351,21 +334,14 @@ ExecFunctionRestrPos(FunctionScan *node) ...@@ -351,21 +334,14 @@ ExecFunctionRestrPos(FunctionScan *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecFunctionReScan(FunctionScan *node, ExprContext *exprCtxt, Plan *parent) ExecFunctionReScan(FunctionScanState *node, ExprContext *exprCtxt)
{ {
FunctionScanState *scanstate; ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
/*
* get information from node
*/
scanstate = (FunctionScanState *) node->scan.scanstate;
ExecClearTuple(scanstate->csstate.cstate.cs_ResultTupleSlot);
/* /*
* If we haven't materialized yet, just return. * If we haven't materialized yet, just return.
*/ */
if (!scanstate->tuplestorestate) if (!node->tuplestorestate)
return; return;
/* /*
...@@ -374,13 +350,13 @@ ExecFunctionReScan(FunctionScan *node, ExprContext *exprCtxt, Plan *parent) ...@@ -374,13 +350,13 @@ ExecFunctionReScan(FunctionScan *node, ExprContext *exprCtxt, Plan *parent)
* whether the function expression contains parameters and/or is * whether the function expression contains parameters and/or is
* marked volatile. FIXME soon. * marked volatile. FIXME soon.
*/ */
if (node->scan.plan.chgParam != NULL) if (node->ss.ps.chgParam != NULL)
{ {
tuplestore_end(scanstate->tuplestorestate); tuplestore_end(node->tuplestorestate);
scanstate->tuplestorestate = NULL; node->tuplestorestate = NULL;
} }
else else
tuplestore_rescan(scanstate->tuplestorestate); tuplestore_rescan(node->tuplestorestate);
} }
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* locate group boundaries. * locate group boundaries.
* *
* IDENTIFICATION * 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 @@ ...@@ -38,12 +38,13 @@
* Return one tuple for each group of matching input tuples. * Return one tuple for each group of matching input tuples.
*/ */
TupleTableSlot * TupleTableSlot *
ExecGroup(Group *node) ExecGroup(GroupState *node)
{ {
GroupState *grpstate;
EState *estate; EState *estate;
ExprContext *econtext; ExprContext *econtext;
TupleDesc tupdesc; TupleDesc tupdesc;
int numCols;
AttrNumber *grpColIdx;
HeapTuple outerTuple = NULL; HeapTuple outerTuple = NULL;
HeapTuple firsttuple; HeapTuple firsttuple;
TupleTableSlot *outerslot; TupleTableSlot *outerslot;
...@@ -53,12 +54,13 @@ ExecGroup(Group *node) ...@@ -53,12 +54,13 @@ ExecGroup(Group *node)
/* /*
* get state info from node * get state info from node
*/ */
grpstate = node->grpstate; if (node->grp_done)
if (grpstate->grp_done)
return NULL; return NULL;
estate = node->plan.state; estate = node->ss.ps.state;
econtext = node->grpstate->csstate.cstate.cs_ExprContext; econtext = node->ss.ps.ps_ExprContext;
tupdesc = ExecGetScanType(&grpstate->csstate); 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 * We need not call ResetExprContext here because execTuplesMatch will
...@@ -67,16 +69,16 @@ ExecGroup(Group *node) ...@@ -67,16 +69,16 @@ ExecGroup(Group *node)
/* If we don't already have first tuple of group, fetch it */ /* If we don't already have first tuple of group, fetch it */
/* this should occur on the first call only */ /* this should occur on the first call only */
firsttuple = grpstate->grp_firstTuple; firsttuple = node->grp_firstTuple;
if (firsttuple == NULL) if (firsttuple == NULL)
{ {
outerslot = ExecProcNode(outerPlan(node), (Plan *) node); outerslot = ExecProcNode(outerPlanState(node));
if (TupIsNull(outerslot)) if (TupIsNull(outerslot))
{ {
grpstate->grp_done = TRUE; node->grp_done = TRUE;
return NULL; return NULL;
} }
grpstate->grp_firstTuple = firsttuple = node->grp_firstTuple = firsttuple =
heap_copytuple(outerslot->val); heap_copytuple(outerslot->val);
} }
...@@ -85,10 +87,10 @@ ExecGroup(Group *node) ...@@ -85,10 +87,10 @@ ExecGroup(Group *node)
*/ */
for (;;) for (;;)
{ {
outerslot = ExecProcNode(outerPlan(node), (Plan *) node); outerslot = ExecProcNode(outerPlanState(node));
if (TupIsNull(outerslot)) if (TupIsNull(outerslot))
{ {
grpstate->grp_done = TRUE; node->grp_done = TRUE;
outerTuple = NULL; outerTuple = NULL;
break; break;
} }
...@@ -100,8 +102,8 @@ ExecGroup(Group *node) ...@@ -100,8 +102,8 @@ ExecGroup(Group *node)
*/ */
if (!execTuplesMatch(firsttuple, outerTuple, if (!execTuplesMatch(firsttuple, outerTuple,
tupdesc, tupdesc,
node->numCols, node->grpColIdx, numCols, grpColIdx,
grpstate->eqfunctions, node->eqfunctions,
econtext->ecxt_per_tuple_memory)) econtext->ecxt_per_tuple_memory))
break; break;
} }
...@@ -111,18 +113,18 @@ ExecGroup(Group *node) ...@@ -111,18 +113,18 @@ ExecGroup(Group *node)
* group, and store it in the result tuple slot. * group, and store it in the result tuple slot.
*/ */
ExecStoreTuple(firsttuple, ExecStoreTuple(firsttuple,
grpstate->csstate.css_ScanTupleSlot, node->ss.ss_ScanTupleSlot,
InvalidBuffer, InvalidBuffer,
false); false);
econtext->ecxt_scantuple = grpstate->csstate.css_ScanTupleSlot; econtext->ecxt_scantuple = node->ss.ss_ScanTupleSlot;
projInfo = grpstate->csstate.cstate.cs_ProjInfo; projInfo = node->ss.ps.ps_ProjInfo;
resultSlot = ExecProject(projInfo, NULL); resultSlot = ExecProject(projInfo, NULL);
/* save first tuple of next group, if we are not done yet */ /* save first tuple of next group, if we are not done yet */
if (!grpstate->grp_done) if (!node->grp_done)
{ {
heap_freetuple(firsttuple); heap_freetuple(firsttuple);
grpstate->grp_firstTuple = heap_copytuple(outerTuple); node->grp_firstTuple = heap_copytuple(outerTuple);
} }
return resultSlot; return resultSlot;
...@@ -135,65 +137,69 @@ ExecGroup(Group *node) ...@@ -135,65 +137,69 @@ ExecGroup(Group *node)
* planner and initializes its outer subtree * planner and initializes its outer subtree
* ----------------- * -----------------
*/ */
bool GroupState *
ExecInitGroup(Group *node, EState *estate, Plan *parent) ExecInitGroup(Group *node, EState *estate)
{ {
GroupState *grpstate; GroupState *grpstate;
Plan *outerPlan;
/*
* assign the node's execution state
*/
node->plan.state = estate;
/* /*
* create state structure * create state structure
*/ */
grpstate = makeNode(GroupState); grpstate = makeNode(GroupState);
node->grpstate = grpstate; grpstate->ss.ps.plan = (Plan *) node;
grpstate->ss.ps.state = estate;
grpstate->grp_firstTuple = NULL; grpstate->grp_firstTuple = NULL;
grpstate->grp_done = FALSE; grpstate->grp_done = FALSE;
/* /*
* create expression context * create expression context
*/ */
ExecAssignExprContext(estate, &grpstate->csstate.cstate); ExecAssignExprContext(estate, &grpstate->ss.ps);
#define GROUP_NSLOTS 2 #define GROUP_NSLOTS 2
/* /*
* tuple table initialization * tuple table initialization
*/ */
ExecInitScanTupleSlot(estate, &grpstate->csstate); ExecInitScanTupleSlot(estate, &grpstate->ss);
ExecInitResultTupleSlot(estate, &grpstate->csstate.cstate); 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); outerPlanState(grpstate) = ExecInitNode(outerPlan(node), estate);
ExecInitNode(outerPlan, estate, (Plan *) node);
/* /*
* initialize tuple type. * initialize tuple type.
*/ */
ExecAssignScanTypeFromOuterPlan((Plan *) node, &grpstate->csstate); ExecAssignScanTypeFromOuterPlan(&grpstate->ss);
/* /*
* Initialize tuple type for both result and scan. This node does no * Initialize tuple type for both result and scan. This node does no
* projection * projection
*/ */
ExecAssignResultTypeFromTL((Plan *) node, &grpstate->csstate.cstate); ExecAssignResultTypeFromTL(&grpstate->ss.ps);
ExecAssignProjectionInfo((Plan *) node, &grpstate->csstate.cstate); ExecAssignProjectionInfo(&grpstate->ss.ps);
/* /*
* Precompute fmgr lookup data for inner loop * Precompute fmgr lookup data for inner loop
*/ */
grpstate->eqfunctions = grpstate->eqfunctions =
execTuplesMatchPrepare(ExecGetScanType(&grpstate->csstate), execTuplesMatchPrepare(ExecGetScanType(&grpstate->ss),
node->numCols, node->numCols,
node->grpColIdx); node->grpColIdx);
return TRUE; return grpstate;
} }
int int
...@@ -208,43 +214,38 @@ ExecCountSlotsGroup(Group *node) ...@@ -208,43 +214,38 @@ ExecCountSlotsGroup(Group *node)
* ----------------------- * -----------------------
*/ */
void void
ExecEndGroup(Group *node) ExecEndGroup(GroupState *node)
{ {
GroupState *grpstate; PlanState *outerPlan;
Plan *outerPlan;
grpstate = node->grpstate; ExecFreeProjectionInfo(&node->ss.ps);
ExecFreeExprContext(&node->ss.ps);
ExecFreeProjectionInfo(&grpstate->csstate.cstate); outerPlan = outerPlanState(node);
ExecFreeExprContext(&grpstate->csstate.cstate); ExecEndNode(outerPlan);
outerPlan = outerPlan(node);
ExecEndNode(outerPlan, (Plan *) node);
/* clean up tuple table */ /* clean up tuple table */
ExecClearTuple(grpstate->csstate.css_ScanTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot);
if (grpstate->grp_firstTuple != NULL) if (node->grp_firstTuple != NULL)
{ {
heap_freetuple(grpstate->grp_firstTuple); heap_freetuple(node->grp_firstTuple);
grpstate->grp_firstTuple = NULL; node->grp_firstTuple = NULL;
} }
} }
void void
ExecReScanGroup(Group *node, ExprContext *exprCtxt, Plan *parent) ExecReScanGroup(GroupState *node, ExprContext *exprCtxt)
{ {
GroupState *grpstate = node->grpstate; node->grp_done = FALSE;
if (node->grp_firstTuple != NULL)
grpstate->grp_done = FALSE;
if (grpstate->grp_firstTuple != NULL)
{ {
heap_freetuple(grpstate->grp_firstTuple); heap_freetuple(node->grp_firstTuple);
grpstate->grp_firstTuple = NULL; node->grp_firstTuple = NULL;
} }
if (((Plan *) node)->lefttree && if (((PlanState *) node)->lefttree &&
((Plan *) node)->lefttree->chgParam == NULL) ((PlanState *) node)->lefttree->chgParam == NULL)
ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node); ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
} }
/***************************************************************************** /*****************************************************************************
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 @@ ...@@ -40,11 +40,10 @@
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
TupleTableSlot * TupleTableSlot *
ExecHash(Hash *node) ExecHash(HashState *node)
{ {
EState *estate; EState *estate;
HashState *hashstate; PlanState *outerNode;
Plan *outerNode;
List *hashkeys; List *hashkeys;
HashJoinTable hashtable; HashJoinTable hashtable;
TupleTableSlot *slot; TupleTableSlot *slot;
...@@ -55,12 +54,10 @@ ExecHash(Hash *node) ...@@ -55,12 +54,10 @@ ExecHash(Hash *node)
/* /*
* get state info from node * get state info from node
*/ */
estate = node->ps.state;
outerNode = outerPlanState(node);
hashstate = node->hashstate; hashtable = node->hashtable;
estate = node->plan.state;
outerNode = outerPlan(node);
hashtable = hashstate->hashtable;
if (hashtable == NULL) if (hashtable == NULL)
elog(ERROR, "ExecHash: hash table is NULL."); elog(ERROR, "ExecHash: hash table is NULL.");
...@@ -79,15 +76,15 @@ ExecHash(Hash *node) ...@@ -79,15 +76,15 @@ ExecHash(Hash *node)
/* /*
* set expression context * set expression context
*/ */
hashkeys = node->hashkeys; hashkeys = ((Hash *) node->ps.plan)->hashkeys;
econtext = hashstate->cstate.cs_ExprContext; econtext = node->ps.ps_ExprContext;
/* /*
* get all inner tuples and insert into the hash table (or temp files) * get all inner tuples and insert into the hash table (or temp files)
*/ */
for (;;) for (;;)
{ {
slot = ExecProcNode(outerNode, (Plan *) node); slot = ExecProcNode(outerNode);
if (TupIsNull(slot)) if (TupIsNull(slot))
break; break;
econtext->ecxt_innertuple = slot; econtext->ecxt_innertuple = slot;
...@@ -108,24 +105,19 @@ ExecHash(Hash *node) ...@@ -108,24 +105,19 @@ ExecHash(Hash *node)
* Init routine for Hash node * Init routine for Hash node
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
bool HashState *
ExecInitHash(Hash *node, EState *estate, Plan *parent) ExecInitHash(Hash *node, EState *estate)
{ {
HashState *hashstate; HashState *hashstate;
Plan *outerPlan;
SO_printf("ExecInitHash: initializing hash node\n"); SO_printf("ExecInitHash: initializing hash node\n");
/*
* assign the node's execution state
*/
node->plan.state = estate;
/* /*
* create state structure * create state structure
*/ */
hashstate = makeNode(HashState); hashstate = makeNode(HashState);
node->hashstate = hashstate; hashstate->ps.plan = (Plan *) node;
hashstate->ps.state = estate;
hashstate->hashtable = NULL; hashstate->hashtable = NULL;
/* /*
...@@ -133,29 +125,38 @@ ExecInitHash(Hash *node, EState *estate, Plan *parent) ...@@ -133,29 +125,38 @@ ExecInitHash(Hash *node, EState *estate, Plan *parent)
* *
* create expression context for node * create expression context for node
*/ */
ExecAssignExprContext(estate, &hashstate->cstate); ExecAssignExprContext(estate, &hashstate->ps);
#define HASH_NSLOTS 1 #define HASH_NSLOTS 1
/* /*
* initialize our result slot * initialize our result slot
*/ */
ExecInitResultTupleSlot(estate, &hashstate->cstate); ExecInitResultTupleSlot(estate, &hashstate->ps);
/* /*
* initializes child nodes * initialize child expressions
*/ */
outerPlan = outerPlan(node); hashstate->ps.targetlist = (List *)
ExecInitNode(outerPlan, estate, (Plan *) node); 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 * initialize tuple type. no need to initialize projection info
* because this node doesn't do projections * because this node doesn't do projections
*/ */
ExecAssignResultTypeFromOuterPlan((Plan *) node, &hashstate->cstate); ExecAssignResultTypeFromOuterPlan(&hashstate->ps);
hashstate->cstate.cs_ProjInfo = NULL; hashstate->ps.ps_ProjInfo = NULL;
return TRUE; return hashstate;
} }
int int
...@@ -173,28 +174,22 @@ ExecCountSlotsHash(Hash *node) ...@@ -173,28 +174,22 @@ ExecCountSlotsHash(Hash *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecEndHash(Hash *node) ExecEndHash(HashState *node)
{ {
HashState *hashstate; PlanState *outerPlan;
Plan *outerPlan;
/*
* get info from the hash state
*/
hashstate = node->hashstate;
/* /*
* free projection info. no need to free result type info because * free projection info. no need to free result type info because
* that came from the outer plan... * that came from the outer plan...
*/ */
ExecFreeProjectionInfo(&hashstate->cstate); ExecFreeProjectionInfo(&node->ps);
ExecFreeExprContext(&hashstate->cstate); ExecFreeExprContext(&node->ps);
/* /*
* shut down the subplan * shut down the subplan
*/ */
outerPlan = outerPlan(node); outerPlan = outerPlanState(node);
ExecEndNode(outerPlan, (Plan *) node); ExecEndNode(outerPlan);
} }
...@@ -758,12 +753,12 @@ ExecHashTableReset(HashJoinTable hashtable, long ntuples) ...@@ -758,12 +753,12 @@ ExecHashTableReset(HashJoinTable hashtable, long ntuples)
} }
void 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 * if chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode. * first ExecProcNode.
*/ */
if (((Plan *) node)->lefttree->chgParam == NULL) if (((PlanState *) node)->lefttree->chgParam == NULL)
ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node); 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.
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: relation.h,v 1.72 2002/11/30 05:21:03 tgl Exp $ * $Id: relation.h,v 1.73 2002/12/05 15:50:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -378,7 +378,6 @@ typedef struct TidPath ...@@ -378,7 +378,6 @@ typedef struct TidPath
{ {
Path path; Path path;
List *tideval; /* qual(s) involving CTID = something */ List *tideval; /* qual(s) involving CTID = something */
Relids unjoined_relids; /* some rels not yet part of my Path */
} TidPath; } TidPath;
/* /*
......
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