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
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994-5, Regents of the University of California * Portions Copyright (c) 1994-5, Regents of the University of California
* *
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.93 2002/11/13 00:39:46 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.94 2002/12/05 15:50:30 tgl Exp $
* *
*/ */
...@@ -34,16 +34,18 @@ typedef struct ExplainState ...@@ -34,16 +34,18 @@ typedef struct ExplainState
{ {
/* options */ /* options */
bool printCost; /* print cost */ bool printCost; /* print cost */
bool printNodes; /* do nodeToString() instead */ bool printNodes; /* do nodeToString() too */
bool printAnalyze; /* print actual times */ bool printAnalyze; /* print actual times */
/* other states */ /* other states */
List *rtable; /* range table */ List *rtable; /* range table */
} ExplainState; } ExplainState;
static StringInfo Explain_PlanToString(Plan *plan, ExplainState *es);
static void ExplainOneQuery(Query *query, ExplainStmt *stmt, static void ExplainOneQuery(Query *query, ExplainStmt *stmt,
TupOutputState *tstate); TupOutputState *tstate);
static void explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, static double elapsed_time(struct timeval *starttime);
static void explain_outNode(StringInfo str,
Plan *plan, PlanState *planstate,
Plan *outer_plan,
int indent, ExplainState *es); int indent, ExplainState *es);
static void show_scan_qual(List *qual, bool is_or_qual, const char *qlabel, static void show_scan_qual(List *qual, bool is_or_qual, const char *qlabel,
int scanrelid, Plan *outer_plan, int scanrelid, Plan *outer_plan,
...@@ -116,8 +118,11 @@ static void ...@@ -116,8 +118,11 @@ static void
ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate) ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate)
{ {
Plan *plan; Plan *plan;
QueryDesc *queryDesc;
ExplainState *es; ExplainState *es;
StringInfo str;
double totaltime = 0; double totaltime = 0;
struct timeval starttime;
/* planner will not cope with utility statements */ /* planner will not cope with utility statements */
if (query->commandType == CMD_UTILITY) if (query->commandType == CMD_UTILITY)
...@@ -136,41 +141,34 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate) ...@@ -136,41 +141,34 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate)
if (plan == NULL) if (plan == NULL)
return; return;
/* We don't support DECLARE CURSOR here */
Assert(!query->isPortal);
gettimeofday(&starttime, NULL);
/* Create a QueryDesc requesting no output */
queryDesc = CreateQueryDesc(query, plan, None, NULL, NULL,
stmt->analyze);
/* call ExecutorStart to prepare the plan for execution */
ExecutorStart(queryDesc);
/* Execute the plan for statistics if asked for */ /* Execute the plan for statistics if asked for */
if (stmt->analyze) if (stmt->analyze)
{ {
struct timeval starttime; /* run the plan */
struct timeval endtime; ExecutorRun(queryDesc, ForwardScanDirection, 0L);
/*
* Set up the instrumentation for the top node. This will cascade
* during plan initialisation
*/
plan->instrument = InstrAlloc();
gettimeofday(&starttime, NULL); /* We can't clean up 'till we're done printing the stats... */
ProcessQuery(query, plan, None, NULL);
CommandCounterIncrement();
gettimeofday(&endtime, NULL);
endtime.tv_sec -= starttime.tv_sec; totaltime += elapsed_time(&starttime);
endtime.tv_usec -= starttime.tv_usec;
while (endtime.tv_usec < 0)
{
endtime.tv_usec += 1000000;
endtime.tv_sec--;
}
totaltime = (double) endtime.tv_sec +
(double) endtime.tv_usec / 1000000.0;
} }
es = (ExplainState *) palloc0(sizeof(ExplainState)); es = (ExplainState *) palloc0(sizeof(ExplainState));
es->printCost = true; /* default */ es->printCost = true; /* default */
es->printNodes = stmt->verbose;
if (stmt->verbose) es->printAnalyze = stmt->analyze;
es->printNodes = true;
es->rtable = query->rtable; es->rtable = query->rtable;
if (es->printNodes) if (es->printNodes)
...@@ -193,33 +191,73 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate) ...@@ -193,33 +191,73 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate)
} }
} }
str = makeStringInfo();
if (es->printCost) if (es->printCost)
{ {
StringInfo str; explain_outNode(str, plan, queryDesc->planstate,
NULL, 0, es);
}
/*
* Close down the query and free resources. Include time for this
* in the total runtime.
*/
gettimeofday(&starttime, NULL);
ExecutorEnd(queryDesc);
CommandCounterIncrement();
str = Explain_PlanToString(plan, es); totaltime += elapsed_time(&starttime);
if (es->printCost)
{
if (stmt->analyze) if (stmt->analyze)
appendStringInfo(str, "Total runtime: %.2f msec\n", appendStringInfo(str, "Total runtime: %.2f msec\n",
1000.0 * totaltime); 1000.0 * totaltime);
do_text_output_multiline(tstate, str->data); do_text_output_multiline(tstate, str->data);
pfree(str->data);
pfree(str);
} }
pfree(str->data);
pfree(str);
pfree(es); pfree(es);
} }
/* Compute elapsed time in seconds since given gettimeofday() timestamp */
static double
elapsed_time(struct timeval *starttime)
{
struct timeval endtime;
gettimeofday(&endtime, NULL);
endtime.tv_sec -= starttime->tv_sec;
endtime.tv_usec -= starttime->tv_usec;
while (endtime.tv_usec < 0)
{
endtime.tv_usec += 1000000;
endtime.tv_sec--;
}
return (double) endtime.tv_sec +
(double) endtime.tv_usec / 1000000.0;
}
/* /*
* explain_outNode - * explain_outNode -
* converts a Plan node into ascii string and appends it to 'str' * converts a Plan node into ascii string and appends it to 'str'
* *
* planstate points to the executor state node corresponding to the plan node.
* We need this to get at the instrumentation data (if any) as well as the
* list of subplans.
*
* outer_plan, if not null, references another plan node that is the outer * outer_plan, if not null, references another plan node that is the outer
* side of a join with the current node. This is only interesting for * side of a join with the current node. This is only interesting for
* deciphering runtime keys of an inner indexscan. * deciphering runtime keys of an inner indexscan.
*/ */
static void static void
explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, explain_outNode(StringInfo str,
Plan *plan, PlanState *planstate,
Plan *outer_plan,
int indent, ExplainState *es) int indent, ExplainState *es)
{ {
List *l; List *l;
...@@ -410,18 +448,23 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, ...@@ -410,18 +448,23 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
plan->startup_cost, plan->total_cost, plan->startup_cost, plan->total_cost,
plan->plan_rows, plan->plan_width); plan->plan_rows, plan->plan_width);
if (plan->instrument && plan->instrument->nloops > 0) /*
* We have to forcibly clean up the instrumentation state because
* we haven't done ExecutorEnd yet. This is pretty grotty ...
*/
InstrEndLoop(planstate->instrument);
if (planstate->instrument && planstate->instrument->nloops > 0)
{ {
double nloops = plan->instrument->nloops; double nloops = planstate->instrument->nloops;
appendStringInfo(str, " (actual time=%.2f..%.2f rows=%.0f loops=%.0f)", appendStringInfo(str, " (actual time=%.2f..%.2f rows=%.0f loops=%.0f)",
1000.0 * plan->instrument->startup / nloops, 1000.0 * planstate->instrument->startup / nloops,
1000.0 * plan->instrument->total / nloops, 1000.0 * planstate->instrument->total / nloops,
plan->instrument->ntuples / nloops, planstate->instrument->ntuples / nloops,
plan->instrument->nloops); planstate->instrument->nloops);
es->printAnalyze = true;
} }
else if( es->printAnalyze ) else if (es->printAnalyze)
{ {
appendStringInfo(str, " (never executed)"); appendStringInfo(str, " (never executed)");
} }
...@@ -538,6 +581,7 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, ...@@ -538,6 +581,7 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
if (plan->initPlan) if (plan->initPlan)
{ {
List *saved_rtable = es->rtable; List *saved_rtable = es->rtable;
List *pslist = planstate->initPlan;
List *lst; List *lst;
for (i = 0; i < indent; i++) for (i = 0; i < indent; i++)
...@@ -545,12 +589,18 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, ...@@ -545,12 +589,18 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
appendStringInfo(str, " InitPlan\n"); appendStringInfo(str, " InitPlan\n");
foreach(lst, plan->initPlan) foreach(lst, plan->initPlan)
{ {
es->rtable = ((SubPlan *) lfirst(lst))->rtable; SubPlan *subplan = (SubPlan *) lfirst(lst);
SubPlanState *subplanstate = (SubPlanState *) lfirst(pslist);
es->rtable = subplan->rtable;
for (i = 0; i < indent; i++) for (i = 0; i < indent; i++)
appendStringInfo(str, " "); appendStringInfo(str, " ");
appendStringInfo(str, " -> "); appendStringInfo(str, " -> ");
explain_outNode(str, ((SubPlan *) lfirst(lst))->plan, NULL, explain_outNode(str, subplan->plan,
subplanstate->planstate,
NULL,
indent + 4, es); indent + 4, es);
pslist = lnext(pslist);
} }
es->rtable = saved_rtable; es->rtable = saved_rtable;
} }
...@@ -561,7 +611,10 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, ...@@ -561,7 +611,10 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
for (i = 0; i < indent; i++) for (i = 0; i < indent; i++)
appendStringInfo(str, " "); appendStringInfo(str, " ");
appendStringInfo(str, " -> "); appendStringInfo(str, " -> ");
explain_outNode(str, outerPlan(plan), NULL, indent + 3, es); explain_outNode(str, outerPlan(plan),
outerPlanState(planstate),
NULL,
indent + 3, es);
} }
/* righttree */ /* righttree */
...@@ -570,15 +623,20 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, ...@@ -570,15 +623,20 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
for (i = 0; i < indent; i++) for (i = 0; i < indent; i++)
appendStringInfo(str, " "); appendStringInfo(str, " ");
appendStringInfo(str, " -> "); appendStringInfo(str, " -> ");
explain_outNode(str, innerPlan(plan), outerPlan(plan), explain_outNode(str, innerPlan(plan),
innerPlanState(planstate),
outerPlan(plan),
indent + 3, es); indent + 3, es);
} }
if (IsA(plan, Append)) if (IsA(plan, Append))
{ {
Append *appendplan = (Append *) plan; Append *appendplan = (Append *) plan;
AppendState *appendstate = (AppendState *) planstate;
List *lst; List *lst;
int j;
j = 0;
foreach(lst, appendplan->appendplans) foreach(lst, appendplan->appendplans)
{ {
Plan *subnode = (Plan *) lfirst(lst); Plan *subnode = (Plan *) lfirst(lst);
...@@ -587,13 +645,18 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, ...@@ -587,13 +645,18 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
appendStringInfo(str, " "); appendStringInfo(str, " ");
appendStringInfo(str, " -> "); appendStringInfo(str, " -> ");
explain_outNode(str, subnode, NULL, indent + 3, es); explain_outNode(str, subnode,
appendstate->appendplans[j],
NULL,
indent + 3, es);
j++;
} }
} }
if (IsA(plan, SubqueryScan)) if (IsA(plan, SubqueryScan))
{ {
SubqueryScan *subqueryscan = (SubqueryScan *) plan; SubqueryScan *subqueryscan = (SubqueryScan *) plan;
SubqueryScanState *subquerystate = (SubqueryScanState *) planstate;
Plan *subnode = subqueryscan->subplan; Plan *subnode = subqueryscan->subplan;
RangeTblEntry *rte = rt_fetch(subqueryscan->scan.scanrelid, RangeTblEntry *rte = rt_fetch(subqueryscan->scan.scanrelid,
es->rtable); es->rtable);
...@@ -606,13 +669,16 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, ...@@ -606,13 +669,16 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
appendStringInfo(str, " "); appendStringInfo(str, " ");
appendStringInfo(str, " -> "); appendStringInfo(str, " -> ");
explain_outNode(str, subnode, NULL, indent + 3, es); explain_outNode(str, subnode,
subquerystate->subplan,
NULL,
indent + 3, es);
es->rtable = saved_rtable; es->rtable = saved_rtable;
} }
/* subPlan-s */ /* subPlan-s */
if (plan->subPlan) if (planstate->subPlan)
{ {
List *saved_rtable = es->rtable; List *saved_rtable = es->rtable;
List *lst; List *lst;
...@@ -620,29 +686,24 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, ...@@ -620,29 +686,24 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan,
for (i = 0; i < indent; i++) for (i = 0; i < indent; i++)
appendStringInfo(str, " "); appendStringInfo(str, " ");
appendStringInfo(str, " SubPlan\n"); appendStringInfo(str, " SubPlan\n");
foreach(lst, plan->subPlan) foreach(lst, planstate->subPlan)
{ {
es->rtable = ((SubPlan *) lfirst(lst))->rtable; SubPlanState *sps = (SubPlanState *) lfirst(lst);
SubPlan *sp = (SubPlan *) sps->ps.plan;
es->rtable = sp->rtable;
for (i = 0; i < indent; i++) for (i = 0; i < indent; i++)
appendStringInfo(str, " "); appendStringInfo(str, " ");
appendStringInfo(str, " -> "); appendStringInfo(str, " -> ");
explain_outNode(str, ((SubPlan *) lfirst(lst))->plan, NULL, explain_outNode(str, sp->plan,
sps->planstate,
NULL,
indent + 4, es); indent + 4, es);
} }
es->rtable = saved_rtable; es->rtable = saved_rtable;
} }
} }
static StringInfo
Explain_PlanToString(Plan *plan, ExplainState *es)
{
StringInfo str = makeStringInfo();
if (plan != NULL)
explain_outNode(str, plan, NULL, 0, es);
return str;
}
/* /*
* Show a qualifier expression for a scan plan node * Show a qualifier expression for a scan plan node
*/ */
......
...@@ -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)
......
...@@ -12,10 +12,9 @@ ...@@ -12,10 +12,9 @@
* ExecutorRun() and ExecutorEnd() * ExecutorRun() and ExecutorEnd()
* *
* These three procedures are the external interfaces to the executor. * These three procedures are the external interfaces to the executor.
* In each case, the query descriptor and the execution state is required * In each case, the query descriptor is required as an argument.
* as arguments
* *
* ExecutorStart() must be called at the beginning of any execution of any * ExecutorStart() must be called at the beginning of execution of any
* query plan and ExecutorEnd() should always be called at the end of * query plan and ExecutorEnd() should always be called at the end of
* execution of a plan. * execution of a plan.
* *
...@@ -27,7 +26,7 @@ ...@@ -27,7 +26,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.189 2002/12/05 04:04:42 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.190 2002/12/05 15:50:30 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -48,16 +47,13 @@ ...@@ -48,16 +47,13 @@
/* decls for local routines only used within this module */ /* decls for local routines only used within this module */
static TupleDesc InitPlan(CmdType operation, static void InitPlan(QueryDesc *queryDesc);
Query *parseTree,
Plan *plan,
EState *estate);
static void initResultRelInfo(ResultRelInfo *resultRelInfo, static void initResultRelInfo(ResultRelInfo *resultRelInfo,
Index resultRelationIndex, Index resultRelationIndex,
List *rangeTable, List *rangeTable,
CmdType operation); CmdType operation);
static void EndPlan(Plan *plan, EState *estate); static void EndPlan(PlanState *planstate, EState *estate);
static TupleTableSlot *ExecutePlan(EState *estate, Plan *plan, static TupleTableSlot *ExecutePlan(EState *estate, PlanState *planstate,
CmdType operation, CmdType operation,
long numberTuples, long numberTuples,
ScanDirection direction, ScanDirection direction,
...@@ -73,11 +69,6 @@ static void ExecUpdate(TupleTableSlot *slot, ItemPointer tupleid, ...@@ -73,11 +69,6 @@ static void ExecUpdate(TupleTableSlot *slot, ItemPointer tupleid,
EState *estate); EState *estate);
static TupleTableSlot *EvalPlanQualNext(EState *estate); static TupleTableSlot *EvalPlanQualNext(EState *estate);
static void EndEvalPlanQual(EState *estate); static void EndEvalPlanQual(EState *estate);
static void ExecCheckQueryPerms(CmdType operation, Query *parseTree,
Plan *plan);
static void ExecCheckPlanPerms(Plan *plan, List *rangeTable,
CmdType operation);
static void ExecCheckRTPerms(List *rangeTable, CmdType operation);
static void ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation); static void ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation);
/* end of local decls */ /* end of local decls */
...@@ -89,26 +80,40 @@ static void ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation); ...@@ -89,26 +80,40 @@ static void ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation);
* This routine must be called at the beginning of any execution of any * This routine must be called at the beginning of any execution of any
* query plan * query plan
* *
* returns a TupleDesc which describes the attributes of the tuples to * Takes a QueryDesc previously created by CreateQueryDesc (it's not real
* be returned by the query. (Same value is saved in queryDesc) * clear why we bother to separate the two functions, but...). The tupDesc
* field of the QueryDesc is filled in to describe the tuples that will be
* returned, and the internal fields (estate and planstate) are set up.
* *
* XXX this will change soon:
* NB: the CurrentMemoryContext when this is called must be the context * NB: the CurrentMemoryContext when this is called must be the context
* to be used as the per-query context for the query plan. ExecutorRun() * to be used as the per-query context for the query plan. ExecutorRun()
* and ExecutorEnd() must be called in this same memory context. * and ExecutorEnd() must be called in this same memory context.
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
TupleDesc void
ExecutorStart(QueryDesc *queryDesc, EState *estate) ExecutorStart(QueryDesc *queryDesc)
{ {
TupleDesc result; EState *estate;
/* sanity checks */ /* sanity checks: queryDesc must not be started already */
Assert(queryDesc != NULL); Assert(queryDesc != NULL);
Assert(queryDesc->estate == NULL);
/*
* Build EState, fill with parameters from queryDesc
*/
estate = CreateExecutorState();
queryDesc->estate = estate;
estate->es_param_list_info = queryDesc->params;
if (queryDesc->plantree->nParamExec > 0) if (queryDesc->plantree->nParamExec > 0)
estate->es_param_exec_vals = (ParamExecData *) estate->es_param_exec_vals = (ParamExecData *)
palloc0(queryDesc->plantree->nParamExec * sizeof(ParamExecData)); palloc0(queryDesc->plantree->nParamExec * sizeof(ParamExecData));
estate->es_instrument = queryDesc->doInstrument;
/* /*
* Make our own private copy of the current query snapshot data. * Make our own private copy of the current query snapshot data.
* *
...@@ -119,16 +124,9 @@ ExecutorStart(QueryDesc *queryDesc, EState *estate) ...@@ -119,16 +124,9 @@ ExecutorStart(QueryDesc *queryDesc, EState *estate)
estate->es_snapshot = CopyQuerySnapshot(); estate->es_snapshot = CopyQuerySnapshot();
/* /*
* Initialize the plan * Initialize the plan state tree
*/ */
result = InitPlan(queryDesc->operation, InitPlan(queryDesc);
queryDesc->parsetree,
queryDesc->plantree,
estate);
queryDesc->tupDesc = result;
return result;
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -150,11 +148,11 @@ ExecutorStart(QueryDesc *queryDesc, EState *estate) ...@@ -150,11 +148,11 @@ ExecutorStart(QueryDesc *queryDesc, EState *estate)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
TupleTableSlot * TupleTableSlot *
ExecutorRun(QueryDesc *queryDesc, EState *estate, ExecutorRun(QueryDesc *queryDesc,
ScanDirection direction, long count) ScanDirection direction, long count)
{ {
CmdType operation; CmdType operation;
Plan *plan; EState *estate;
CommandDest dest; CommandDest dest;
DestReceiver *destfunc; DestReceiver *destfunc;
TupleTableSlot *result; TupleTableSlot *result;
...@@ -169,7 +167,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, ...@@ -169,7 +167,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate,
* feature. * feature.
*/ */
operation = queryDesc->operation; operation = queryDesc->operation;
plan = queryDesc->plantree; estate = queryDesc->estate;
dest = queryDesc->dest; dest = queryDesc->dest;
/* /*
...@@ -189,7 +187,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, ...@@ -189,7 +187,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate,
result = NULL; result = NULL;
else else
result = ExecutePlan(estate, result = ExecutePlan(estate,
plan, queryDesc->planstate,
operation, operation,
count, count,
direction, direction,
...@@ -211,12 +209,16 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, ...@@ -211,12 +209,16 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate,
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecutorEnd(QueryDesc *queryDesc, EState *estate) ExecutorEnd(QueryDesc *queryDesc)
{ {
EState *estate;
/* sanity checks */ /* sanity checks */
Assert(queryDesc != NULL); Assert(queryDesc != NULL);
EndPlan(queryDesc->plantree, estate); estate = queryDesc->estate;
EndPlan(queryDesc->planstate, estate);
if (estate->es_snapshot != NULL) if (estate->es_snapshot != NULL)
{ {
...@@ -235,97 +237,55 @@ ExecutorEnd(QueryDesc *queryDesc, EState *estate) ...@@ -235,97 +237,55 @@ ExecutorEnd(QueryDesc *queryDesc, EState *estate)
/* /*
* ExecCheckQueryPerms * CreateExecutorState
* Check access permissions for all relations referenced in a query.
*/ */
static void EState *
ExecCheckQueryPerms(CmdType operation, Query *parseTree, Plan *plan) CreateExecutorState(void)
{ {
EState *state;
/* /*
* Check RTEs in the query's primary rangetable. * create a new executor state
*/ */
ExecCheckRTPerms(parseTree->rtable, operation); state = makeNode(EState);
/* /*
* Search for subplans and APPEND nodes to check their rangetables. * initialize the Executor State structure
*/ */
ExecCheckPlanPerms(plan, parseTree->rtable, operation); state->es_direction = ForwardScanDirection;
} state->es_range_table = NIL;
/* state->es_result_relations = NULL;
* ExecCheckPlanPerms state->es_num_result_relations = 0;
* Recursively scan the plan tree to check access permissions in state->es_result_relation_info = NULL;
* subplans.
*/
static void
ExecCheckPlanPerms(Plan *plan, List *rangeTable, CmdType operation)
{
List *subp;
if (plan == NULL)
return;
/* Check subplans, which we assume are plain SELECT queries */
foreach(subp, plan->initPlan)
{
SubPlan *subplan = (SubPlan *) lfirst(subp);
ExecCheckRTPerms(subplan->rtable, CMD_SELECT);
ExecCheckPlanPerms(subplan->plan, subplan->rtable, CMD_SELECT);
}
foreach(subp, plan->subPlan)
{
SubPlan *subplan = (SubPlan *) lfirst(subp);
ExecCheckRTPerms(subplan->rtable, CMD_SELECT); state->es_junkFilter = NULL;
ExecCheckPlanPerms(subplan->plan, subplan->rtable, CMD_SELECT);
}
/* Check lower plan nodes */ state->es_into_relation_descriptor = NULL;
ExecCheckPlanPerms(plan->lefttree, rangeTable, operation); state->es_param_list_info = NULL;
ExecCheckPlanPerms(plan->righttree, rangeTable, operation); state->es_param_exec_vals = NULL;
/* Do node-type-specific checks */ state->es_tupleTable = NULL;
switch (nodeTag(plan)) state->es_query_cxt = CurrentMemoryContext;
{
case T_SubqueryScan:
{
SubqueryScan *scan = (SubqueryScan *) plan;
RangeTblEntry *rte;
/* Recursively check the subquery */ state->es_instrument = false;
rte = rt_fetch(scan->scan.scanrelid, rangeTable);
Assert(rte->rtekind == RTE_SUBQUERY);
ExecCheckQueryPerms(operation, rte->subquery, scan->subplan);
break;
}
case T_Append:
{
Append *app = (Append *) plan;
List *appendplans;
foreach(appendplans, app->appendplans) state->es_per_tuple_exprcontext = NULL;
{
ExecCheckPlanPerms((Plan *) lfirst(appendplans),
rangeTable,
operation);
}
break;
}
default: /*
break; * return the executor state structure
} */
return state;
} }
/* /*
* ExecCheckRTPerms * ExecCheckRTPerms
* Check access permissions for all relations listed in a range table. * Check access permissions for all relations listed in a range table.
*/ */
static void void
ExecCheckRTPerms(List *rangeTable, CmdType operation) ExecCheckRTPerms(List *rangeTable, CmdType operation)
{ {
List *lp; List *lp;
...@@ -350,11 +310,18 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation) ...@@ -350,11 +310,18 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
AclResult aclcheck_result; AclResult aclcheck_result;
/* /*
* Only plain-relation RTEs need to be checked here. Subquery RTEs * If it's a subquery, recursively examine its rangetable.
* will be checked when ExecCheckPlanPerms finds the SubqueryScan */
* node, and function RTEs are checked by init_fcache when the if (rte->rtekind == RTE_SUBQUERY)
* function is prepared for execution. Join and special RTEs need no {
* checks. ExecCheckRTPerms(rte->subquery->rtable, operation);
return;
}
/*
* Otherwise, only plain-relation RTEs need to be checked here.
* Function RTEs are checked by init_fcache when the function is prepared
* for execution. Join and special RTEs need no checks.
*/ */
if (rte->rtekind != RTE_RELATION) if (rte->rtekind != RTE_RELATION)
return; return;
...@@ -367,7 +334,7 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation) ...@@ -367,7 +334,7 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
* *
* Note: GetUserId() is presently fast enough that there's no harm in * Note: GetUserId() is presently fast enough that there's no harm in
* calling it separately for each RTE. If that stops being true, we * calling it separately for each RTE. If that stops being true, we
* could call it once in ExecCheckQueryPerms and pass the userid down * could call it once in ExecCheckRTPerms and pass the userid down
* from there. But for now, no need for the extra clutter. * from there. But for now, no need for the extra clutter.
*/ */
userid = rte->checkAsUser ? rte->checkAsUser : GetUserId(); userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();
...@@ -428,7 +395,8 @@ typedef struct execRowMark ...@@ -428,7 +395,8 @@ typedef struct execRowMark
typedef struct evalPlanQual typedef struct evalPlanQual
{ {
Plan *plan; Plan *plan; /* XXX temporary */
PlanState *planstate;
Index rti; Index rti;
EState estate; EState estate;
struct evalPlanQual *free; struct evalPlanQual *free;
...@@ -441,17 +409,24 @@ typedef struct evalPlanQual ...@@ -441,17 +409,24 @@ typedef struct evalPlanQual
* and start up the rule manager * and start up the rule manager
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static TupleDesc static void
InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) InitPlan(QueryDesc *queryDesc)
{ {
CmdType operation = queryDesc->operation;
Query *parseTree = queryDesc->parsetree;
Plan *plan = queryDesc->plantree;
EState *estate = queryDesc->estate;
PlanState *planstate;
List *rangeTable; List *rangeTable;
Relation intoRelationDesc; Relation intoRelationDesc;
TupleDesc tupType; TupleDesc tupType;
/* /*
* Do permissions checks. * Do permissions checks. It's sufficient to examine the query's
* top rangetable here --- subplan RTEs will be checked during
* ExecInitSubPlan().
*/ */
ExecCheckQueryPerms(operation, parseTree, plan); ExecCheckRTPerms(parseTree->rtable, operation);
/* /*
* get information from query descriptor * get information from query descriptor
...@@ -575,14 +550,14 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) ...@@ -575,14 +550,14 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
* query tree. This opens files, allocates storage and leaves us * query tree. This opens files, allocates storage and leaves us
* ready to start processing tuples. * ready to start processing tuples.
*/ */
ExecInitNode(plan, estate, NULL); planstate = ExecInitNode(plan, estate);
/* /*
* Get the tuple descriptor describing the type of tuples to return. * Get the tuple descriptor describing the type of tuples to return.
* (this is especially important if we are creating a relation with * (this is especially important if we are creating a relation with
* "SELECT INTO") * "SELECT INTO")
*/ */
tupType = ExecGetTupType(plan); /* tuple descriptor */ tupType = ExecGetTupType(planstate);
/* /*
* Initialize the junk filter if needed. SELECT and INSERT queries * Initialize the junk filter if needed. SELECT and INSERT queries
...@@ -627,26 +602,29 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) ...@@ -627,26 +602,29 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
*/ */
if (parseTree->resultRelations != NIL) if (parseTree->resultRelations != NIL)
{ {
List *subplans; PlanState **appendplans;
int as_nplans;
ResultRelInfo *resultRelInfo; ResultRelInfo *resultRelInfo;
int i;
/* Top plan had better be an Append here. */ /* Top plan had better be an Append here. */
Assert(IsA(plan, Append)); Assert(IsA(plan, Append));
Assert(((Append *) plan)->isTarget); Assert(((Append *) plan)->isTarget);
subplans = ((Append *) plan)->appendplans; Assert(IsA(planstate, AppendState));
Assert(length(subplans) == estate->es_num_result_relations); appendplans = ((AppendState *) planstate)->appendplans;
as_nplans = ((AppendState *) planstate)->as_nplans;
Assert(as_nplans == estate->es_num_result_relations);
resultRelInfo = estate->es_result_relations; resultRelInfo = estate->es_result_relations;
while (subplans != NIL) for (i = 0; i < as_nplans; i++)
{ {
Plan *subplan = (Plan *) lfirst(subplans); PlanState *subplan = appendplans[i];
JunkFilter *j; JunkFilter *j;
j = ExecInitJunkFilter(subplan->targetlist, j = ExecInitJunkFilter(subplan->plan->targetlist,
ExecGetTupType(subplan), ExecGetTupType(subplan),
ExecAllocTableSlot(estate->es_tupleTable)); ExecAllocTableSlot(estate->es_tupleTable));
resultRelInfo->ri_junkFilter = j; resultRelInfo->ri_junkFilter = j;
resultRelInfo++; resultRelInfo++;
subplans = lnext(subplans);
} }
/* /*
...@@ -661,7 +639,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) ...@@ -661,7 +639,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
/* Normal case with just one JunkFilter */ /* Normal case with just one JunkFilter */
JunkFilter *j; JunkFilter *j;
j = ExecInitJunkFilter(plan->targetlist, j = ExecInitJunkFilter(planstate->plan->targetlist,
tupType, tupType,
ExecAllocTableSlot(estate->es_tupleTable)); ExecAllocTableSlot(estate->es_tupleTable));
estate->es_junkFilter = j; estate->es_junkFilter = j;
...@@ -755,7 +733,8 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) ...@@ -755,7 +733,8 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate)
estate->es_into_relation_descriptor = intoRelationDesc; estate->es_into_relation_descriptor = intoRelationDesc;
return tupType; queryDesc->tupDesc = tupType;
queryDesc->planstate = planstate;
} }
/* /*
...@@ -816,11 +795,11 @@ initResultRelInfo(ResultRelInfo *resultRelInfo, ...@@ -816,11 +795,11 @@ initResultRelInfo(ResultRelInfo *resultRelInfo,
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* EndPlan * EndPlan
* *
* Cleans up the query plan -- closes files and free up storages * Cleans up the query plan -- closes files and frees up storage
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static void static void
EndPlan(Plan *plan, EState *estate) EndPlan(PlanState *planstate, EState *estate)
{ {
ResultRelInfo *resultRelInfo; ResultRelInfo *resultRelInfo;
int i; int i;
...@@ -835,7 +814,7 @@ EndPlan(Plan *plan, EState *estate) ...@@ -835,7 +814,7 @@ EndPlan(Plan *plan, EState *estate)
/* /*
* shut down the node-type-specific query processing * shut down the node-type-specific query processing
*/ */
ExecEndNode(plan, NULL); ExecEndNode(planstate);
/* /*
* destroy the executor "tuple" table. * destroy the executor "tuple" table.
...@@ -902,7 +881,7 @@ EndPlan(Plan *plan, EState *estate) ...@@ -902,7 +881,7 @@ EndPlan(Plan *plan, EState *estate)
*/ */
static TupleTableSlot * static TupleTableSlot *
ExecutePlan(EState *estate, ExecutePlan(EState *estate,
Plan *plan, PlanState *planstate,
CmdType operation, CmdType operation,
long numberTuples, long numberTuples,
ScanDirection direction, ScanDirection direction,
...@@ -964,10 +943,10 @@ lnext: ; ...@@ -964,10 +943,10 @@ lnext: ;
{ {
slot = EvalPlanQualNext(estate); slot = EvalPlanQualNext(estate);
if (TupIsNull(slot)) if (TupIsNull(slot))
slot = ExecProcNode(plan, NULL); slot = ExecProcNode(planstate);
} }
else else
slot = ExecProcNode(plan, NULL); slot = ExecProcNode(planstate);
/* /*
* if the tuple is null, then we assume there is nothing more to * if the tuple is null, then we assume there is nothing more to
...@@ -1765,7 +1744,7 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid) ...@@ -1765,7 +1744,7 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
oldepq = (evalPlanQual *) epqstate->es_evalPlanQual; oldepq = (evalPlanQual *) epqstate->es_evalPlanQual;
Assert(oldepq->rti != 0); Assert(oldepq->rti != 0);
/* stop execution */ /* stop execution */
ExecEndNode(epq->plan, NULL); ExecEndNode(epq->planstate);
ExecDropTupleTable(epqstate->es_tupleTable, true); ExecDropTupleTable(epqstate->es_tupleTable, true);
epqstate->es_tupleTable = NULL; epqstate->es_tupleTable = NULL;
heap_freetuple(epqstate->es_evTuple[epq->rti - 1]); heap_freetuple(epqstate->es_evTuple[epq->rti - 1]);
...@@ -1793,10 +1772,8 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid) ...@@ -1793,10 +1772,8 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
/* /*
* Each stack level has its own copy of the plan tree. This * Each stack level has its own copy of the plan tree. This
* is wasteful, but necessary as long as plan nodes point to * is wasteful, but necessary until plan trees are fully
* exec state nodes rather than vice versa. Note that * read-only.
* copyfuncs.c doesn't attempt to copy the exec state nodes,
* which is a good thing in this situation.
*/ */
newepq->plan = copyObject(estate->es_origPlan); newepq->plan = copyObject(estate->es_origPlan);
...@@ -1858,7 +1835,7 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid) ...@@ -1858,7 +1835,7 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
if (endNode) if (endNode)
{ {
/* stop execution */ /* stop execution */
ExecEndNode(epq->plan, NULL); ExecEndNode(epq->planstate);
ExecDropTupleTable(epqstate->es_tupleTable, true); ExecDropTupleTable(epqstate->es_tupleTable, true);
epqstate->es_tupleTable = NULL; epqstate->es_tupleTable = NULL;
} }
...@@ -1886,7 +1863,7 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid) ...@@ -1886,7 +1863,7 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
epqstate->es_tupleTable = epqstate->es_tupleTable =
ExecCreateTupleTable(estate->es_tupleTable->size); ExecCreateTupleTable(estate->es_tupleTable->size);
ExecInitNode(epq->plan, epqstate, NULL); epq->planstate = ExecInitNode(epq->plan, epqstate);
return EvalPlanQualNext(estate); return EvalPlanQualNext(estate);
} }
...@@ -1902,7 +1879,7 @@ EvalPlanQualNext(EState *estate) ...@@ -1902,7 +1879,7 @@ EvalPlanQualNext(EState *estate)
Assert(epq->rti != 0); Assert(epq->rti != 0);
lpqnext:; lpqnext:;
slot = ExecProcNode(epq->plan, NULL); slot = ExecProcNode(epq->planstate);
/* /*
* No more tuples for this PQ. Continue previous one. * No more tuples for this PQ. Continue previous one.
...@@ -1910,7 +1887,7 @@ lpqnext:; ...@@ -1910,7 +1887,7 @@ lpqnext:;
if (TupIsNull(slot)) if (TupIsNull(slot))
{ {
/* stop execution */ /* stop execution */
ExecEndNode(epq->plan, NULL); ExecEndNode(epq->planstate);
ExecDropTupleTable(epqstate->es_tupleTable, true); ExecDropTupleTable(epqstate->es_tupleTable, true);
epqstate->es_tupleTable = NULL; epqstate->es_tupleTable = NULL;
heap_freetuple(epqstate->es_evTuple[epq->rti - 1]); heap_freetuple(epqstate->es_evTuple[epq->rti - 1]);
...@@ -1951,7 +1928,7 @@ EndEvalPlanQual(EState *estate) ...@@ -1951,7 +1928,7 @@ EndEvalPlanQual(EState *estate)
for (;;) for (;;)
{ {
/* stop execution */ /* stop execution */
ExecEndNode(epq->plan, NULL); ExecEndNode(epq->planstate);
ExecDropTupleTable(epqstate->es_tupleTable, true); ExecDropTupleTable(epqstate->es_tupleTable, true);
epqstate->es_tupleTable = NULL; epqstate->es_tupleTable = NULL;
if (epqstate->es_evTuple[epq->rti - 1] != NULL) if (epqstate->es_evTuple[epq->rti - 1] != NULL)
......
...@@ -5,23 +5,23 @@ ...@@ -5,23 +5,23 @@
* "get a tuple", and "cleanup" routines for the given node type. * "get a tuple", and "cleanup" routines for the given node type.
* If the node has children, then it will presumably call ExecInitNode, * If the node has children, then it will presumably call ExecInitNode,
* ExecProcNode, or ExecEndNode on its subnodes and do the appropriate * ExecProcNode, or ExecEndNode on its subnodes and do the appropriate
* processing.. * processing.
* *
* 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
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.30 2002/06/20 20:29:27 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.31 2002/12/05 15:50:31 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
/* /*
* INTERFACE ROUTINES * INTERFACE ROUTINES
* ExecCountSlotsNode - count tuple slots needed by plan tree
* ExecInitNode - initialize a plan node and its subplans * ExecInitNode - initialize a plan node and its subplans
* ExecProcNode - get a tuple by executing the plan node * ExecProcNode - get a tuple by executing the plan node
* ExecEndNode - shut down a plan node and its subplans * ExecEndNode - shut down a plan node and its subplans
* ExecCountSlotsNode - count tuple slots needed by plan tree
* ExecGetTupType - get result tuple type of a plan node * ExecGetTupType - get result tuple type of a plan node
* *
* NOTES * NOTES
...@@ -53,10 +53,12 @@ ...@@ -53,10 +53,12 @@
* * ExecInitNode() notices that it is looking at a nest loop and * * ExecInitNode() notices that it is looking at a nest loop and
* as the code below demonstrates, it calls ExecInitNestLoop(). * as the code below demonstrates, it calls ExecInitNestLoop().
* Eventually this calls ExecInitNode() on the right and left subplans * Eventually this calls ExecInitNode() on the right and left subplans
* and so forth until the entire plan is initialized. * and so forth until the entire plan is initialized. The result
* of ExecInitNode() is a plan state tree built with the same structure
* as the underlying plan tree.
* *
* * Then when ExecRun() is called, it calls ExecutePlan() which * * Then when ExecRun() is called, it calls ExecutePlan() which calls
* calls ExecProcNode() repeatedly on the top node of the plan. * ExecProcNode() repeatedly on the top node of the plan state tree.
* Each time this happens, ExecProcNode() will end up calling * Each time this happens, ExecProcNode() will end up calling
* ExecNestLoop(), which calls ExecProcNode() on its subplans. * ExecNestLoop(), which calls ExecProcNode() on its subplans.
* Each of these subplans is a sequential scan so ExecSeqScan() is * Each of these subplans is a sequential scan so ExecSeqScan() is
...@@ -73,7 +75,6 @@ ...@@ -73,7 +75,6 @@
* ExecInitNode(), ExecProcNode() and ExecEndNode() dispatch * ExecInitNode(), ExecProcNode() and ExecEndNode() dispatch
* their work to the appopriate node support routines which may * their work to the appopriate node support routines which may
* in turn call these routines themselves on their subplans. * in turn call these routines themselves on their subplans.
*
*/ */
#include "postgres.h" #include "postgres.h"
...@@ -81,11 +82,11 @@ ...@@ -81,11 +82,11 @@
#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/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"
...@@ -96,7 +97,7 @@ ...@@ -96,7 +97,7 @@
#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"
#include "miscadmin.h" #include "miscadmin.h"
#include "tcop/tcopprot.h" #include "tcop/tcopprot.h"
...@@ -109,32 +110,23 @@ ...@@ -109,32 +110,23 @@
* *
* Initial States: * Initial States:
* 'node' is the plan produced by the query planner * 'node' is the plan produced by the query planner
* 'estate' is the shared execution state for the query tree
* *
* returns TRUE/FALSE on whether the plan was successfully initialized * Returns a PlanState node corresponding to the given Plan node.
* ------------------------------------------------------------------------ * ------------------------------------------------------------------------
*/ */
bool PlanState *
ExecInitNode(Plan *node, EState *estate, Plan *parent) ExecInitNode(Plan *node, EState *estate)
{ {
bool result; PlanState *result;
List *subps;
List *subp; List *subp;
/* /*
* do nothing when we get to the end of a leaf on tree. * do nothing when we get to the end of a leaf on tree.
*/ */
if (node == NULL) if (node == NULL)
return FALSE; return NULL;
/* Set up instrumentation for this node if the parent has it */
if (!node->instrument && parent && parent->instrument)
node->instrument = InstrAlloc();
foreach(subp, node->initPlan)
{
result = ExecInitSubPlan((SubPlan *) lfirst(subp), estate, node);
if (result == FALSE)
return FALSE;
}
switch (nodeTag(node)) switch (nodeTag(node))
{ {
...@@ -142,104 +134,124 @@ ExecInitNode(Plan *node, EState *estate, Plan *parent) ...@@ -142,104 +134,124 @@ ExecInitNode(Plan *node, EState *estate, Plan *parent)
* control nodes * control nodes
*/ */
case T_Result: case T_Result:
result = ExecInitResult((Result *) node, estate, parent); result = (PlanState *) ExecInitResult((Result *) node, estate);
break; break;
case T_Append: case T_Append:
result = ExecInitAppend((Append *) node, estate, parent); result = (PlanState *) ExecInitAppend((Append *) node, estate);
break; break;
/* /*
* scan nodes * scan nodes
*/ */
case T_SeqScan: case T_SeqScan:
result = ExecInitSeqScan((SeqScan *) node, estate, parent); result = (PlanState *) ExecInitSeqScan((SeqScan *) node, estate);
break; break;
case T_IndexScan: case T_IndexScan:
result = ExecInitIndexScan((IndexScan *) node, estate, parent); result = (PlanState *) ExecInitIndexScan((IndexScan *) node, estate);
break; break;
case T_TidScan: case T_TidScan:
result = ExecInitTidScan((TidScan *) node, estate, parent); result = (PlanState *) ExecInitTidScan((TidScan *) node, estate);
break; break;
case T_SubqueryScan: case T_SubqueryScan:
result = ExecInitSubqueryScan((SubqueryScan *) node, estate, result = (PlanState *) ExecInitSubqueryScan((SubqueryScan *) node, estate);
parent);
break; break;
case T_FunctionScan: case T_FunctionScan:
result = ExecInitFunctionScan((FunctionScan *) node, estate, result = (PlanState *) ExecInitFunctionScan((FunctionScan *) node, estate);
parent);
break; break;
/* /*
* join nodes * join nodes
*/ */
case T_NestLoop: case T_NestLoop:
result = ExecInitNestLoop((NestLoop *) node, estate, parent); result = (PlanState *) ExecInitNestLoop((NestLoop *) node, estate);
break; break;
case T_MergeJoin: case T_MergeJoin:
result = ExecInitMergeJoin((MergeJoin *) node, estate, parent); result = (PlanState *) ExecInitMergeJoin((MergeJoin *) node, estate);
break;
case T_Hash:
result = ExecInitHash((Hash *) node, estate, parent);
break; break;
case T_HashJoin: case T_HashJoin:
result = ExecInitHashJoin((HashJoin *) node, estate, parent); result = (PlanState *) ExecInitHashJoin((HashJoin *) node, estate);
break; break;
/* /*
* materialization nodes * materialization nodes
*/ */
case T_Material: case T_Material:
result = ExecInitMaterial((Material *) node, estate, parent); result = (PlanState *) ExecInitMaterial((Material *) node, estate);
break; break;
case T_Sort: case T_Sort:
result = ExecInitSort((Sort *) node, estate, parent); result = (PlanState *) ExecInitSort((Sort *) node, estate);
break; break;
case T_Unique: case T_Group:
result = ExecInitUnique((Unique *) node, estate, parent); result = (PlanState *) ExecInitGroup((Group *) node, estate);
break; break;
case T_SetOp: case T_Agg:
result = ExecInitSetOp((SetOp *) node, estate, parent); result = (PlanState *) ExecInitAgg((Agg *) node, estate);
break; break;
case T_Limit: case T_Unique:
result = ExecInitLimit((Limit *) node, estate, parent); result = (PlanState *) ExecInitUnique((Unique *) node, estate);
break; break;
case T_Group: case T_Hash:
result = ExecInitGroup((Group *) node, estate, parent); result = (PlanState *) ExecInitHash((Hash *) node, estate);
break; break;
case T_Agg: case T_SetOp:
result = ExecInitAgg((Agg *) node, estate, parent); result = (PlanState *) ExecInitSetOp((SetOp *) node, estate);
break;
case T_Limit:
result = (PlanState *) ExecInitLimit((Limit *) node, estate);
break; break;
default: default:
elog(ERROR, "ExecInitNode: node type %d unsupported", elog(ERROR, "ExecInitNode: node type %d unsupported",
(int) nodeTag(node)); (int) nodeTag(node));
result = FALSE; result = NULL; /* keep compiler quiet */
break; break;
} }
if (result != FALSE) /*
{ * Initialize any initPlans present in this node. The planner put
foreach(subp, node->subPlan) * them in a separate list for us.
*/
subps = NIL;
foreach(subp, node->initPlan)
{ {
result = ExecInitSubPlan((SubPlan *) lfirst(subp), estate, node); SubPlan *subplan = (SubPlan *) lfirst(subp);
if (result == FALSE)
return FALSE; Assert(IsA(subplan, SubPlan));
subps = lappend(subps, ExecInitSubPlan(subplan, estate));
} }
result->initPlan = subps;
/*
* Initialize any subPlans present in this node. These were found
* by ExecInitExpr during initialization of the PlanState.
*/
subps = NIL;
foreach(subp, result->subPlan)
{
SubPlan *subplan = (SubPlan *) lfirst(subp);
Assert(IsA(subplan, SubPlan));
subps = lappend(subps, ExecInitSubPlan(subplan, estate));
} }
result->subPlan = subps;
/* Set up instrumentation for this node if requested */
if (estate->es_instrument)
result->instrument = InstrAlloc();
return result; return result;
} }
...@@ -248,12 +260,11 @@ ExecInitNode(Plan *node, EState *estate, Plan *parent) ...@@ -248,12 +260,11 @@ ExecInitNode(Plan *node, EState *estate, Plan *parent)
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecProcNode * ExecProcNode
* *
* Initial States: * Execute the given node to return a(nother) tuple.
* the query tree must be initialized once by calling ExecInit.
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
TupleTableSlot * TupleTableSlot *
ExecProcNode(Plan *node, Plan *parent) ExecProcNode(PlanState *node)
{ {
TupleTableSlot *result; TupleTableSlot *result;
...@@ -265,8 +276,8 @@ ExecProcNode(Plan *node, Plan *parent) ...@@ -265,8 +276,8 @@ ExecProcNode(Plan *node, Plan *parent)
if (node == NULL) if (node == NULL)
return NULL; return NULL;
if (node->chgParam != NULL) /* something changed */ if (node->chgParam != NIL) /* something changed */
ExecReScan(node, NULL, parent); /* let ReScan handle this */ ExecReScan(node, NULL); /* let ReScan handle this */
if (node->instrument) if (node->instrument)
InstrStartNode(node->instrument); InstrStartNode(node->instrument);
...@@ -276,85 +287,85 @@ ExecProcNode(Plan *node, Plan *parent) ...@@ -276,85 +287,85 @@ ExecProcNode(Plan *node, Plan *parent)
/* /*
* control nodes * control nodes
*/ */
case T_Result: case T_ResultState:
result = ExecResult((Result *) node); result = ExecResult((ResultState *) node);
break; break;
case T_Append: case T_AppendState:
result = ExecProcAppend((Append *) node); result = ExecProcAppend((AppendState *) node);
break; break;
/* /*
* scan nodes * scan nodes
*/ */
case T_SeqScan: case T_SeqScanState:
result = ExecSeqScan((SeqScan *) node); result = ExecSeqScan((SeqScanState *) node);
break; break;
case T_IndexScan: case T_IndexScanState:
result = ExecIndexScan((IndexScan *) node); result = ExecIndexScan((IndexScanState *) node);
break; break;
case T_TidScan: case T_TidScanState:
result = ExecTidScan((TidScan *) node); result = ExecTidScan((TidScanState *) node);
break; break;
case T_SubqueryScan: case T_SubqueryScanState:
result = ExecSubqueryScan((SubqueryScan *) node); result = ExecSubqueryScan((SubqueryScanState *) node);
break; break;
case T_FunctionScan: case T_FunctionScanState:
result = ExecFunctionScan((FunctionScan *) node); result = ExecFunctionScan((FunctionScanState *) node);
break; break;
/* /*
* join nodes * join nodes
*/ */
case T_NestLoop: case T_NestLoopState:
result = ExecNestLoop((NestLoop *) node); result = ExecNestLoop((NestLoopState *) node);
break; break;
case T_MergeJoin: case T_MergeJoinState:
result = ExecMergeJoin((MergeJoin *) node); result = ExecMergeJoin((MergeJoinState *) node);
break; break;
case T_Hash: case T_HashJoinState:
result = ExecHash((Hash *) node); result = ExecHashJoin((HashJoinState *) node);
break;
case T_HashJoin:
result = ExecHashJoin((HashJoin *) node);
break; break;
/* /*
* materialization nodes * materialization nodes
*/ */
case T_Material: case T_MaterialState:
result = ExecMaterial((Material *) node); result = ExecMaterial((MaterialState *) node);
break; break;
case T_Sort: case T_SortState:
result = ExecSort((Sort *) node); result = ExecSort((SortState *) node);
break; break;
case T_Unique: case T_GroupState:
result = ExecUnique((Unique *) node); result = ExecGroup((GroupState *) node);
break; break;
case T_SetOp: case T_AggState:
result = ExecSetOp((SetOp *) node); result = ExecAgg((AggState *) node);
break; break;
case T_Limit: case T_UniqueState:
result = ExecLimit((Limit *) node); result = ExecUnique((UniqueState *) node);
break; break;
case T_Group: case T_HashState:
result = ExecGroup((Group *) node); result = ExecHash((HashState *) node);
break; break;
case T_Agg: case T_SetOpState:
result = ExecAgg((Agg *) node); result = ExecSetOp((SetOpState *) node);
break;
case T_LimitState:
result = ExecLimit((LimitState *) node);
break; break;
default: default:
...@@ -370,10 +381,16 @@ ExecProcNode(Plan *node, Plan *parent) ...@@ -370,10 +381,16 @@ ExecProcNode(Plan *node, Plan *parent)
return result; return result;
} }
/*
* ExecCountSlotsNode - count up the number of tuple table slots needed
*
* Note that this scans a Plan tree, not a PlanState tree, because we
* haven't built the PlanState tree yet ...
*/
int int
ExecCountSlotsNode(Plan *node) ExecCountSlotsNode(Plan *node)
{ {
if (node == (Plan *) NULL) if (node == NULL)
return 0; return 0;
switch (nodeTag(node)) switch (nodeTag(node))
...@@ -414,9 +431,6 @@ ExecCountSlotsNode(Plan *node) ...@@ -414,9 +431,6 @@ ExecCountSlotsNode(Plan *node)
case T_MergeJoin: case T_MergeJoin:
return ExecCountSlotsMergeJoin((MergeJoin *) node); return ExecCountSlotsMergeJoin((MergeJoin *) node);
case T_Hash:
return ExecCountSlotsHash((Hash *) node);
case T_HashJoin: case T_HashJoin:
return ExecCountSlotsHashJoin((HashJoin *) node); return ExecCountSlotsHashJoin((HashJoin *) node);
...@@ -429,26 +443,30 @@ ExecCountSlotsNode(Plan *node) ...@@ -429,26 +443,30 @@ ExecCountSlotsNode(Plan *node)
case T_Sort: case T_Sort:
return ExecCountSlotsSort((Sort *) node); return ExecCountSlotsSort((Sort *) node);
case T_Group:
return ExecCountSlotsGroup((Group *) node);
case T_Agg:
return ExecCountSlotsAgg((Agg *) node);
case T_Unique: case T_Unique:
return ExecCountSlotsUnique((Unique *) node); return ExecCountSlotsUnique((Unique *) node);
case T_Hash:
return ExecCountSlotsHash((Hash *) node);
case T_SetOp: case T_SetOp:
return ExecCountSlotsSetOp((SetOp *) node); return ExecCountSlotsSetOp((SetOp *) node);
case T_Limit: case T_Limit:
return ExecCountSlotsLimit((Limit *) node); return ExecCountSlotsLimit((Limit *) node);
case T_Group:
return ExecCountSlotsGroup((Group *) node);
case T_Agg:
return ExecCountSlotsAgg((Agg *) node);
default: default:
elog(ERROR, "ExecCountSlotsNode: node type %d unsupported", elog(ERROR, "ExecCountSlotsNode: node type %d unsupported",
(int) nodeTag(node)); (int) nodeTag(node));
break; break;
} }
return 0; return 0;
} }
...@@ -464,7 +482,7 @@ ExecCountSlotsNode(Plan *node) ...@@ -464,7 +482,7 @@ ExecCountSlotsNode(Plan *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecEndNode(Plan *node, Plan *parent) ExecEndNode(PlanState *node)
{ {
List *subp; List *subp;
...@@ -474,14 +492,19 @@ ExecEndNode(Plan *node, Plan *parent) ...@@ -474,14 +492,19 @@ ExecEndNode(Plan *node, Plan *parent)
if (node == NULL) if (node == NULL)
return; return;
if (node->instrument)
InstrEndLoop(node->instrument);
/* Clean up initPlans and subPlans */
foreach(subp, node->initPlan) foreach(subp, node->initPlan)
ExecEndSubPlan((SubPlan *) lfirst(subp)); ExecEndSubPlan((SubPlanState *) lfirst(subp));
foreach(subp, node->subPlan) foreach(subp, node->subPlan)
ExecEndSubPlan((SubPlan *) lfirst(subp)); ExecEndSubPlan((SubPlanState *) lfirst(subp));
if (node->chgParam != NULL)
if (node->chgParam != NIL)
{ {
freeList(node->chgParam); freeList(node->chgParam);
node->chgParam = NULL; node->chgParam = NIL;
} }
switch (nodeTag(node)) switch (nodeTag(node))
...@@ -489,85 +512,85 @@ ExecEndNode(Plan *node, Plan *parent) ...@@ -489,85 +512,85 @@ ExecEndNode(Plan *node, Plan *parent)
/* /*
* control nodes * control nodes
*/ */
case T_Result: case T_ResultState:
ExecEndResult((Result *) node); ExecEndResult((ResultState *) node);
break; break;
case T_Append: case T_AppendState:
ExecEndAppend((Append *) node); ExecEndAppend((AppendState *) node);
break; break;
/* /*
* scan nodes * scan nodes
*/ */
case T_SeqScan: case T_SeqScanState:
ExecEndSeqScan((SeqScan *) node); ExecEndSeqScan((SeqScanState *) node);
break; break;
case T_IndexScan: case T_IndexScanState:
ExecEndIndexScan((IndexScan *) node); ExecEndIndexScan((IndexScanState *) node);
break; break;
case T_TidScan: case T_TidScanState:
ExecEndTidScan((TidScan *) node); ExecEndTidScan((TidScanState *) node);
break; break;
case T_SubqueryScan: case T_SubqueryScanState:
ExecEndSubqueryScan((SubqueryScan *) node); ExecEndSubqueryScan((SubqueryScanState *) node);
break; break;
case T_FunctionScan: case T_FunctionScanState:
ExecEndFunctionScan((FunctionScan *) node); ExecEndFunctionScan((FunctionScanState *) node);
break; break;
/* /*
* join nodes * join nodes
*/ */
case T_NestLoop: case T_NestLoopState:
ExecEndNestLoop((NestLoop *) node); ExecEndNestLoop((NestLoopState *) node);
break; break;
case T_MergeJoin: case T_MergeJoinState:
ExecEndMergeJoin((MergeJoin *) node); ExecEndMergeJoin((MergeJoinState *) node);
break; break;
case T_Hash: case T_HashJoinState:
ExecEndHash((Hash *) node); ExecEndHashJoin((HashJoinState *) node);
break;
case T_HashJoin:
ExecEndHashJoin((HashJoin *) node);
break; break;
/* /*
* materialization nodes * materialization nodes
*/ */
case T_Material: case T_MaterialState:
ExecEndMaterial((Material *) node); ExecEndMaterial((MaterialState *) node);
break; break;
case T_Sort: case T_SortState:
ExecEndSort((Sort *) node); ExecEndSort((SortState *) node);
break; break;
case T_Unique: case T_GroupState:
ExecEndUnique((Unique *) node); ExecEndGroup((GroupState *) node);
break; break;
case T_SetOp: case T_AggState:
ExecEndSetOp((SetOp *) node); ExecEndAgg((AggState *) node);
break; break;
case T_Limit: case T_UniqueState:
ExecEndLimit((Limit *) node); ExecEndUnique((UniqueState *) node);
break; break;
case T_Group: case T_HashState:
ExecEndGroup((Group *) node); ExecEndHash((HashState *) node);
break; break;
case T_Agg: case T_SetOpState:
ExecEndAgg((Agg *) node); ExecEndSetOp((SetOpState *) node);
break;
case T_LimitState:
ExecEndLimit((LimitState *) node);
break; break;
default: default:
...@@ -575,9 +598,6 @@ ExecEndNode(Plan *node, Plan *parent) ...@@ -575,9 +598,6 @@ ExecEndNode(Plan *node, Plan *parent)
(int) nodeTag(node)); (int) nodeTag(node));
break; break;
} }
if (node->instrument)
InstrEndLoop(node->instrument);
} }
...@@ -592,7 +612,7 @@ ExecEndNode(Plan *node, Plan *parent) ...@@ -592,7 +612,7 @@ ExecEndNode(Plan *node, Plan *parent)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
TupleDesc TupleDesc
ExecGetTupType(Plan *node) ExecGetTupType(PlanState *node)
{ {
TupleTableSlot *slot; TupleTableSlot *slot;
...@@ -601,147 +621,147 @@ ExecGetTupType(Plan *node) ...@@ -601,147 +621,147 @@ ExecGetTupType(Plan *node)
switch (nodeTag(node)) switch (nodeTag(node))
{ {
case T_Result: case T_ResultState:
{ {
ResultState *resstate = ((Result *) node)->resstate; ResultState *resstate = (ResultState *) node;
slot = resstate->cstate.cs_ResultTupleSlot; slot = resstate->ps.ps_ResultTupleSlot;
} }
break; break;
case T_SeqScan: case T_AppendState:
{ {
CommonScanState *scanstate = ((SeqScan *) node)->scanstate; AppendState *appendstate = (AppendState *) node;
slot = scanstate->cstate.cs_ResultTupleSlot; slot = appendstate->ps.ps_ResultTupleSlot;
} }
break; break;
case T_NestLoop: case T_SeqScanState:
{ {
NestLoopState *nlstate = ((NestLoop *) node)->nlstate; SeqScanState *scanstate = (SeqScanState *) node;
slot = nlstate->jstate.cs_ResultTupleSlot; slot = scanstate->ps.ps_ResultTupleSlot;
} }
break; break;
case T_Append: case T_IndexScanState:
{ {
AppendState *appendstate = ((Append *) node)->appendstate; IndexScanState *scanstate = (IndexScanState *) node;
slot = appendstate->cstate.cs_ResultTupleSlot; slot = scanstate->ss.ps.ps_ResultTupleSlot;
} }
break; break;
case T_IndexScan: case T_TidScanState:
{ {
CommonScanState *scanstate = ((IndexScan *) node)->scan.scanstate; TidScanState *scanstate = (TidScanState *) node;
slot = scanstate->cstate.cs_ResultTupleSlot; slot = scanstate->ss.ps.ps_ResultTupleSlot;
} }
break; break;
case T_TidScan: case T_SubqueryScanState:
{ {
CommonScanState *scanstate = ((TidScan *) node)->scan.scanstate; SubqueryScanState *scanstate = (SubqueryScanState *) node;
slot = scanstate->cstate.cs_ResultTupleSlot; slot = scanstate->ss.ps.ps_ResultTupleSlot;
} }
break; break;
case T_SubqueryScan: case T_FunctionScanState:
{ {
CommonScanState *scanstate = ((SubqueryScan *) node)->scan.scanstate; FunctionScanState *scanstate = (FunctionScanState *) node;
slot = scanstate->cstate.cs_ResultTupleSlot; slot = scanstate->ss.ps.ps_ResultTupleSlot;
} }
break; break;
case T_FunctionScan: case T_NestLoopState:
{ {
CommonScanState *scanstate = ((FunctionScan *) node)->scan.scanstate; NestLoopState *nlstate = (NestLoopState *) node;
slot = scanstate->cstate.cs_ResultTupleSlot; slot = nlstate->js.ps.ps_ResultTupleSlot;
} }
break; break;
case T_Material: case T_MergeJoinState:
{ {
MaterialState *matstate = ((Material *) node)->matstate; MergeJoinState *mergestate = (MergeJoinState *) node;
slot = matstate->csstate.css_ScanTupleSlot; slot = mergestate->js.ps.ps_ResultTupleSlot;
} }
break; break;
case T_Sort: case T_HashJoinState:
{ {
SortState *sortstate = ((Sort *) node)->sortstate; HashJoinState *hashjoinstate = (HashJoinState *) node;
slot = sortstate->csstate.css_ScanTupleSlot; slot = hashjoinstate->js.ps.ps_ResultTupleSlot;
} }
break; break;
case T_Agg: case T_MaterialState:
{ {
AggState *aggstate = ((Agg *) node)->aggstate; MaterialState *matstate = (MaterialState *) node;
slot = aggstate->csstate.cstate.cs_ResultTupleSlot; slot = matstate->ss.ss_ScanTupleSlot;
} }
break; break;
case T_Group: case T_SortState:
{ {
GroupState *grpstate = ((Group *) node)->grpstate; SortState *sortstate = (SortState *) node;
slot = grpstate->csstate.cstate.cs_ResultTupleSlot; slot = sortstate->ss.ss_ScanTupleSlot;
} }
break; break;
case T_Hash: case T_GroupState:
{ {
HashState *hashstate = ((Hash *) node)->hashstate; GroupState *grpstate = (GroupState *) node;
slot = hashstate->cstate.cs_ResultTupleSlot; slot = grpstate->ss.ps.ps_ResultTupleSlot;
} }
break; break;
case T_Unique: case T_AggState:
{ {
UniqueState *uniquestate = ((Unique *) node)->uniquestate; AggState *aggstate = (AggState *) node;
slot = uniquestate->cstate.cs_ResultTupleSlot; slot = aggstate->ss.ps.ps_ResultTupleSlot;
} }
break; break;
case T_SetOp: case T_UniqueState:
{ {
SetOpState *setopstate = ((SetOp *) node)->setopstate; UniqueState *uniquestate = (UniqueState *) node;
slot = setopstate->cstate.cs_ResultTupleSlot; slot = uniquestate->ps.ps_ResultTupleSlot;
} }
break; break;
case T_Limit: case T_HashState:
{ {
LimitState *limitstate = ((Limit *) node)->limitstate; HashState *hashstate = (HashState *) node;
slot = limitstate->cstate.cs_ResultTupleSlot; slot = hashstate->ps.ps_ResultTupleSlot;
} }
break; break;
case T_MergeJoin: case T_SetOpState:
{ {
MergeJoinState *mergestate = ((MergeJoin *) node)->mergestate; SetOpState *setopstate = (SetOpState *) node;
slot = mergestate->jstate.cs_ResultTupleSlot; slot = setopstate->ps.ps_ResultTupleSlot;
} }
break; break;
case T_HashJoin: case T_LimitState:
{ {
HashJoinState *hashjoinstate = ((HashJoin *) node)->hashjoinstate; LimitState *limitstate = (LimitState *) node;
slot = hashjoinstate->jstate.cs_ResultTupleSlot; slot = limitstate->ps.ps_ResultTupleSlot;
} }
break; break;
......
...@@ -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)
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.97 2002/11/29 21:39:11 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.98 2002/12/05 15:50:32 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -212,11 +212,12 @@ static void finalize_aggregate(AggState *aggstate, ...@@ -212,11 +212,12 @@ static void finalize_aggregate(AggState *aggstate,
AggStatePerAgg peraggstate, AggStatePerAgg peraggstate,
AggStatePerGroup pergroupstate, AggStatePerGroup pergroupstate,
Datum *resultVal, bool *resultIsNull); Datum *resultVal, bool *resultIsNull);
static void build_hash_table(Agg *node); static void build_hash_table(AggState *aggstate);
static AggHashEntry lookup_hash_entry(Agg *node, TupleTableSlot *slot); static AggHashEntry lookup_hash_entry(AggState *aggstate,
static TupleTableSlot *agg_retrieve_direct(Agg *node); TupleTableSlot *slot);
static void agg_fill_hash_table(Agg *node); static TupleTableSlot *agg_retrieve_direct(AggState *aggstate);
static TupleTableSlot *agg_retrieve_hash_table(Agg *node); static void agg_fill_hash_table(AggState *aggstate);
static TupleTableSlot *agg_retrieve_hash_table(AggState *aggstate);
static Datum GetAggInitVal(Datum textInitVal, Oid transtype); static Datum GetAggInitVal(Datum textInitVal, Oid transtype);
...@@ -521,7 +522,7 @@ finalize_aggregate(AggState *aggstate, ...@@ -521,7 +522,7 @@ finalize_aggregate(AggState *aggstate,
{ {
MemoryContext oldContext; MemoryContext oldContext;
oldContext = MemoryContextSwitchTo(aggstate->csstate.cstate.cs_ExprContext->ecxt_per_tuple_memory); oldContext = MemoryContextSwitchTo(aggstate->ss.ps.ps_ExprContext->ecxt_per_tuple_memory);
/* /*
* Apply the agg's finalfn if one is provided, else return transValue. * Apply the agg's finalfn if one is provided, else return transValue.
...@@ -572,9 +573,9 @@ finalize_aggregate(AggState *aggstate, ...@@ -572,9 +573,9 @@ finalize_aggregate(AggState *aggstate,
* The hash table always lives in the aggcontext memory context. * The hash table always lives in the aggcontext memory context.
*/ */
static void static void
build_hash_table(Agg *node) build_hash_table(AggState *aggstate)
{ {
AggState *aggstate = node->aggstate; Agg *node = (Agg *) aggstate->ss.ps.plan;
AggHashTable hashtable; AggHashTable hashtable;
Size tabsize; Size tabsize;
...@@ -596,9 +597,9 @@ build_hash_table(Agg *node) ...@@ -596,9 +597,9 @@ build_hash_table(Agg *node)
* When called, CurrentMemoryContext should be the per-query context. * When called, CurrentMemoryContext should be the per-query context.
*/ */
static AggHashEntry static AggHashEntry
lookup_hash_entry(Agg *node, TupleTableSlot *slot) lookup_hash_entry(AggState *aggstate, TupleTableSlot *slot)
{ {
AggState *aggstate = node->aggstate; Agg *node = (Agg *) aggstate->ss.ps.plan;
AggHashTable hashtable = aggstate->hashtable; AggHashTable hashtable = aggstate->hashtable;
MemoryContext tmpmem = aggstate->tmpcontext->ecxt_per_tuple_memory; MemoryContext tmpmem = aggstate->tmpcontext->ecxt_per_tuple_memory;
HeapTuple tuple = slot->val; HeapTuple tuple = slot->val;
...@@ -684,16 +685,14 @@ lookup_hash_entry(Agg *node, TupleTableSlot *slot) ...@@ -684,16 +685,14 @@ lookup_hash_entry(Agg *node, TupleTableSlot *slot)
* the result tuple. * the result tuple.
*/ */
TupleTableSlot * TupleTableSlot *
ExecAgg(Agg *node) ExecAgg(AggState *node)
{ {
AggState *aggstate = node->aggstate; if (node->agg_done)
if (aggstate->agg_done)
return NULL; return NULL;
if (node->aggstrategy == AGG_HASHED) if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
{ {
if (!aggstate->table_filled) if (!node->table_filled)
agg_fill_hash_table(node); agg_fill_hash_table(node);
return agg_retrieve_hash_table(node); return agg_retrieve_hash_table(node);
} }
...@@ -707,10 +706,10 @@ ExecAgg(Agg *node) ...@@ -707,10 +706,10 @@ ExecAgg(Agg *node)
* ExecAgg for non-hashed case * ExecAgg for non-hashed case
*/ */
static TupleTableSlot * static TupleTableSlot *
agg_retrieve_direct(Agg *node) agg_retrieve_direct(AggState *aggstate)
{ {
AggState *aggstate; Agg *node = (Agg *) aggstate->ss.ps.plan;
Plan *outerPlan; PlanState *outerPlan;
ExprContext *econtext; ExprContext *econtext;
ExprContext *tmpcontext; ExprContext *tmpcontext;
ProjectionInfo *projInfo; ProjectionInfo *projInfo;
...@@ -726,22 +725,21 @@ agg_retrieve_direct(Agg *node) ...@@ -726,22 +725,21 @@ agg_retrieve_direct(Agg *node)
/* /*
* get state info from node * get state info from node
*/ */
aggstate = node->aggstate; outerPlan = outerPlanState(aggstate);
outerPlan = outerPlan(node);
/* econtext is the per-output-tuple expression context */ /* econtext is the per-output-tuple expression context */
econtext = aggstate->csstate.cstate.cs_ExprContext; econtext = aggstate->ss.ps.ps_ExprContext;
aggvalues = econtext->ecxt_aggvalues; aggvalues = econtext->ecxt_aggvalues;
aggnulls = econtext->ecxt_aggnulls; aggnulls = econtext->ecxt_aggnulls;
/* tmpcontext is the per-input-tuple expression context */ /* tmpcontext is the per-input-tuple expression context */
tmpcontext = aggstate->tmpcontext; tmpcontext = aggstate->tmpcontext;
projInfo = aggstate->csstate.cstate.cs_ProjInfo; projInfo = aggstate->ss.ps.ps_ProjInfo;
peragg = aggstate->peragg; peragg = aggstate->peragg;
pergroup = aggstate->pergroup; pergroup = aggstate->pergroup;
firstSlot = aggstate->csstate.css_ScanTupleSlot; firstSlot = aggstate->ss.ss_ScanTupleSlot;
/* /*
* We loop retrieving groups until we find one matching * We loop retrieving groups until we find one matching
* node->plan.qual * aggstate->ss.ps.qual
*/ */
do do
{ {
...@@ -754,7 +752,7 @@ agg_retrieve_direct(Agg *node) ...@@ -754,7 +752,7 @@ agg_retrieve_direct(Agg *node)
*/ */
if (aggstate->grp_firstTuple == NULL) if (aggstate->grp_firstTuple == NULL)
{ {
outerslot = ExecProcNode(outerPlan, (Plan *) node); outerslot = ExecProcNode(outerPlan);
if (!TupIsNull(outerslot)) if (!TupIsNull(outerslot))
{ {
/* /*
...@@ -810,7 +808,7 @@ agg_retrieve_direct(Agg *node) ...@@ -810,7 +808,7 @@ agg_retrieve_direct(Agg *node)
/* Reset per-input-tuple context after each tuple */ /* Reset per-input-tuple context after each tuple */
ResetExprContext(tmpcontext); ResetExprContext(tmpcontext);
outerslot = ExecProcNode(outerPlan, (Plan *) node); outerslot = ExecProcNode(outerPlan);
if (TupIsNull(outerslot)) if (TupIsNull(outerslot))
{ {
/* no more outer-plan tuples available */ /* no more outer-plan tuples available */
...@@ -917,7 +915,7 @@ agg_retrieve_direct(Agg *node) ...@@ -917,7 +915,7 @@ agg_retrieve_direct(Agg *node)
* Otherwise, return the tuple. * Otherwise, return the tuple.
*/ */
} }
while (!ExecQual(node->plan.qual, econtext, false)); while (!ExecQual(aggstate->ss.ps.qual, econtext, false));
return resultSlot; return resultSlot;
} }
...@@ -926,10 +924,9 @@ agg_retrieve_direct(Agg *node) ...@@ -926,10 +924,9 @@ agg_retrieve_direct(Agg *node)
* ExecAgg for hashed case: phase 1, read input and build hash table * ExecAgg for hashed case: phase 1, read input and build hash table
*/ */
static void static void
agg_fill_hash_table(Agg *node) agg_fill_hash_table(AggState *aggstate)
{ {
AggState *aggstate; PlanState *outerPlan;
Plan *outerPlan;
ExprContext *tmpcontext; ExprContext *tmpcontext;
AggHashEntry entry; AggHashEntry entry;
TupleTableSlot *outerslot; TupleTableSlot *outerslot;
...@@ -937,8 +934,7 @@ agg_fill_hash_table(Agg *node) ...@@ -937,8 +934,7 @@ agg_fill_hash_table(Agg *node)
/* /*
* get state info from node * get state info from node
*/ */
aggstate = node->aggstate; outerPlan = outerPlanState(aggstate);
outerPlan = outerPlan(node);
/* tmpcontext is the per-input-tuple expression context */ /* tmpcontext is the per-input-tuple expression context */
tmpcontext = aggstate->tmpcontext; tmpcontext = aggstate->tmpcontext;
...@@ -948,14 +944,14 @@ agg_fill_hash_table(Agg *node) ...@@ -948,14 +944,14 @@ agg_fill_hash_table(Agg *node)
*/ */
for (;;) for (;;)
{ {
outerslot = ExecProcNode(outerPlan, (Plan *) node); outerslot = ExecProcNode(outerPlan);
if (TupIsNull(outerslot)) if (TupIsNull(outerslot))
break; break;
/* set up for advance_aggregates call */ /* set up for advance_aggregates call */
tmpcontext->ecxt_scantuple = outerslot; tmpcontext->ecxt_scantuple = outerslot;
/* Find or build hashtable entry for this tuple's group */ /* Find or build hashtable entry for this tuple's group */
entry = lookup_hash_entry(node, outerslot); entry = lookup_hash_entry(aggstate, outerslot);
/* Advance the aggregates */ /* Advance the aggregates */
advance_aggregates(aggstate, entry->pergroup); advance_aggregates(aggstate, entry->pergroup);
...@@ -974,9 +970,8 @@ agg_fill_hash_table(Agg *node) ...@@ -974,9 +970,8 @@ agg_fill_hash_table(Agg *node)
* ExecAgg for hashed case: phase 2, retrieving groups from hash table * ExecAgg for hashed case: phase 2, retrieving groups from hash table
*/ */
static TupleTableSlot * static TupleTableSlot *
agg_retrieve_hash_table(Agg *node) agg_retrieve_hash_table(AggState *aggstate)
{ {
AggState *aggstate;
ExprContext *econtext; ExprContext *econtext;
ProjectionInfo *projInfo; ProjectionInfo *projInfo;
Datum *aggvalues; Datum *aggvalues;
...@@ -992,19 +987,18 @@ agg_retrieve_hash_table(Agg *node) ...@@ -992,19 +987,18 @@ agg_retrieve_hash_table(Agg *node)
/* /*
* get state info from node * get state info from node
*/ */
aggstate = node->aggstate;
/* econtext is the per-output-tuple expression context */ /* econtext is the per-output-tuple expression context */
econtext = aggstate->csstate.cstate.cs_ExprContext; econtext = aggstate->ss.ps.ps_ExprContext;
aggvalues = econtext->ecxt_aggvalues; aggvalues = econtext->ecxt_aggvalues;
aggnulls = econtext->ecxt_aggnulls; aggnulls = econtext->ecxt_aggnulls;
projInfo = aggstate->csstate.cstate.cs_ProjInfo; projInfo = aggstate->ss.ps.ps_ProjInfo;
peragg = aggstate->peragg; peragg = aggstate->peragg;
hashtable = aggstate->hashtable; hashtable = aggstate->hashtable;
firstSlot = aggstate->csstate.css_ScanTupleSlot; firstSlot = aggstate->ss.ss_ScanTupleSlot;
/* /*
* We loop retrieving groups until we find one matching * We loop retrieving groups until we find one satisfying
* node->plan.qual * aggstate->ss.ps.qual
*/ */
do do
{ {
...@@ -1071,7 +1065,7 @@ agg_retrieve_hash_table(Agg *node) ...@@ -1071,7 +1065,7 @@ agg_retrieve_hash_table(Agg *node)
* Otherwise, return the tuple. * Otherwise, return the tuple.
*/ */
} }
while (!ExecQual(node->plan.qual, econtext, false)); while (!ExecQual(aggstate->ss.ps.qual, econtext, false));
return resultSlot; return resultSlot;
} }
...@@ -1083,8 +1077,8 @@ agg_retrieve_hash_table(Agg *node) ...@@ -1083,8 +1077,8 @@ agg_retrieve_hash_table(Agg *node)
* planner and initializes its outer subtree * planner and initializes its outer subtree
* ----------------- * -----------------
*/ */
bool AggState *
ExecInitAgg(Agg *node, EState *estate, Plan *parent) ExecInitAgg(Agg *node, EState *estate)
{ {
AggState *aggstate; AggState *aggstate;
AggStatePerAgg peragg; AggStatePerAgg peragg;
...@@ -1094,16 +1088,15 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent) ...@@ -1094,16 +1088,15 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
aggno; aggno;
List *alist; List *alist;
/*
* assign the node's execution state
*/
node->plan.state = estate;
/* /*
* create state structure * create state structure
*/ */
aggstate = makeNode(AggState); aggstate = makeNode(AggState);
node->aggstate = aggstate; aggstate->ss.ps.plan = (Plan *) node;
aggstate->ss.ps.state = estate;
aggstate->aggs = NIL;
aggstate->numaggs = 0;
aggstate->eqfunctions = NULL; aggstate->eqfunctions = NULL;
aggstate->peragg = NULL; aggstate->peragg = NULL;
aggstate->agg_done = false; aggstate->agg_done = false;
...@@ -1111,38 +1104,14 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent) ...@@ -1111,38 +1104,14 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
aggstate->grp_firstTuple = NULL; aggstate->grp_firstTuple = NULL;
aggstate->hashtable = NULL; aggstate->hashtable = NULL;
/*
* find aggregates in targetlist and quals
*
* Note: pull_agg_clauses also checks that no aggs contain other agg
* calls in their arguments. This would make no sense under SQL
* semantics anyway (and it's forbidden by the spec). Because that is
* true, we don't need to worry about evaluating the aggs in any
* particular order.
*/
aggstate->aggs = nconc(pull_agg_clause((Node *) node->plan.targetlist),
pull_agg_clause((Node *) node->plan.qual));
aggstate->numaggs = numaggs = length(aggstate->aggs);
if (numaggs <= 0)
{
/*
* This is not an error condition: we might be using the Agg node just
* to do hash-based grouping. Even in the regular case,
* constant-expression simplification could optimize away all of the
* Aggrefs in the targetlist and qual. So keep going, but force local
* copy of numaggs positive so that palloc()s below don't choke.
*/
numaggs = 1;
}
/* /*
* Create expression contexts. We need two, one for per-input-tuple * Create expression contexts. We need two, one for per-input-tuple
* processing and one for per-output-tuple processing. We cheat a little * processing and one for per-output-tuple processing. We cheat a little
* by using ExecAssignExprContext() to build both. * by using ExecAssignExprContext() to build both.
*/ */
ExecAssignExprContext(estate, &aggstate->csstate.cstate); ExecAssignExprContext(estate, &aggstate->ss.ps);
aggstate->tmpcontext = aggstate->csstate.cstate.cs_ExprContext; aggstate->tmpcontext = aggstate->ss.ps.ps_ExprContext;
ExecAssignExprContext(estate, &aggstate->csstate.cstate); ExecAssignExprContext(estate, &aggstate->ss.ps);
/* /*
* We also need a long-lived memory context for holding hashtable * We also need a long-lived memory context for holding hashtable
...@@ -1163,14 +1132,64 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent) ...@@ -1163,14 +1132,64 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
/* /*
* tuple table initialization * tuple table initialization
*/ */
ExecInitScanTupleSlot(estate, &aggstate->csstate); ExecInitScanTupleSlot(estate, &aggstate->ss);
ExecInitResultTupleSlot(estate, &aggstate->csstate.cstate); ExecInitResultTupleSlot(estate, &aggstate->ss.ps);
/*
* initialize child expressions
*
* Note: ExecInitExpr finds Aggrefs for us, and also checks that no aggs
* contain other agg calls in their arguments. This would make no sense
* under SQL semantics anyway (and it's forbidden by the spec). Because
* that is true, we don't need to worry about evaluating the aggs in any
* particular order.
*/
aggstate->ss.ps.targetlist = (List *)
ExecInitExpr((Node *) node->plan.targetlist,
(PlanState *) aggstate);
aggstate->ss.ps.qual = (List *)
ExecInitExpr((Node *) node->plan.qual,
(PlanState *) aggstate);
/*
* initialize child nodes
*/
outerPlan = outerPlan(node);
outerPlanState(aggstate) = ExecInitNode(outerPlan, estate);
/*
* initialize source tuple type.
*/
ExecAssignScanTypeFromOuterPlan(&aggstate->ss);
/*
* Initialize result tuple type and projection info.
*/
ExecAssignResultTypeFromTL(&aggstate->ss.ps);
ExecAssignProjectionInfo(&aggstate->ss.ps);
/*
* get the count of aggregates in targetlist and quals
*/
numaggs = aggstate->numaggs;
Assert(numaggs == length(aggstate->aggs));
if (numaggs <= 0)
{
/*
* This is not an error condition: we might be using the Agg node just
* to do hash-based grouping. Even in the regular case,
* constant-expression simplification could optimize away all of the
* Aggrefs in the targetlist and qual. So keep going, but force local
* copy of numaggs positive so that palloc()s below don't choke.
*/
numaggs = 1;
}
/* /*
* Set up aggregate-result storage in the output expr context, and also * Set up aggregate-result storage in the output expr context, and also
* allocate my private per-agg working storage * allocate my private per-agg working storage
*/ */
econtext = aggstate->csstate.cstate.cs_ExprContext; econtext = aggstate->ss.ps.ps_ExprContext;
econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs); econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs);
econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs); econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs);
...@@ -1179,7 +1198,7 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent) ...@@ -1179,7 +1198,7 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
if (node->aggstrategy == AGG_HASHED) if (node->aggstrategy == AGG_HASHED)
{ {
build_hash_table(node); build_hash_table(aggstate);
aggstate->table_filled = false; aggstate->table_filled = false;
} }
else else
...@@ -1190,30 +1209,13 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent) ...@@ -1190,30 +1209,13 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
aggstate->pergroup = pergroup; aggstate->pergroup = pergroup;
} }
/*
* initialize child nodes
*/
outerPlan = outerPlan(node);
ExecInitNode(outerPlan, estate, (Plan *) node);
/*
* initialize source tuple type.
*/
ExecAssignScanTypeFromOuterPlan((Plan *) node, &aggstate->csstate);
/*
* Initialize result tuple type and projection info.
*/
ExecAssignResultTypeFromTL((Plan *) node, &aggstate->csstate.cstate);
ExecAssignProjectionInfo((Plan *) node, &aggstate->csstate.cstate);
/* /*
* If we are grouping, precompute fmgr lookup data for inner loop * If we are grouping, precompute fmgr lookup data for inner loop
*/ */
if (node->numCols > 0) if (node->numCols > 0)
{ {
aggstate->eqfunctions = aggstate->eqfunctions =
execTuplesMatchPrepare(ExecGetScanType(&aggstate->csstate), execTuplesMatchPrepare(ExecGetScanType(&aggstate->ss),
node->numCols, node->numCols,
node->grpColIdx); node->grpColIdx);
} }
...@@ -1330,7 +1332,7 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent) ...@@ -1330,7 +1332,7 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent)
ReleaseSysCache(aggTuple); ReleaseSysCache(aggTuple);
} }
return TRUE; return aggstate;
} }
static Datum static Datum
...@@ -1372,84 +1374,82 @@ ExecCountSlotsAgg(Agg *node) ...@@ -1372,84 +1374,82 @@ ExecCountSlotsAgg(Agg *node)
} }
void void
ExecEndAgg(Agg *node) ExecEndAgg(AggState *node)
{ {
AggState *aggstate = node->aggstate; PlanState *outerPlan;
Plan *outerPlan;
int aggno; int aggno;
/* Make sure we have closed any open tuplesorts */ /* Make sure we have closed any open tuplesorts */
for (aggno = 0; aggno < aggstate->numaggs; aggno++) for (aggno = 0; aggno < node->numaggs; aggno++)
{ {
AggStatePerAgg peraggstate = &aggstate->peragg[aggno]; AggStatePerAgg peraggstate = &node->peragg[aggno];
if (peraggstate->sortstate) if (peraggstate->sortstate)
tuplesort_end(peraggstate->sortstate); tuplesort_end(peraggstate->sortstate);
} }
ExecFreeProjectionInfo(&aggstate->csstate.cstate); ExecFreeProjectionInfo(&node->ss.ps);
/* /*
* Free both the expr contexts. * Free both the expr contexts.
*/ */
ExecFreeExprContext(&aggstate->csstate.cstate); ExecFreeExprContext(&node->ss.ps);
aggstate->csstate.cstate.cs_ExprContext = aggstate->tmpcontext; node->ss.ps.ps_ExprContext = node->tmpcontext;
ExecFreeExprContext(&aggstate->csstate.cstate); ExecFreeExprContext(&node->ss.ps);
MemoryContextDelete(aggstate->aggcontext); MemoryContextDelete(node->aggcontext);
outerPlan = outerPlan(node); outerPlan = outerPlanState(node);
ExecEndNode(outerPlan, (Plan *) node); ExecEndNode(outerPlan);
/* clean up tuple table */ /* clean up tuple table */
ExecClearTuple(aggstate->csstate.css_ScanTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot);
if (aggstate->grp_firstTuple != NULL) if (node->grp_firstTuple != NULL)
{ {
heap_freetuple(aggstate->grp_firstTuple); heap_freetuple(node->grp_firstTuple);
aggstate->grp_firstTuple = NULL; node->grp_firstTuple = NULL;
} }
} }
void void
ExecReScanAgg(Agg *node, ExprContext *exprCtxt, Plan *parent) ExecReScanAgg(AggState *node, ExprContext *exprCtxt)
{ {
AggState *aggstate = node->aggstate; ExprContext *econtext = node->ss.ps.ps_ExprContext;
ExprContext *econtext = aggstate->csstate.cstate.cs_ExprContext;
int aggno; int aggno;
/* Make sure we have closed any open tuplesorts */ /* Make sure we have closed any open tuplesorts */
for (aggno = 0; aggno < aggstate->numaggs; aggno++) for (aggno = 0; aggno < node->numaggs; aggno++)
{ {
AggStatePerAgg peraggstate = &aggstate->peragg[aggno]; AggStatePerAgg peraggstate = &node->peragg[aggno];
if (peraggstate->sortstate) if (peraggstate->sortstate)
tuplesort_end(peraggstate->sortstate); tuplesort_end(peraggstate->sortstate);
peraggstate->sortstate = NULL; peraggstate->sortstate = NULL;
} }
aggstate->agg_done = false; node->agg_done = false;
if (aggstate->grp_firstTuple != NULL) if (node->grp_firstTuple != NULL)
{ {
heap_freetuple(aggstate->grp_firstTuple); heap_freetuple(node->grp_firstTuple);
aggstate->grp_firstTuple = NULL; node->grp_firstTuple = NULL;
} }
MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * aggstate->numaggs); MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numaggs);
MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * aggstate->numaggs); MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numaggs);
MemoryContextReset(aggstate->aggcontext); MemoryContextReset(node->aggcontext);
if (node->aggstrategy == AGG_HASHED) if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
{ {
build_hash_table(node); build_hash_table(node);
aggstate->table_filled = false; node->table_filled = false;
} }
/* /*
* if chgParam of subnode is not null then plan will be re-scanned by * 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 == NIL)
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/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);
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.42 2002/11/30 00:08:15 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.43 2002/12/05 15:50:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include "utils/memutils.h" #include "utils/memutils.h"
static TupleTableSlot *ExecHashJoinOuterGetTuple(Plan *node, Plan *parent, static TupleTableSlot *ExecHashJoinOuterGetTuple(PlanState *node,
HashJoinState *hjstate); HashJoinState *hjstate);
static TupleTableSlot *ExecHashJoinGetSavedTuple(HashJoinState *hjstate, static TupleTableSlot *ExecHashJoinGetSavedTuple(HashJoinState *hjstate,
BufFile *file, BufFile *file,
...@@ -41,12 +41,11 @@ static int ExecHashJoinNewBatch(HashJoinState *hjstate); ...@@ -41,12 +41,11 @@ static int ExecHashJoinNewBatch(HashJoinState *hjstate);
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
TupleTableSlot * /* return: a tuple or NULL */ TupleTableSlot * /* return: a tuple or NULL */
ExecHashJoin(HashJoin *node) ExecHashJoin(HashJoinState *node)
{ {
HashJoinState *hjstate;
EState *estate; EState *estate;
Plan *outerNode; PlanState *outerNode;
Hash *hashNode; HashState *hashNode;
List *hjclauses; List *hjclauses;
List *outerkeys; List *outerkeys;
List *joinqual; List *joinqual;
...@@ -65,37 +64,36 @@ ExecHashJoin(HashJoin *node) ...@@ -65,37 +64,36 @@ ExecHashJoin(HashJoin *node)
/* /*
* get information from HashJoin node * get information from HashJoin node
*/ */
hjstate = node->hashjoinstate;
hjclauses = node->hashclauses; hjclauses = node->hashclauses;
estate = node->join.plan.state; estate = node->js.ps.state;
joinqual = node->join.joinqual; joinqual = node->js.joinqual;
otherqual = node->join.plan.qual; otherqual = node->js.ps.qual;
hashNode = (Hash *) innerPlan(node); hashNode = (HashState *) innerPlanState(node);
outerNode = outerPlan(node); outerNode = outerPlanState(node);
hashPhaseDone = hjstate->hj_hashdone; hashPhaseDone = node->hj_hashdone;
dir = estate->es_direction; dir = estate->es_direction;
/* /*
* get information from HashJoin state * get information from HashJoin state
*/ */
hashtable = hjstate->hj_HashTable; hashtable = node->hj_HashTable;
outerkeys = hjstate->hj_OuterHashKeys; outerkeys = node->hj_OuterHashKeys;
econtext = hjstate->jstate.cs_ExprContext; econtext = node->js.ps.ps_ExprContext;
/* /*
* 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
* join tuple (because there is a function-returning-set in the * join 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 (hjstate->jstate.cs_TupFromTlist) if (node->js.ps.ps_TupFromTlist)
{ {
TupleTableSlot *result; TupleTableSlot *result;
result = ExecProject(hjstate->jstate.cs_ProjInfo, &isDone); result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
if (isDone == ExprMultipleResult) if (isDone == ExprMultipleResult)
return result; return result;
/* Done with that source tuple... */ /* Done with that source tuple... */
hjstate->jstate.cs_TupFromTlist = false; node->js.ps.ps_TupFromTlist = false;
} }
/* /*
...@@ -116,16 +114,16 @@ ExecHashJoin(HashJoin *node) ...@@ -116,16 +114,16 @@ ExecHashJoin(HashJoin *node)
/* /*
* create the hash table * create the hash table
*/ */
hashtable = ExecHashTableCreate(hashNode); hashtable = ExecHashTableCreate((Hash *) hashNode->ps.plan);
hjstate->hj_HashTable = hashtable; node->hj_HashTable = hashtable;
/* /*
* execute the Hash node, to build the hash table * execute the Hash node, to build the hash table
*/ */
hashNode->hashstate->hashtable = hashtable; hashNode->hashtable = hashtable;
innerTupleSlot = ExecProcNode((Plan *) hashNode, (Plan *) node); innerTupleSlot = ExecProcNode((PlanState *) hashNode);
} }
hjstate->hj_hashdone = true; node->hj_hashdone = true;
/* /*
* Open temp files for outer batches, if needed. Note that file * Open temp files for outer batches, if needed. Note that file
...@@ -140,40 +138,39 @@ ExecHashJoin(HashJoin *node) ...@@ -140,40 +138,39 @@ ExecHashJoin(HashJoin *node)
/* /*
* Now get an outer tuple and probe into the hash table for matches * Now get an outer tuple and probe into the hash table for matches
*/ */
outerTupleSlot = hjstate->jstate.cs_OuterTupleSlot; outerTupleSlot = node->js.ps.ps_OuterTupleSlot;
for (;;) for (;;)
{ {
/* /*
* If we don't have an outer tuple, get the next one * If we don't have an outer tuple, get the next one
*/ */
if (hjstate->hj_NeedNewOuter) if (node->hj_NeedNewOuter)
{ {
outerTupleSlot = ExecHashJoinOuterGetTuple(outerNode, outerTupleSlot = ExecHashJoinOuterGetTuple(outerNode,
(Plan *) node, node);
hjstate);
if (TupIsNull(outerTupleSlot)) if (TupIsNull(outerTupleSlot))
{ {
/* /*
* when the last batch runs out, clean up and exit * when the last batch runs out, clean up and exit
*/ */
ExecHashTableDestroy(hashtable); ExecHashTableDestroy(hashtable);
hjstate->hj_HashTable = NULL; node->hj_HashTable = NULL;
return NULL; return NULL;
} }
hjstate->jstate.cs_OuterTupleSlot = outerTupleSlot; node->js.ps.ps_OuterTupleSlot = outerTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot; econtext->ecxt_outertuple = outerTupleSlot;
hjstate->hj_NeedNewOuter = false; node->hj_NeedNewOuter = false;
hjstate->hj_MatchedOuter = false; node->hj_MatchedOuter = false;
/* /*
* now we have an outer tuple, find the corresponding bucket * now we have an outer tuple, find the corresponding bucket
* for this tuple from the hash table * for this tuple from the hash table
*/ */
hjstate->hj_CurBucketNo = ExecHashGetBucket(hashtable, econtext, node->hj_CurBucketNo = ExecHashGetBucket(hashtable, econtext,
outerkeys); outerkeys);
hjstate->hj_CurTuple = NULL; node->hj_CurTuple = NULL;
/* /*
* Now we've got an outer tuple and the corresponding hash * Now we've got an outer tuple and the corresponding hash
...@@ -182,7 +179,7 @@ ExecHashJoin(HashJoin *node) ...@@ -182,7 +179,7 @@ ExecHashJoin(HashJoin *node)
*/ */
if (hashtable->curbatch == 0) if (hashtable->curbatch == 0)
{ {
int batch = ExecHashJoinGetBatch(hjstate->hj_CurBucketNo, int batch = ExecHashJoinGetBatch(node->hj_CurBucketNo,
hashtable); hashtable);
if (batch > 0) if (batch > 0)
...@@ -196,7 +193,7 @@ ExecHashJoin(HashJoin *node) ...@@ -196,7 +193,7 @@ ExecHashJoin(HashJoin *node)
hashtable->outerBatchSize[batchno]++; hashtable->outerBatchSize[batchno]++;
ExecHashJoinSaveTuple(outerTupleSlot->val, ExecHashJoinSaveTuple(outerTupleSlot->val,
hashtable->outerBatchFile[batchno]); hashtable->outerBatchFile[batchno]);
hjstate->hj_NeedNewOuter = true; node->hj_NeedNewOuter = true;
continue; /* loop around for a new outer tuple */ continue; /* loop around for a new outer tuple */
} }
} }
...@@ -207,7 +204,7 @@ ExecHashJoin(HashJoin *node) ...@@ -207,7 +204,7 @@ ExecHashJoin(HashJoin *node)
*/ */
for (;;) for (;;)
{ {
curtuple = ExecScanHashBucket(hjstate, curtuple = ExecScanHashBucket(node,
hjclauses, hjclauses,
econtext); econtext);
if (curtuple == NULL) if (curtuple == NULL)
...@@ -217,7 +214,7 @@ ExecHashJoin(HashJoin *node) ...@@ -217,7 +214,7 @@ ExecHashJoin(HashJoin *node)
* we've got a match, but still need to test non-hashed quals * we've got a match, but still need to test non-hashed quals
*/ */
inntuple = ExecStoreTuple(curtuple, inntuple = ExecStoreTuple(curtuple,
hjstate->hj_HashTupleSlot, node->hj_HashTupleSlot,
InvalidBuffer, InvalidBuffer,
false); /* don't pfree this tuple */ false); /* don't pfree this tuple */
econtext->ecxt_innertuple = inntuple; econtext->ecxt_innertuple = inntuple;
...@@ -235,17 +232,17 @@ ExecHashJoin(HashJoin *node) ...@@ -235,17 +232,17 @@ ExecHashJoin(HashJoin *node)
*/ */
if (ExecQual(joinqual, econtext, false)) if (ExecQual(joinqual, econtext, false))
{ {
hjstate->hj_MatchedOuter = true; node->hj_MatchedOuter = true;
if (otherqual == NIL || ExecQual(otherqual, econtext, false)) if (otherqual == NIL || ExecQual(otherqual, econtext, false))
{ {
TupleTableSlot *result; TupleTableSlot *result;
result = ExecProject(hjstate->jstate.cs_ProjInfo, &isDone); result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
if (isDone != ExprEndResult) if (isDone != ExprEndResult)
{ {
hjstate->jstate.cs_TupFromTlist = node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult); (isDone == ExprMultipleResult);
return result; return result;
} }
...@@ -258,10 +255,10 @@ ExecHashJoin(HashJoin *node) ...@@ -258,10 +255,10 @@ ExecHashJoin(HashJoin *node)
* whether to emit a dummy outer-join tuple. If not, loop around * whether to emit a dummy outer-join tuple. If not, loop around
* to get a new outer tuple. * to get a new outer tuple.
*/ */
hjstate->hj_NeedNewOuter = true; node->hj_NeedNewOuter = true;
if (!hjstate->hj_MatchedOuter && if (!node->hj_MatchedOuter &&
node->join.jointype == JOIN_LEFT) node->js.jointype == JOIN_LEFT)
{ {
/* /*
* We are doing an outer join and there were no join matches * We are doing an outer join and there were no join matches
...@@ -269,7 +266,7 @@ ExecHashJoin(HashJoin *node) ...@@ -269,7 +266,7 @@ ExecHashJoin(HashJoin *node)
* nulls for the inner tuple, and return it if it passes the * nulls for the inner tuple, and return it if it passes the
* non-join quals. * non-join quals.
*/ */
econtext->ecxt_innertuple = hjstate->hj_NullInnerTupleSlot; econtext->ecxt_innertuple = node->hj_NullInnerTupleSlot;
if (ExecQual(otherqual, econtext, false)) if (ExecQual(otherqual, econtext, false))
{ {
...@@ -280,11 +277,11 @@ ExecHashJoin(HashJoin *node) ...@@ -280,11 +277,11 @@ ExecHashJoin(HashJoin *node)
*/ */
TupleTableSlot *result; TupleTableSlot *result;
result = ExecProject(hjstate->jstate.cs_ProjInfo, &isDone); result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
if (isDone != ExprEndResult) if (isDone != ExprEndResult)
{ {
hjstate->jstate.cs_TupFromTlist = node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult); (isDone == ExprMultipleResult);
return result; return result;
} }
...@@ -299,47 +296,60 @@ ExecHashJoin(HashJoin *node) ...@@ -299,47 +296,60 @@ ExecHashJoin(HashJoin *node)
* Init routine for HashJoin node. * Init routine for HashJoin node.
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
bool /* return: initialization status */ HashJoinState *
ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent) ExecInitHashJoin(HashJoin *node, EState *estate)
{ {
HashJoinState *hjstate; HashJoinState *hjstate;
Plan *outerNode; Plan *outerNode;
Hash *hashNode; Hash *hashNode;
List *hcl; List *hcl;
/*
* assign the node's execution state
*/
node->join.plan.state = estate;
/* /*
* create state structure * create state structure
*/ */
hjstate = makeNode(HashJoinState); hjstate = makeNode(HashJoinState);
node->hashjoinstate = hjstate; hjstate->js.ps.plan = (Plan *) node;
hjstate->js.ps.state = estate;
/* /*
* Miscellaneous initialization * Miscellaneous initialization
* *
* create expression context for node * create expression context for node
*/ */
ExecAssignExprContext(estate, &hjstate->jstate); ExecAssignExprContext(estate, &hjstate->js.ps);
/*
* initialize child expressions
*/
hjstate->js.ps.targetlist = (List *)
ExecInitExpr((Node *) node->join.plan.targetlist,
(PlanState *) hjstate);
hjstate->js.ps.qual = (List *)
ExecInitExpr((Node *) node->join.plan.qual,
(PlanState *) hjstate);
hjstate->js.jointype = node->join.jointype;
hjstate->js.joinqual = (List *)
ExecInitExpr((Node *) node->join.joinqual,
(PlanState *) hjstate);
hjstate->hashclauses = (List *)
ExecInitExpr((Node *) node->hashclauses,
(PlanState *) hjstate);
/* /*
* initializes child nodes * initialize child nodes
*/ */
outerNode = outerPlan((Plan *) node); outerNode = outerPlan(node);
hashNode = (Hash *) innerPlan((Plan *) node); hashNode = (Hash *) innerPlan(node);
ExecInitNode(outerNode, estate, (Plan *) node); outerPlanState(hjstate) = ExecInitNode(outerNode, estate);
ExecInitNode((Plan *) hashNode, estate, (Plan *) node); innerPlanState(hjstate) = ExecInitNode((Plan *) hashNode, estate);
#define HASHJOIN_NSLOTS 3 #define HASHJOIN_NSLOTS 3
/* /*
* tuple table initialization * tuple table initialization
*/ */
ExecInitResultTupleSlot(estate, &hjstate->jstate); ExecInitResultTupleSlot(estate, &hjstate->js.ps);
hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate); hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate);
switch (node->join.jointype) switch (node->join.jointype)
...@@ -349,7 +359,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent) ...@@ -349,7 +359,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
case JOIN_LEFT: case JOIN_LEFT:
hjstate->hj_NullInnerTupleSlot = hjstate->hj_NullInnerTupleSlot =
ExecInitNullTupleSlot(estate, ExecInitNullTupleSlot(estate,
ExecGetTupType((Plan *) hashNode)); ExecGetTupType(innerPlanState(hjstate)));
break; break;
default: default:
elog(ERROR, "ExecInitHashJoin: unsupported join type %d", elog(ERROR, "ExecInitHashJoin: unsupported join type %d",
...@@ -364,8 +374,8 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent) ...@@ -364,8 +374,8 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
* the contents of the hash table. -cim 6/9/91 * the contents of the hash table. -cim 6/9/91
*/ */
{ {
HashState *hashstate = hashNode->hashstate; HashState *hashstate = (HashState *) innerPlanState(hjstate);
TupleTableSlot *slot = hashstate->cstate.cs_ResultTupleSlot; TupleTableSlot *slot = hashstate->ps.ps_ResultTupleSlot;
hjstate->hj_HashTupleSlot = slot; hjstate->hj_HashTupleSlot = slot;
} }
...@@ -373,11 +383,11 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent) ...@@ -373,11 +383,11 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
/* /*
* initialize tuple type and projection info * initialize tuple type and projection info
*/ */
ExecAssignResultTypeFromTL((Plan *) node, &hjstate->jstate); ExecAssignResultTypeFromTL(&hjstate->js.ps);
ExecAssignProjectionInfo((Plan *) node, &hjstate->jstate); ExecAssignProjectionInfo(&hjstate->js.ps);
ExecSetSlotDescriptor(hjstate->hj_OuterTupleSlot, ExecSetSlotDescriptor(hjstate->hj_OuterTupleSlot,
ExecGetTupType(outerNode), ExecGetTupType(outerPlanState(hjstate)),
false); false);
/* /*
...@@ -402,12 +412,12 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent) ...@@ -402,12 +412,12 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent)
get_leftop(lfirst(hcl))); get_leftop(lfirst(hcl)));
} }
hjstate->jstate.cs_OuterTupleSlot = NULL; hjstate->js.ps.ps_OuterTupleSlot = NULL;
hjstate->jstate.cs_TupFromTlist = false; hjstate->js.ps.ps_TupFromTlist = false;
hjstate->hj_NeedNewOuter = true; hjstate->hj_NeedNewOuter = true;
hjstate->hj_MatchedOuter = false; hjstate->hj_MatchedOuter = false;
return TRUE; return hjstate;
} }
int int
...@@ -425,46 +435,35 @@ ExecCountSlotsHashJoin(HashJoin *node) ...@@ -425,46 +435,35 @@ ExecCountSlotsHashJoin(HashJoin *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecEndHashJoin(HashJoin *node) ExecEndHashJoin(HashJoinState *node)
{ {
HashJoinState *hjstate;
/*
* get info from the HashJoin state
*/
hjstate = node->hashjoinstate;
/* /*
* free hash table in case we end plan before all tuples are retrieved * free hash table in case we end plan before all tuples are retrieved
*/ */
if (hjstate->hj_HashTable) if (node->hj_HashTable)
{ {
ExecHashTableDestroy(hjstate->hj_HashTable); ExecHashTableDestroy(node->hj_HashTable);
hjstate->hj_HashTable = NULL; node->hj_HashTable = NULL;
} }
/* /*
* Free the projection info and the scan attribute info * Free the projection info and the scan attribute info
*
* Note: we don't ExecFreeResultType(hjstate) because the rule manager
* depends on the tupType returned by ExecMain(). So for now, this is
* freed at end-transaction time. -cim 6/2/91
*/ */
ExecFreeProjectionInfo(&hjstate->jstate); ExecFreeProjectionInfo(&node->js.ps);
ExecFreeExprContext(&hjstate->jstate); ExecFreeExprContext(&node->js.ps);
/* /*
* clean up subtrees * clean up subtrees
*/ */
ExecEndNode(outerPlan((Plan *) node), (Plan *) node); ExecEndNode(outerPlanState(node));
ExecEndNode(innerPlan((Plan *) node), (Plan *) node); ExecEndNode(innerPlanState(node));
/* /*
* clean out the tuple table * clean out the tuple table
*/ */
ExecClearTuple(hjstate->jstate.cs_ResultTupleSlot); ExecClearTuple(node->js.ps.ps_ResultTupleSlot);
ExecClearTuple(hjstate->hj_OuterTupleSlot); ExecClearTuple(node->hj_OuterTupleSlot);
ExecClearTuple(hjstate->hj_HashTupleSlot); ExecClearTuple(node->hj_HashTupleSlot);
} }
...@@ -478,7 +477,7 @@ ExecEndHashJoin(HashJoin *node) ...@@ -478,7 +477,7 @@ ExecEndHashJoin(HashJoin *node)
*/ */
static TupleTableSlot * static TupleTableSlot *
ExecHashJoinOuterGetTuple(Plan *node, Plan *parent, HashJoinState *hjstate) ExecHashJoinOuterGetTuple(PlanState *node, HashJoinState *hjstate)
{ {
HashJoinTable hashtable = hjstate->hj_HashTable; HashJoinTable hashtable = hjstate->hj_HashTable;
int curbatch = hashtable->curbatch; int curbatch = hashtable->curbatch;
...@@ -486,7 +485,7 @@ ExecHashJoinOuterGetTuple(Plan *node, Plan *parent, HashJoinState *hjstate) ...@@ -486,7 +485,7 @@ ExecHashJoinOuterGetTuple(Plan *node, Plan *parent, HashJoinState *hjstate)
if (curbatch == 0) if (curbatch == 0)
{ /* if it is the first pass */ { /* if it is the first pass */
slot = ExecProcNode(node, parent); slot = ExecProcNode(node);
if (!TupIsNull(slot)) if (!TupIsNull(slot))
return slot; return slot;
...@@ -611,7 +610,7 @@ ExecHashJoinNewBatch(HashJoinState *hjstate) ...@@ -611,7 +610,7 @@ ExecHashJoinNewBatch(HashJoinState *hjstate)
*/ */
ExecHashTableReset(hashtable, innerBatchSize[newbatch - 1]); ExecHashTableReset(hashtable, innerBatchSize[newbatch - 1]);
econtext = hjstate->jstate.cs_ExprContext; econtext = hjstate->js.ps.ps_ExprContext;
innerhashkeys = hjstate->hj_InnerHashKeys; innerhashkeys = hjstate->hj_InnerHashKeys;
while ((slot = ExecHashJoinGetSavedTuple(hjstate, while ((slot = ExecHashJoinGetSavedTuple(hjstate,
...@@ -682,39 +681,37 @@ ExecHashJoinSaveTuple(HeapTuple heapTuple, ...@@ -682,39 +681,37 @@ ExecHashJoinSaveTuple(HeapTuple heapTuple,
} }
void void
ExecReScanHashJoin(HashJoin *node, ExprContext *exprCtxt, Plan *parent) ExecReScanHashJoin(HashJoinState *node, ExprContext *exprCtxt)
{ {
HashJoinState *hjstate = node->hashjoinstate; if (!node->hj_hashdone)
if (!hjstate->hj_hashdone)
return; return;
hjstate->hj_hashdone = false; node->hj_hashdone = false;
/* /*
* Unfortunately, currently we have to destroy hashtable in all * Unfortunately, currently we have to destroy hashtable in all
* cases... * cases...
*/ */
if (hjstate->hj_HashTable) if (node->hj_HashTable)
{ {
ExecHashTableDestroy(hjstate->hj_HashTable); ExecHashTableDestroy(node->hj_HashTable);
hjstate->hj_HashTable = NULL; node->hj_HashTable = NULL;
} }
hjstate->hj_CurBucketNo = 0; node->hj_CurBucketNo = 0;
hjstate->hj_CurTuple = (HashJoinTuple) NULL; node->hj_CurTuple = (HashJoinTuple) NULL;
hjstate->jstate.cs_OuterTupleSlot = (TupleTableSlot *) NULL; node->js.ps.ps_OuterTupleSlot = (TupleTableSlot *) NULL;
hjstate->jstate.cs_TupFromTlist = false; node->js.ps.ps_TupFromTlist = false;
hjstate->hj_NeedNewOuter = true; node->hj_NeedNewOuter = true;
hjstate->hj_MatchedOuter = false; node->hj_MatchedOuter = false;
/* /*
* if chgParam of subnodes is not null then plans will be re-scanned * if chgParam of subnodes is not null then plans will be re-scanned
* by first ExecProcNode. * by 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);
if (((Plan *) node)->righttree->chgParam == NULL) if (((PlanState *) node)->righttree->chgParam == NULL)
ExecReScan(((Plan *) node)->righttree, exprCtxt, (Plan *) node); ExecReScan(((PlanState *) node)->righttree, exprCtxt);
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.71 2002/09/04 20:31:18 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.72 2002/12/05 15:50:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
#define LEFT_OP 1 #define LEFT_OP 1
#define RIGHT_OP 2 #define RIGHT_OP 2
static TupleTableSlot *IndexNext(IndexScan *node); static TupleTableSlot *IndexNext(IndexScanState *node);
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* IndexNext * IndexNext
...@@ -65,15 +65,14 @@ static TupleTableSlot *IndexNext(IndexScan *node); ...@@ -65,15 +65,14 @@ static TupleTableSlot *IndexNext(IndexScan *node);
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static TupleTableSlot * static TupleTableSlot *
IndexNext(IndexScan *node) IndexNext(IndexScanState *node)
{ {
EState *estate; EState *estate;
CommonScanState *scanstate;
IndexScanState *indexstate;
ExprContext *econtext; ExprContext *econtext;
ScanDirection direction; ScanDirection direction;
IndexScanDescPtr scanDescs; IndexScanDescPtr scanDescs;
IndexScanDesc scandesc; IndexScanDesc scandesc;
Index scanrelid;
HeapTuple tuple; HeapTuple tuple;
TupleTableSlot *slot; TupleTableSlot *slot;
int numIndices; int numIndices;
...@@ -83,21 +82,20 @@ IndexNext(IndexScan *node) ...@@ -83,21 +82,20 @@ IndexNext(IndexScan *node)
/* /*
* extract necessary information from index scan node * extract necessary information from index scan node
*/ */
estate = node->scan.plan.state; estate = node->ss.ps.state;
direction = estate->es_direction; direction = estate->es_direction;
if (ScanDirectionIsBackward(node->indxorderdir)) if (ScanDirectionIsBackward(((IndexScan *) node->ss.ps.plan)->indxorderdir))
{ {
if (ScanDirectionIsForward(direction)) if (ScanDirectionIsForward(direction))
direction = BackwardScanDirection; direction = BackwardScanDirection;
else if (ScanDirectionIsBackward(direction)) else if (ScanDirectionIsBackward(direction))
direction = ForwardScanDirection; direction = ForwardScanDirection;
} }
scanstate = node->scan.scanstate; scanDescs = node->iss_ScanDescs;
indexstate = node->indxstate; numIndices = node->iss_NumIndices;
scanDescs = indexstate->iss_ScanDescs; econtext = node->ss.ps.ps_ExprContext;
numIndices = indexstate->iss_NumIndices; slot = node->ss.ss_ScanTupleSlot;
econtext = scanstate->cstate.cs_ExprContext; scanrelid = ((IndexScan *) node->ss.ps.plan)->scan.scanrelid;
slot = scanstate->css_ScanTupleSlot;
/* /*
* Check if we are evaluating PlanQual for tuple of this relation. * Check if we are evaluating PlanQual for tuple of this relation.
...@@ -106,15 +104,15 @@ IndexNext(IndexScan *node) ...@@ -106,15 +104,15 @@ IndexNext(IndexScan *node)
* switching in Init/ReScan plan... * switching in Init/ReScan plan...
*/ */
if (estate->es_evTuple != NULL && if (estate->es_evTuple != NULL &&
estate->es_evTuple[node->scan.scanrelid - 1] != NULL) estate->es_evTuple[scanrelid - 1] != NULL)
{ {
List *qual; List *qual;
ExecClearTuple(slot); ExecClearTuple(slot);
if (estate->es_evTupleNull[node->scan.scanrelid - 1]) if (estate->es_evTupleNull[scanrelid - 1])
return slot; /* return empty slot */ return slot; /* return empty slot */
ExecStoreTuple(estate->es_evTuple[node->scan.scanrelid - 1], ExecStoreTuple(estate->es_evTuple[scanrelid - 1],
slot, InvalidBuffer, false); slot, InvalidBuffer, false);
/* Does the tuple meet any of the OR'd indxqual conditions? */ /* Does the tuple meet any of the OR'd indxqual conditions? */
...@@ -131,7 +129,7 @@ IndexNext(IndexScan *node) ...@@ -131,7 +129,7 @@ IndexNext(IndexScan *node)
slot->val = NULL; slot->val = NULL;
/* Flag for the next call that no more tuples */ /* Flag for the next call that no more tuples */
estate->es_evTupleNull[node->scan.scanrelid - 1] = true; estate->es_evTupleNull[scanrelid - 1] = true;
return slot; return slot;
} }
...@@ -144,24 +142,24 @@ IndexNext(IndexScan *node) ...@@ -144,24 +142,24 @@ IndexNext(IndexScan *node)
bBackward = ScanDirectionIsBackward(direction); bBackward = ScanDirectionIsBackward(direction);
if (bBackward) if (bBackward)
{ {
indexNumber = numIndices - indexstate->iss_IndexPtr - 1; indexNumber = numIndices - node->iss_IndexPtr - 1;
if (indexNumber < 0) if (indexNumber < 0)
{ {
indexNumber = 0; indexNumber = 0;
indexstate->iss_IndexPtr = numIndices - 1; node->iss_IndexPtr = numIndices - 1;
} }
} }
else else
{ {
if ((indexNumber = indexstate->iss_IndexPtr) < 0) if ((indexNumber = node->iss_IndexPtr) < 0)
{ {
indexNumber = 0; indexNumber = 0;
indexstate->iss_IndexPtr = 0; node->iss_IndexPtr = 0;
} }
} }
while (indexNumber < numIndices) while (indexNumber < numIndices)
{ {
scandesc = scanDescs[indexstate->iss_IndexPtr]; scandesc = scanDescs[node->iss_IndexPtr];
while ((tuple = index_getnext(scandesc, direction)) != NULL) while ((tuple = index_getnext(scandesc, direction)) != NULL)
{ {
/* /*
...@@ -181,7 +179,7 @@ IndexNext(IndexScan *node) ...@@ -181,7 +179,7 @@ IndexNext(IndexScan *node)
* We do this by passing the tuple through ExecQual and * We do this by passing the tuple through ExecQual and
* checking for failure with all previous qualifications. * checking for failure with all previous qualifications.
*/ */
if (indexstate->iss_IndexPtr > 0) if (node->iss_IndexPtr > 0)
{ {
bool prev_matches = false; bool prev_matches = false;
int prev_index; int prev_index;
...@@ -191,7 +189,7 @@ IndexNext(IndexScan *node) ...@@ -191,7 +189,7 @@ IndexNext(IndexScan *node)
ResetExprContext(econtext); ResetExprContext(econtext);
qual = node->indxqualorig; qual = node->indxqualorig;
for (prev_index = 0; for (prev_index = 0;
prev_index < indexstate->iss_IndexPtr; prev_index < node->iss_IndexPtr;
prev_index++) prev_index++)
{ {
if (ExecQual((List *) lfirst(qual), econtext, false)) if (ExecQual((List *) lfirst(qual), econtext, false))
...@@ -216,9 +214,9 @@ IndexNext(IndexScan *node) ...@@ -216,9 +214,9 @@ IndexNext(IndexScan *node)
{ {
indexNumber++; indexNumber++;
if (bBackward) if (bBackward)
indexstate->iss_IndexPtr--; node->iss_IndexPtr--;
else else
indexstate->iss_IndexPtr++; node->iss_IndexPtr++;
} }
} }
...@@ -251,21 +249,19 @@ IndexNext(IndexScan *node) ...@@ -251,21 +249,19 @@ IndexNext(IndexScan *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
TupleTableSlot * TupleTableSlot *
ExecIndexScan(IndexScan *node) ExecIndexScan(IndexScanState *node)
{ {
IndexScanState *indexstate = node->indxstate;
/* /*
* If we have runtime keys and they've not already been set up, do it * If we have runtime keys and they've not already been set up, do it
* now. * now.
*/ */
if (indexstate->iss_RuntimeKeyInfo && !indexstate->iss_RuntimeKeysReady) if (node->iss_RuntimeKeyInfo && !node->iss_RuntimeKeysReady)
ExecReScan((Plan *) node, NULL, NULL); ExecReScan((PlanState *) node, NULL);
/* /*
* use IndexNext as access method * use IndexNext as access method
*/ */
return ExecScan(&node->scan, (ExecScanAccessMtd) IndexNext); return ExecScan(&node->ss, (ExecScanAccessMtd) IndexNext);
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -280,28 +276,27 @@ ExecIndexScan(IndexScan *node) ...@@ -280,28 +276,27 @@ ExecIndexScan(IndexScan *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent) ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt)
{ {
EState *estate; EState *estate;
IndexScanState *indexstate;
ExprContext *econtext; ExprContext *econtext;
int numIndices; int numIndices;
IndexScanDescPtr scanDescs; IndexScanDescPtr scanDescs;
ScanKey *scanKeys; ScanKey *scanKeys;
int **runtimeKeyInfo; int **runtimeKeyInfo;
int *numScanKeys; int *numScanKeys;
Index scanrelid;
int i; int i;
int j; int j;
estate = node->scan.plan.state; estate = node->ss.ps.state;
indexstate = node->indxstate; econtext = node->iss_RuntimeContext; /* context for runtime keys */
econtext = indexstate->iss_RuntimeContext; /* context for runtime numIndices = node->iss_NumIndices;
* keys */ scanDescs = node->iss_ScanDescs;
numIndices = indexstate->iss_NumIndices; scanKeys = node->iss_ScanKeys;
scanDescs = indexstate->iss_ScanDescs; runtimeKeyInfo = node->iss_RuntimeKeyInfo;
scanKeys = indexstate->iss_ScanKeys; numScanKeys = node->iss_NumScanKeys;
runtimeKeyInfo = indexstate->iss_RuntimeKeyInfo; scanrelid = ((IndexScan *) node->ss.ps.plan)->scan.scanrelid;
numScanKeys = indexstate->iss_NumScanKeys;
if (econtext) if (econtext)
{ {
...@@ -315,7 +310,7 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent) ...@@ -315,7 +310,7 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
ExprContext *stdecontext; ExprContext *stdecontext;
econtext->ecxt_outertuple = exprCtxt->ecxt_outertuple; econtext->ecxt_outertuple = exprCtxt->ecxt_outertuple;
stdecontext = node->scan.scanstate->cstate.cs_ExprContext; stdecontext = node->ss.ps.ps_ExprContext;
stdecontext->ecxt_outertuple = exprCtxt->ecxt_outertuple; stdecontext->ecxt_outertuple = exprCtxt->ecxt_outertuple;
} }
...@@ -392,22 +387,22 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent) ...@@ -392,22 +387,22 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
} }
} }
indexstate->iss_RuntimeKeysReady = true; node->iss_RuntimeKeysReady = true;
} }
/* If this is re-scanning of PlanQual ... */ /* If this is re-scanning of PlanQual ... */
if (estate->es_evTuple != NULL && if (estate->es_evTuple != NULL &&
estate->es_evTuple[node->scan.scanrelid - 1] != NULL) estate->es_evTuple[scanrelid - 1] != NULL)
{ {
estate->es_evTupleNull[node->scan.scanrelid - 1] = false; estate->es_evTupleNull[scanrelid - 1] = false;
return; return;
} }
/* reset index scans */ /* reset index scans */
if (ScanDirectionIsBackward(node->indxorderdir)) if (ScanDirectionIsBackward(((IndexScan *) node->ss.ps.plan)->indxorderdir))
indexstate->iss_IndexPtr = numIndices; node->iss_IndexPtr = numIndices;
else else
indexstate->iss_IndexPtr = -1; node->iss_IndexPtr = -1;
for (i = 0; i < numIndices; i++) for (i = 0; i < numIndices; i++)
{ {
...@@ -427,13 +422,10 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent) ...@@ -427,13 +422,10 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecEndIndexScan(IndexScan *node) ExecEndIndexScan(IndexScanState *node)
{ {
CommonScanState *scanstate;
IndexScanState *indexstate;
int **runtimeKeyInfo; int **runtimeKeyInfo;
ScanKey *scanKeys; ScanKey *scanKeys;
List *indxqual;
int *numScanKeys; int *numScanKeys;
int numIndices; int numIndices;
Relation relation; Relation relation;
...@@ -441,32 +433,25 @@ ExecEndIndexScan(IndexScan *node) ...@@ -441,32 +433,25 @@ ExecEndIndexScan(IndexScan *node)
IndexScanDescPtr indexScanDescs; IndexScanDescPtr indexScanDescs;
int i; int i;
scanstate = node->scan.scanstate; runtimeKeyInfo = node->iss_RuntimeKeyInfo;
indexstate = node->indxstate;
indxqual = node->indxqual;
runtimeKeyInfo = indexstate->iss_RuntimeKeyInfo;
/* /*
* extract information from the node * extract information from the node
*/ */
numIndices = indexstate->iss_NumIndices; numIndices = node->iss_NumIndices;
scanKeys = indexstate->iss_ScanKeys; scanKeys = node->iss_ScanKeys;
numScanKeys = indexstate->iss_NumScanKeys; numScanKeys = node->iss_NumScanKeys;
indexRelationDescs = indexstate->iss_RelationDescs; indexRelationDescs = node->iss_RelationDescs;
indexScanDescs = indexstate->iss_ScanDescs; indexScanDescs = node->iss_ScanDescs;
relation = scanstate->css_currentRelation; relation = node->ss.ss_currentRelation;
/* /*
* 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->cstate); ExecFreeProjectionInfo(&node->ss.ps);
ExecFreeExprContext(&scanstate->cstate); ExecFreeExprContext(&node->ss.ps);
if (indexstate->iss_RuntimeContext) if (node->iss_RuntimeContext)
FreeExprContext(indexstate->iss_RuntimeContext); FreeExprContext(node->iss_RuntimeContext);
/* /*
* close the index relations * close the index relations
...@@ -514,12 +499,11 @@ ExecEndIndexScan(IndexScan *node) ...@@ -514,12 +499,11 @@ ExecEndIndexScan(IndexScan *node)
/* /*
* clear out tuple table slots * clear out tuple table slots
*/ */
ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot); ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecClearTuple(scanstate->css_ScanTupleSlot); ExecClearTuple(node->ss.ss_ScanTupleSlot);
pfree(scanstate); pfree(node->iss_RelationDescs);
pfree(indexstate->iss_RelationDescs); pfree(node->iss_ScanDescs);
pfree(indexstate->iss_ScanDescs); pfree(node);
pfree(indexstate);
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -531,21 +515,16 @@ ExecEndIndexScan(IndexScan *node) ...@@ -531,21 +515,16 @@ ExecEndIndexScan(IndexScan *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecIndexMarkPos(IndexScan *node) ExecIndexMarkPos(IndexScanState *node)
{ {
IndexScanState *indexstate;
IndexScanDescPtr indexScanDescs; IndexScanDescPtr indexScanDescs;
IndexScanDesc scanDesc; IndexScanDesc scanDesc;
int indexPtr; int indexPtr;
indexstate = node->indxstate; indexPtr = node->iss_MarkIndexPtr = node->iss_IndexPtr;
indexPtr = indexstate->iss_MarkIndexPtr = indexstate->iss_IndexPtr; indexScanDescs = node->iss_ScanDescs;
indexScanDescs = indexstate->iss_ScanDescs;
scanDesc = indexScanDescs[indexPtr]; scanDesc = indexScanDescs[indexPtr];
#ifdef NOT_USED
IndexScanMarkPosition(scanDesc);
#endif
index_markpos(scanDesc); index_markpos(scanDesc);
} }
...@@ -560,21 +539,16 @@ ExecIndexMarkPos(IndexScan *node) ...@@ -560,21 +539,16 @@ ExecIndexMarkPos(IndexScan *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecIndexRestrPos(IndexScan *node) ExecIndexRestrPos(IndexScanState *node)
{ {
IndexScanState *indexstate;
IndexScanDescPtr indexScanDescs; IndexScanDescPtr indexScanDescs;
IndexScanDesc scanDesc; IndexScanDesc scanDesc;
int indexPtr; int indexPtr;
indexstate = node->indxstate; indexPtr = node->iss_IndexPtr = node->iss_MarkIndexPtr;
indexPtr = indexstate->iss_IndexPtr = indexstate->iss_MarkIndexPtr; indexScanDescs = node->iss_ScanDescs;
indexScanDescs = indexstate->iss_ScanDescs;
scanDesc = indexScanDescs[indexPtr]; scanDesc = indexScanDescs[indexPtr];
#ifdef NOT_USED
IndexScanRestorePosition(scanDesc);
#endif
index_restrpos(scanDesc); index_restrpos(scanDesc);
} }
...@@ -597,11 +571,10 @@ ExecIndexRestrPos(IndexScan *node) ...@@ -597,11 +571,10 @@ ExecIndexRestrPos(IndexScan *node)
* estate: the execution state initialized in InitPlan. * estate: the execution state initialized in InitPlan.
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
bool IndexScanState *
ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent) ExecInitIndexScan(IndexScan *node, EState *estate)
{ {
IndexScanState *indexstate; IndexScanState *indexstate;
CommonScanState *scanstate;
List *indxqual; List *indxqual;
List *indxid; List *indxid;
List *listscan; List *listscan;
...@@ -620,45 +593,52 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent) ...@@ -620,45 +593,52 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
Relation currentRelation; Relation currentRelation;
/* /*
* assign execution state to node * create state structure
*/ */
node->scan.plan.state = estate; indexstate = makeNode(IndexScanState);
indexstate->ss.ps.plan = (Plan *) node;
indexstate->ss.ps.state = estate;
/* /*
* Part 1) initialize scan state * Miscellaneous initialization
* *
* create new CommonScanState for node * create expression context for node
*/ */
scanstate = makeNode(CommonScanState); ExecAssignExprContext(estate, &indexstate->ss.ps);
node->scan.scanstate = scanstate;
/* /*
* Miscellaneous initialization * initialize child expressions
*
* create expression context for node
*/ */
ExecAssignExprContext(estate, &scanstate->cstate); indexstate->ss.ps.targetlist = (List *)
ExecInitExpr((Node *) node->scan.plan.targetlist,
(PlanState *) indexstate);
indexstate->ss.ps.qual = (List *)
ExecInitExpr((Node *) node->scan.plan.qual,
(PlanState *) indexstate);
indexstate->indxqual = (List *)
ExecInitExpr((Node *) node->indxqual,
(PlanState *) indexstate);
indexstate->indxqualorig = (List *)
ExecInitExpr((Node *) node->indxqualorig,
(PlanState *) indexstate);
#define INDEXSCAN_NSLOTS 2 #define INDEXSCAN_NSLOTS 2
/* /*
* tuple table initialization * tuple table initialization
*/ */
ExecInitResultTupleSlot(estate, &scanstate->cstate); ExecInitResultTupleSlot(estate, &indexstate->ss.ps);
ExecInitScanTupleSlot(estate, scanstate); ExecInitScanTupleSlot(estate, &indexstate->ss);
/* /*
* initialize projection info. result type comes from scan desc * initialize projection info. result type comes from scan desc
* below.. * below..
*/ */
ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate); ExecAssignProjectionInfo(&indexstate->ss.ps);
/* /*
* Part 2) initialize index scan state * Initialize index-specific scan state
*
* create new IndexScanState for node
*/ */
indexstate = makeNode(IndexScanState);
indexstate->iss_NumIndices = 0; indexstate->iss_NumIndices = 0;
indexstate->iss_IndexPtr = -1; indexstate->iss_IndexPtr = -1;
indexstate->iss_ScanKeys = NULL; indexstate->iss_ScanKeys = NULL;
...@@ -669,8 +649,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent) ...@@ -669,8 +649,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
indexstate->iss_RelationDescs = NULL; indexstate->iss_RelationDescs = NULL;
indexstate->iss_ScanDescs = NULL; indexstate->iss_ScanDescs = NULL;
node->indxstate = indexstate;
/* /*
* get the index node information * get the index node information
*/ */
...@@ -836,7 +814,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent) ...@@ -836,7 +814,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
{ {
/* treat Param like a constant */ /* treat Param like a constant */
scanvalue = ExecEvalParam((Param *) leftop, scanvalue = ExecEvalParam((Param *) leftop,
scanstate->cstate.cs_ExprContext, indexstate->ss.ps.ps_ExprContext,
&isnull); &isnull);
if (isnull) if (isnull)
flags |= SK_ISNULL; flags |= SK_ISNULL;
...@@ -911,7 +889,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent) ...@@ -911,7 +889,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
{ {
/* treat Param like a constant */ /* treat Param like a constant */
scanvalue = ExecEvalParam((Param *) rightop, scanvalue = ExecEvalParam((Param *) rightop,
scanstate->cstate.cs_ExprContext, indexstate->ss.ps.ps_ExprContext,
&isnull); &isnull);
if (isnull) if (isnull)
flags |= SK_ISNULL; flags |= SK_ISNULL;
...@@ -976,12 +954,12 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent) ...@@ -976,12 +954,12 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
*/ */
if (have_runtime_keys) if (have_runtime_keys)
{ {
ExprContext *stdecontext = scanstate->cstate.cs_ExprContext; ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext;
ExecAssignExprContext(estate, &scanstate->cstate); ExecAssignExprContext(estate, &indexstate->ss.ps);
indexstate->iss_RuntimeKeyInfo = runtimeKeyInfo; indexstate->iss_RuntimeKeyInfo = runtimeKeyInfo;
indexstate->iss_RuntimeContext = scanstate->cstate.cs_ExprContext; indexstate->iss_RuntimeContext = indexstate->ss.ps.ps_ExprContext;
scanstate->cstate.cs_ExprContext = stdecontext; indexstate->ss.ps.ps_ExprContext = stdecontext;
} }
else else
{ {
...@@ -1008,14 +986,14 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent) ...@@ -1008,14 +986,14 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
if (!RelationGetForm(currentRelation)->relhasindex) if (!RelationGetForm(currentRelation)->relhasindex)
elog(ERROR, "indexes of the relation %u was inactivated", reloid); elog(ERROR, "indexes of the relation %u was inactivated", reloid);
scanstate->css_currentRelation = currentRelation; indexstate->ss.ss_currentRelation = currentRelation;
scanstate->css_currentScanDesc = NULL; /* no heap scan here */ indexstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */
/* /*
* get the scan type from the relation descriptor. * get the scan type from the relation descriptor.
*/ */
ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false); ExecAssignScanType(&indexstate->ss, RelationGetDescr(currentRelation), false);
ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate); ExecAssignResultTypeFromTL(&indexstate->ss.ps);
/* /*
* open the index relations and initialize relation and scan * open the index relations and initialize relation and scan
...@@ -1043,7 +1021,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent) ...@@ -1043,7 +1021,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
/* /*
* all done. * all done.
*/ */
return TRUE; return indexstate;
} }
int int
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeLimit.c,v 1.11 2002/11/22 22:10:01 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeLimit.c,v 1.12 2002/12/05 15:50:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include "executor/executor.h" #include "executor/executor.h"
#include "executor/nodeLimit.h" #include "executor/nodeLimit.h"
static void recompute_limits(Limit *node); static void recompute_limits(LimitState *node);
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -35,26 +35,24 @@ static void recompute_limits(Limit *node); ...@@ -35,26 +35,24 @@ static void recompute_limits(Limit *node);
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
TupleTableSlot * /* return: a tuple or NULL */ TupleTableSlot * /* return: a tuple or NULL */
ExecLimit(Limit *node) ExecLimit(LimitState *node)
{ {
LimitState *limitstate;
ScanDirection direction; ScanDirection direction;
TupleTableSlot *resultTupleSlot; TupleTableSlot *resultTupleSlot;
TupleTableSlot *slot; TupleTableSlot *slot;
Plan *outerPlan; PlanState *outerPlan;
/* /*
* get information from the node * get information from the node
*/ */
limitstate = node->limitstate; direction = node->ps.state->es_direction;
direction = node->plan.state->es_direction; outerPlan = outerPlanState(node);
outerPlan = outerPlan((Plan *) node); resultTupleSlot = node->ps.ps_ResultTupleSlot;
resultTupleSlot = limitstate->cstate.cs_ResultTupleSlot;
/* /*
* The main logic is a simple state machine. * The main logic is a simple state machine.
*/ */
switch (limitstate->lstate) switch (node->lstate)
{ {
case LIMIT_INITIAL: case LIMIT_INITIAL:
/* /*
...@@ -71,9 +69,9 @@ ExecLimit(Limit *node) ...@@ -71,9 +69,9 @@ ExecLimit(Limit *node)
/* /*
* Check for empty window; if so, treat like empty subplan. * Check for empty window; if so, treat like empty subplan.
*/ */
if (limitstate->count <= 0 && !limitstate->noCount) if (node->count <= 0 && !node->noCount)
{ {
limitstate->lstate = LIMIT_EMPTY; node->lstate = LIMIT_EMPTY;
return NULL; return NULL;
} }
/* /*
...@@ -81,24 +79,24 @@ ExecLimit(Limit *node) ...@@ -81,24 +79,24 @@ ExecLimit(Limit *node)
*/ */
for (;;) for (;;)
{ {
slot = ExecProcNode(outerPlan, (Plan *) node); slot = ExecProcNode(outerPlan);
if (TupIsNull(slot)) if (TupIsNull(slot))
{ {
/* /*
* The subplan returns too few tuples for us to produce * The subplan returns too few tuples for us to produce
* any output at all. * any output at all.
*/ */
limitstate->lstate = LIMIT_EMPTY; node->lstate = LIMIT_EMPTY;
return NULL; return NULL;
} }
limitstate->subSlot = slot; node->subSlot = slot;
if (++limitstate->position > limitstate->offset) if (++node->position > node->offset)
break; break;
} }
/* /*
* Okay, we have the first tuple of the window. * Okay, we have the first tuple of the window.
*/ */
limitstate->lstate = LIMIT_INWINDOW; node->lstate = LIMIT_INWINDOW;
break; break;
case LIMIT_EMPTY: case LIMIT_EMPTY:
...@@ -117,23 +115,23 @@ ExecLimit(Limit *node) ...@@ -117,23 +115,23 @@ ExecLimit(Limit *node)
* advancing the subplan or the position variable; but * advancing the subplan or the position variable; but
* change the state machine state to record having done so. * change the state machine state to record having done so.
*/ */
if (!limitstate->noCount && if (!node->noCount &&
limitstate->position >= limitstate->offset + limitstate->count) node->position >= node->offset + node->count)
{ {
limitstate->lstate = LIMIT_WINDOWEND; node->lstate = LIMIT_WINDOWEND;
return NULL; return NULL;
} }
/* /*
* Get next tuple from subplan, if any. * Get next tuple from subplan, if any.
*/ */
slot = ExecProcNode(outerPlan, (Plan *) node); slot = ExecProcNode(outerPlan);
if (TupIsNull(slot)) if (TupIsNull(slot))
{ {
limitstate->lstate = LIMIT_SUBPLANEOF; node->lstate = LIMIT_SUBPLANEOF;
return NULL; return NULL;
} }
limitstate->subSlot = slot; node->subSlot = slot;
limitstate->position++; node->position++;
} }
else else
{ {
...@@ -141,19 +139,19 @@ ExecLimit(Limit *node) ...@@ -141,19 +139,19 @@ ExecLimit(Limit *node)
* Backwards scan, so check for stepping off start of window. * Backwards scan, so check for stepping off start of window.
* As above, change only state-machine status if so. * As above, change only state-machine status if so.
*/ */
if (limitstate->position <= limitstate->offset + 1) if (node->position <= node->offset + 1)
{ {
limitstate->lstate = LIMIT_WINDOWSTART; node->lstate = LIMIT_WINDOWSTART;
return NULL; return NULL;
} }
/* /*
* Get previous tuple from subplan; there should be one! * Get previous tuple from subplan; there should be one!
*/ */
slot = ExecProcNode(outerPlan, (Plan *) node); slot = ExecProcNode(outerPlan);
if (TupIsNull(slot)) if (TupIsNull(slot))
elog(ERROR, "ExecLimit: subplan failed to run backwards"); elog(ERROR, "ExecLimit: subplan failed to run backwards");
limitstate->subSlot = slot; node->subSlot = slot;
limitstate->position--; node->position--;
} }
break; break;
...@@ -164,11 +162,11 @@ ExecLimit(Limit *node) ...@@ -164,11 +162,11 @@ ExecLimit(Limit *node)
* Backing up from subplan EOF, so re-fetch previous tuple; * Backing up from subplan EOF, so re-fetch previous tuple;
* there should be one! Note previous tuple must be in window. * there should be one! Note previous tuple must be in window.
*/ */
slot = ExecProcNode(outerPlan, (Plan *) node); slot = ExecProcNode(outerPlan);
if (TupIsNull(slot)) if (TupIsNull(slot))
elog(ERROR, "ExecLimit: subplan failed to run backwards"); elog(ERROR, "ExecLimit: subplan failed to run backwards");
limitstate->subSlot = slot; node->subSlot = slot;
limitstate->lstate = LIMIT_INWINDOW; node->lstate = LIMIT_INWINDOW;
/* position does not change 'cause we didn't advance it before */ /* position does not change 'cause we didn't advance it before */
break; break;
...@@ -179,8 +177,8 @@ ExecLimit(Limit *node) ...@@ -179,8 +177,8 @@ ExecLimit(Limit *node)
* Backing up from window end: simply re-return the last * Backing up from window end: simply re-return the last
* tuple fetched from the subplan. * tuple fetched from the subplan.
*/ */
slot = limitstate->subSlot; slot = node->subSlot;
limitstate->lstate = LIMIT_INWINDOW; node->lstate = LIMIT_INWINDOW;
/* position does not change 'cause we didn't advance it before */ /* position does not change 'cause we didn't advance it before */
break; break;
...@@ -191,14 +189,14 @@ ExecLimit(Limit *node) ...@@ -191,14 +189,14 @@ ExecLimit(Limit *node)
* Advancing after having backed off window start: simply * Advancing after having backed off window start: simply
* re-return the last tuple fetched from the subplan. * re-return the last tuple fetched from the subplan.
*/ */
slot = limitstate->subSlot; slot = node->subSlot;
limitstate->lstate = LIMIT_INWINDOW; node->lstate = LIMIT_INWINDOW;
/* position does not change 'cause we didn't change it before */ /* position does not change 'cause we didn't change it before */
break; break;
default: default:
elog(ERROR, "ExecLimit: impossible state %d", elog(ERROR, "ExecLimit: impossible state %d",
(int) limitstate->lstate); (int) node->lstate);
slot = NULL; /* keep compiler quiet */ slot = NULL; /* keep compiler quiet */
break; break;
} }
...@@ -220,55 +218,54 @@ ExecLimit(Limit *node) ...@@ -220,55 +218,54 @@ ExecLimit(Limit *node)
* This is also a handy place to reset the current-position state info. * This is also a handy place to reset the current-position state info.
*/ */
static void static void
recompute_limits(Limit *node) recompute_limits(LimitState *node)
{ {
LimitState *limitstate = node->limitstate; ExprContext *econtext = node->ps.ps_ExprContext;
ExprContext *econtext = limitstate->cstate.cs_ExprContext;
bool isNull; bool isNull;
if (node->limitOffset) if (node->limitOffset)
{ {
limitstate->offset = node->offset =
DatumGetInt32(ExecEvalExprSwitchContext(node->limitOffset, DatumGetInt32(ExecEvalExprSwitchContext(node->limitOffset,
econtext, econtext,
&isNull, &isNull,
NULL)); NULL));
/* Interpret NULL offset as no offset */ /* Interpret NULL offset as no offset */
if (isNull) if (isNull)
limitstate->offset = 0; node->offset = 0;
else if (limitstate->offset < 0) else if (node->offset < 0)
limitstate->offset = 0; node->offset = 0;
} }
else else
{ {
/* No OFFSET supplied */ /* No OFFSET supplied */
limitstate->offset = 0; node->offset = 0;
} }
if (node->limitCount) if (node->limitCount)
{ {
limitstate->noCount = false; node->noCount = false;
limitstate->count = node->count =
DatumGetInt32(ExecEvalExprSwitchContext(node->limitCount, DatumGetInt32(ExecEvalExprSwitchContext(node->limitCount,
econtext, econtext,
&isNull, &isNull,
NULL)); NULL));
/* Interpret NULL count as no count (LIMIT ALL) */ /* Interpret NULL count as no count (LIMIT ALL) */
if (isNull) if (isNull)
limitstate->noCount = true; node->noCount = true;
else if (limitstate->count < 0) else if (node->count < 0)
limitstate->count = 0; node->count = 0;
} }
else else
{ {
/* No COUNT supplied */ /* No COUNT supplied */
limitstate->count = 0; node->count = 0;
limitstate->noCount = true; node->noCount = true;
} }
/* Reset position to start-of-scan */ /* Reset position to start-of-scan */
limitstate->position = 0; node->position = 0;
limitstate->subSlot = NULL; node->subSlot = NULL;
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -278,22 +275,19 @@ recompute_limits(Limit *node) ...@@ -278,22 +275,19 @@ recompute_limits(Limit *node)
* the node's subplan. * the node's subplan.
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
bool /* return: initialization status */ LimitState *
ExecInitLimit(Limit *node, EState *estate, Plan *parent) ExecInitLimit(Limit *node, EState *estate)
{ {
LimitState *limitstate; LimitState *limitstate;
Plan *outerPlan; Plan *outerPlan;
/* /*
* assign execution state to node * create state structure
*/
node->plan.state = estate;
/*
* create new LimitState for node
*/ */
limitstate = makeNode(LimitState); limitstate = makeNode(LimitState);
node->limitstate = limitstate; limitstate->ps.plan = (Plan *) node;
limitstate->ps.state = estate;
limitstate->lstate = LIMIT_INITIAL; limitstate->lstate = LIMIT_INITIAL;
/* /*
...@@ -302,29 +296,37 @@ ExecInitLimit(Limit *node, EState *estate, Plan *parent) ...@@ -302,29 +296,37 @@ ExecInitLimit(Limit *node, EState *estate, Plan *parent)
* Limit nodes never call ExecQual or ExecProject, but they need an * Limit nodes never call ExecQual or ExecProject, but they need an
* exprcontext anyway to evaluate the limit/offset parameters in. * exprcontext anyway to evaluate the limit/offset parameters in.
*/ */
ExecAssignExprContext(estate, &limitstate->cstate); ExecAssignExprContext(estate, &limitstate->ps);
/*
* initialize child expressions
*/
limitstate->limitOffset = ExecInitExpr(node->limitOffset,
(PlanState *) limitstate);
limitstate->limitCount = ExecInitExpr(node->limitCount,
(PlanState *) limitstate);
#define LIMIT_NSLOTS 1 #define LIMIT_NSLOTS 1
/* /*
* Tuple table initialization * Tuple table initialization
*/ */
ExecInitResultTupleSlot(estate, &limitstate->cstate); ExecInitResultTupleSlot(estate, &limitstate->ps);
/* /*
* then initialize outer plan * then initialize outer plan
*/ */
outerPlan = outerPlan((Plan *) node); outerPlan = outerPlan(node);
ExecInitNode(outerPlan, estate, (Plan *) node); outerPlanState(limitstate) = ExecInitNode(outerPlan, estate);
/* /*
* limit nodes do no projections, so initialize projection info for * limit nodes do no projections, so initialize projection info for
* this node appropriately * this node appropriately
*/ */
ExecAssignResultTypeFromOuterPlan((Plan *) node, &limitstate->cstate); ExecAssignResultTypeFromOuterPlan(&limitstate->ps);
limitstate->cstate.cs_ProjInfo = NULL; limitstate->ps.ps_ProjInfo = NULL;
return TRUE; return limitstate;
} }
int int
...@@ -343,33 +345,29 @@ ExecCountSlotsLimit(Limit *node) ...@@ -343,33 +345,29 @@ ExecCountSlotsLimit(Limit *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecEndLimit(Limit *node) ExecEndLimit(LimitState *node)
{ {
LimitState *limitstate = node->limitstate; ExecFreeExprContext(&node->ps);
ExecFreeExprContext(&limitstate->cstate); ExecEndNode(outerPlanState(node));
ExecEndNode(outerPlan((Plan *) node), (Plan *) node);
/* clean up tuple table */ /* clean up tuple table */
ExecClearTuple(limitstate->cstate.cs_ResultTupleSlot); ExecClearTuple(node->ps.ps_ResultTupleSlot);
} }
void void
ExecReScanLimit(Limit *node, ExprContext *exprCtxt, Plan *parent) ExecReScanLimit(LimitState *node, ExprContext *exprCtxt)
{ {
LimitState *limitstate = node->limitstate;
/* resetting lstate will force offset/limit recalculation */ /* resetting lstate will force offset/limit recalculation */
limitstate->lstate = LIMIT_INITIAL; node->lstate = LIMIT_INITIAL;
ExecClearTuple(limitstate->cstate.cs_ResultTupleSlot); ExecClearTuple(node->ps.ps_ResultTupleSlot);
/* /*
* if chgParam of subnode is not null then plan will be re-scanned by * 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);
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMaterial.c,v 1.38 2002/06/20 20:29:28 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeMaterial.c,v 1.39 2002/12/05 15:50:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -43,10 +43,9 @@ ...@@ -43,10 +43,9 @@
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
TupleTableSlot * /* result tuple from subplan */ TupleTableSlot * /* result tuple from subplan */
ExecMaterial(Material *node) ExecMaterial(MaterialState *node)
{ {
EState *estate; EState *estate;
MaterialState *matstate;
ScanDirection dir; ScanDirection dir;
Tuplestorestate *tuplestorestate; Tuplestorestate *tuplestorestate;
HeapTuple heapTuple; HeapTuple heapTuple;
...@@ -56,10 +55,9 @@ ExecMaterial(Material *node) ...@@ -56,10 +55,9 @@ ExecMaterial(Material *node)
/* /*
* get state info from node * get state info from node
*/ */
matstate = node->matstate; estate = node->ss.ps.state;
estate = node->plan.state;
dir = estate->es_direction; dir = estate->es_direction;
tuplestorestate = (Tuplestorestate *) matstate->tuplestorestate; tuplestorestate = (Tuplestorestate *) node->tuplestorestate;
/* /*
* If first time through, read all tuples from outer plan and pass * If first time through, read all tuples from outer plan and pass
...@@ -69,7 +67,7 @@ ExecMaterial(Material *node) ...@@ -69,7 +67,7 @@ ExecMaterial(Material *node)
if (tuplestorestate == NULL) if (tuplestorestate == NULL)
{ {
Plan *outerNode; PlanState *outerNode;
/* /*
* Want to scan subplan in the forward direction while creating * Want to scan subplan in the forward direction while creating
...@@ -84,16 +82,16 @@ ExecMaterial(Material *node) ...@@ -84,16 +82,16 @@ ExecMaterial(Material *node)
tuplestorestate = tuplestore_begin_heap(true, /* randomAccess */ tuplestorestate = tuplestore_begin_heap(true, /* randomAccess */
SortMem); SortMem);
matstate->tuplestorestate = (void *) tuplestorestate; node->tuplestorestate = (void *) tuplestorestate;
/* /*
* Scan the subplan and feed all the tuples to tuplestore. * Scan the subplan and feed all the tuples to tuplestore.
*/ */
outerNode = outerPlan((Plan *) node); outerNode = outerPlanState(node);
for (;;) for (;;)
{ {
slot = ExecProcNode(outerNode, (Plan *) node); slot = ExecProcNode(outerNode);
if (TupIsNull(slot)) if (TupIsNull(slot))
break; break;
...@@ -117,7 +115,7 @@ ExecMaterial(Material *node) ...@@ -117,7 +115,7 @@ ExecMaterial(Material *node)
* Get the first or next tuple from tuplestore. Returns NULL if no * Get the first or next tuple from tuplestore. Returns NULL if no
* more tuples. * more tuples.
*/ */
slot = (TupleTableSlot *) matstate->csstate.cstate.cs_ResultTupleSlot; slot = (TupleTableSlot *) node->ss.ps.ps_ResultTupleSlot;
heapTuple = tuplestore_getheaptuple(tuplestorestate, heapTuple = tuplestore_getheaptuple(tuplestorestate,
ScanDirectionIsForward(dir), ScanDirectionIsForward(dir),
&should_free); &should_free);
...@@ -129,23 +127,20 @@ ExecMaterial(Material *node) ...@@ -129,23 +127,20 @@ ExecMaterial(Material *node)
* ExecInitMaterial * ExecInitMaterial
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
bool /* initialization status */ MaterialState *
ExecInitMaterial(Material *node, EState *estate, Plan *parent) ExecInitMaterial(Material *node, EState *estate)
{ {
MaterialState *matstate; MaterialState *matstate;
Plan *outerPlan; Plan *outerPlan;
/*
* assign the node's execution state
*/
node->plan.state = estate;
/* /*
* create state structure * create state structure
*/ */
matstate = makeNode(MaterialState); matstate = makeNode(MaterialState);
matstate->ss.ps.plan = (Plan *) node;
matstate->ss.ps.state = estate;
matstate->tuplestorestate = NULL; matstate->tuplestorestate = NULL;
node->matstate = matstate;
/* /*
* Miscellaneous initialization * Miscellaneous initialization
...@@ -161,24 +156,24 @@ ExecInitMaterial(Material *node, EState *estate, Plan *parent) ...@@ -161,24 +156,24 @@ ExecInitMaterial(Material *node, EState *estate, Plan *parent)
* *
* material nodes only return tuples from their materialized relation. * material nodes only return tuples from their materialized relation.
*/ */
ExecInitResultTupleSlot(estate, &matstate->csstate.cstate); ExecInitResultTupleSlot(estate, &matstate->ss.ps);
ExecInitScanTupleSlot(estate, &matstate->csstate); ExecInitScanTupleSlot(estate, &matstate->ss);
/* /*
* initializes child nodes * initializes child nodes
*/ */
outerPlan = outerPlan((Plan *) node); outerPlan = outerPlan(node);
ExecInitNode(outerPlan, estate, (Plan *) node); outerPlanState(matstate) = ExecInitNode(outerPlan, 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, &matstate->csstate.cstate); ExecAssignResultTypeFromOuterPlan(&matstate->ss.ps);
ExecAssignScanTypeFromOuterPlan((Plan *) node, &matstate->csstate); ExecAssignScanTypeFromOuterPlan(&matstate->ss);
matstate->csstate.cstate.cs_ProjInfo = NULL; matstate->ss.ps.ps_ProjInfo = NULL;
return TRUE; return matstate;
} }
int int
...@@ -194,33 +189,24 @@ ExecCountSlotsMaterial(Material *node) ...@@ -194,33 +189,24 @@ ExecCountSlotsMaterial(Material *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecEndMaterial(Material *node) ExecEndMaterial(MaterialState *node)
{ {
MaterialState *matstate;
Plan *outerPlan;
/* /*
* get info from the material state * clean out the tuple table
*/ */
matstate = node->matstate; ExecClearTuple(node->ss.ss_ScanTupleSlot);
/* /*
* shut down the subplan * shut down the subplan
*/ */
outerPlan = outerPlan((Plan *) node); ExecEndNode(outerPlanState(node));
ExecEndNode(outerPlan, (Plan *) node);
/*
* clean out the tuple table
*/
ExecClearTuple(matstate->csstate.css_ScanTupleSlot);
/* /*
* Release tuplestore resources * Release tuplestore resources
*/ */
if (matstate->tuplestorestate != NULL) if (node->tuplestorestate != NULL)
tuplestore_end((Tuplestorestate *) matstate->tuplestorestate); tuplestore_end((Tuplestorestate *) node->tuplestorestate);
matstate->tuplestorestate = NULL; node->tuplestorestate = NULL;
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -230,17 +216,15 @@ ExecEndMaterial(Material *node) ...@@ -230,17 +216,15 @@ ExecEndMaterial(Material *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecMaterialMarkPos(Material *node) ExecMaterialMarkPos(MaterialState *node)
{ {
MaterialState *matstate = node->matstate;
/* /*
* if we haven't materialized yet, just return. * if we haven't materialized yet, just return.
*/ */
if (!matstate->tuplestorestate) if (!node->tuplestorestate)
return; return;
tuplestore_markpos((Tuplestorestate *) matstate->tuplestorestate); tuplestore_markpos((Tuplestorestate *) node->tuplestorestate);
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -250,20 +234,18 @@ ExecMaterialMarkPos(Material *node) ...@@ -250,20 +234,18 @@ ExecMaterialMarkPos(Material *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecMaterialRestrPos(Material *node) ExecMaterialRestrPos(MaterialState *node)
{ {
MaterialState *matstate = node->matstate;
/* /*
* if we haven't materialized yet, just return. * if we haven't materialized yet, just return.
*/ */
if (!matstate->tuplestorestate) if (!node->tuplestorestate)
return; return;
/* /*
* restore the scan to the previously marked position * restore the scan to the previously marked position
*/ */
tuplestore_restorepos((Tuplestorestate *) matstate->tuplestorestate); tuplestore_restorepos((Tuplestorestate *) node->tuplestorestate);
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -273,19 +255,17 @@ ExecMaterialRestrPos(Material *node) ...@@ -273,19 +255,17 @@ ExecMaterialRestrPos(Material *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecMaterialReScan(Material *node, ExprContext *exprCtxt, Plan *parent) ExecMaterialReScan(MaterialState *node, ExprContext *exprCtxt)
{ {
MaterialState *matstate = node->matstate;
/* /*
* If we haven't materialized yet, just return. If outerplan' chgParam * If we haven't materialized yet, just return. If outerplan' chgParam
* is not NULL then it will be re-scanned by ExecProcNode, else - no * is not NULL then it will be re-scanned by ExecProcNode, else - no
* reason to re-scan it at all. * reason to re-scan it at all.
*/ */
if (!matstate->tuplestorestate) if (!node->tuplestorestate)
return; return;
ExecClearTuple(matstate->csstate.cstate.cs_ResultTupleSlot); ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
/* /*
* If subnode is to be rescanned then we forget previous stored * If subnode is to be rescanned then we forget previous stored
...@@ -293,11 +273,11 @@ ExecMaterialReScan(Material *node, ExprContext *exprCtxt, Plan *parent) ...@@ -293,11 +273,11 @@ ExecMaterialReScan(Material *node, ExprContext *exprCtxt, Plan *parent)
* *
* Otherwise we can just rewind and rescan the stored output. * Otherwise we can just rewind and rescan the stored output.
*/ */
if (((Plan *) node)->lefttree->chgParam != NULL) if (((PlanState *) node)->lefttree->chgParam != NULL)
{ {
tuplestore_end((Tuplestorestate *) matstate->tuplestorestate); tuplestore_end((Tuplestorestate *) node->tuplestorestate);
matstate->tuplestorestate = NULL; node->tuplestorestate = NULL;
} }
else else
tuplestore_rescan((Tuplestorestate *) matstate->tuplestorestate); tuplestore_rescan((Tuplestorestate *) node->tuplestorestate);
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.51 2002/09/04 20:31:18 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.52 2002/12/05 15:50:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -340,10 +340,9 @@ ExecMergeTupleDump(MergeJoinState *mergestate) ...@@ -340,10 +340,9 @@ ExecMergeTupleDump(MergeJoinState *mergestate)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
TupleTableSlot * TupleTableSlot *
ExecMergeJoin(MergeJoin *node) ExecMergeJoin(MergeJoinState *node)
{ {
EState *estate; EState *estate;
MergeJoinState *mergestate;
ScanDirection direction; ScanDirection direction;
List *innerSkipQual; List *innerSkipQual;
List *outerSkipQual; List *outerSkipQual;
...@@ -352,9 +351,9 @@ ExecMergeJoin(MergeJoin *node) ...@@ -352,9 +351,9 @@ ExecMergeJoin(MergeJoin *node)
List *otherqual; List *otherqual;
bool qualResult; bool qualResult;
bool compareResult; bool compareResult;
Plan *innerPlan; PlanState *innerPlan;
TupleTableSlot *innerTupleSlot; TupleTableSlot *innerTupleSlot;
Plan *outerPlan; PlanState *outerPlan;
TupleTableSlot *outerTupleSlot; TupleTableSlot *outerTupleSlot;
ExprContext *econtext; ExprContext *econtext;
bool doFillOuter; bool doFillOuter;
...@@ -363,17 +362,16 @@ ExecMergeJoin(MergeJoin *node) ...@@ -363,17 +362,16 @@ ExecMergeJoin(MergeJoin *node)
/* /*
* get information from node * get information from node
*/ */
mergestate = node->mergestate; estate = node->js.ps.state;
estate = node->join.plan.state;
direction = estate->es_direction; direction = estate->es_direction;
innerPlan = innerPlan((Plan *) node); innerPlan = innerPlanState(node);
outerPlan = outerPlan((Plan *) node); outerPlan = outerPlanState(node);
econtext = mergestate->jstate.cs_ExprContext; econtext = node->js.ps.ps_ExprContext;
mergeclauses = node->mergeclauses; mergeclauses = node->mergeclauses;
joinqual = node->join.joinqual; joinqual = node->js.joinqual;
otherqual = node->join.plan.qual; otherqual = node->js.ps.qual;
switch (node->join.jointype) switch (node->js.jointype)
{ {
case JOIN_INNER: case JOIN_INNER:
doFillOuter = false; doFillOuter = false;
...@@ -393,7 +391,7 @@ ExecMergeJoin(MergeJoin *node) ...@@ -393,7 +391,7 @@ ExecMergeJoin(MergeJoin *node)
break; break;
default: default:
elog(ERROR, "ExecMergeJoin: unsupported join type %d", elog(ERROR, "ExecMergeJoin: unsupported join type %d",
(int) node->join.jointype); (int) node->js.jointype);
doFillOuter = false; /* keep compiler quiet */ doFillOuter = false; /* keep compiler quiet */
doFillInner = false; doFillInner = false;
break; break;
...@@ -401,13 +399,13 @@ ExecMergeJoin(MergeJoin *node) ...@@ -401,13 +399,13 @@ ExecMergeJoin(MergeJoin *node)
if (ScanDirectionIsForward(direction)) if (ScanDirectionIsForward(direction))
{ {
outerSkipQual = mergestate->mj_OuterSkipQual; outerSkipQual = node->mj_OuterSkipQual;
innerSkipQual = mergestate->mj_InnerSkipQual; innerSkipQual = node->mj_InnerSkipQual;
} }
else else
{ {
outerSkipQual = mergestate->mj_InnerSkipQual; outerSkipQual = node->mj_InnerSkipQual;
innerSkipQual = mergestate->mj_OuterSkipQual; innerSkipQual = node->mj_OuterSkipQual;
} }
/* /*
...@@ -415,16 +413,16 @@ ExecMergeJoin(MergeJoin *node) ...@@ -415,16 +413,16 @@ ExecMergeJoin(MergeJoin *node)
* join tuple (because there is a function-returning-set in the * join 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 (mergestate->jstate.cs_TupFromTlist) if (node->js.ps.ps_TupFromTlist)
{ {
TupleTableSlot *result; TupleTableSlot *result;
ExprDoneCond isDone; ExprDoneCond isDone;
result = ExecProject(mergestate->jstate.cs_ProjInfo, &isDone); result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
if (isDone == ExprMultipleResult) if (isDone == ExprMultipleResult)
return result; return result;
/* Done with that source tuple... */ /* Done with that source tuple... */
mergestate->jstate.cs_TupFromTlist = false; node->js.ps.ps_TupFromTlist = false;
} }
/* /*
...@@ -444,9 +442,9 @@ ExecMergeJoin(MergeJoin *node) ...@@ -444,9 +442,9 @@ ExecMergeJoin(MergeJoin *node)
* Note: The join states are highlighted with 32-* comments for * Note: The join states are highlighted with 32-* comments for
* improved readability. * improved readability.
*/ */
MJ_dump(mergestate); MJ_dump(node);
switch (mergestate->mj_JoinState) switch (node->mj_JoinState)
{ {
/* /*
* EXEC_MJ_INITIALIZE means that this is the first time * EXEC_MJ_INITIALIZE means that this is the first time
...@@ -459,8 +457,8 @@ ExecMergeJoin(MergeJoin *node) ...@@ -459,8 +457,8 @@ ExecMergeJoin(MergeJoin *node)
case EXEC_MJ_INITIALIZE: case EXEC_MJ_INITIALIZE:
MJ_printf("ExecMergeJoin: EXEC_MJ_INITIALIZE\n"); MJ_printf("ExecMergeJoin: EXEC_MJ_INITIALIZE\n");
outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node); outerTupleSlot = ExecProcNode(outerPlan);
mergestate->mj_OuterTupleSlot = outerTupleSlot; node->mj_OuterTupleSlot = outerTupleSlot;
if (TupIsNull(outerTupleSlot)) if (TupIsNull(outerTupleSlot))
{ {
MJ_printf("ExecMergeJoin: outer subplan is empty\n"); MJ_printf("ExecMergeJoin: outer subplan is empty\n");
...@@ -471,16 +469,16 @@ ExecMergeJoin(MergeJoin *node) ...@@ -471,16 +469,16 @@ ExecMergeJoin(MergeJoin *node)
* inner tuples. We set MatchedInner = true to * inner tuples. We set MatchedInner = true to
* force the ENDOUTER state to advance inner. * force the ENDOUTER state to advance inner.
*/ */
mergestate->mj_JoinState = EXEC_MJ_ENDOUTER; node->mj_JoinState = EXEC_MJ_ENDOUTER;
mergestate->mj_MatchedInner = true; node->mj_MatchedInner = true;
break; break;
} }
/* Otherwise we're done. */ /* Otherwise we're done. */
return NULL; return NULL;
} }
innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node); innerTupleSlot = ExecProcNode(innerPlan);
mergestate->mj_InnerTupleSlot = innerTupleSlot; node->mj_InnerTupleSlot = innerTupleSlot;
if (TupIsNull(innerTupleSlot)) if (TupIsNull(innerTupleSlot))
{ {
MJ_printf("ExecMergeJoin: inner subplan is empty\n"); MJ_printf("ExecMergeJoin: inner subplan is empty\n");
...@@ -493,8 +491,8 @@ ExecMergeJoin(MergeJoin *node) ...@@ -493,8 +491,8 @@ ExecMergeJoin(MergeJoin *node)
* state to emit this tuple before advancing * state to emit this tuple before advancing
* outer. * outer.
*/ */
mergestate->mj_JoinState = EXEC_MJ_ENDINNER; node->mj_JoinState = EXEC_MJ_ENDINNER;
mergestate->mj_MatchedOuter = false; node->mj_MatchedOuter = false;
break; break;
} }
/* Otherwise we're done. */ /* Otherwise we're done. */
...@@ -505,7 +503,7 @@ ExecMergeJoin(MergeJoin *node) ...@@ -505,7 +503,7 @@ ExecMergeJoin(MergeJoin *node)
* OK, we have the initial tuples. Begin by skipping * OK, we have the initial tuples. Begin by skipping
* unmatched inner tuples. * unmatched inner tuples.
*/ */
mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_BEGIN; node->mj_JoinState = EXEC_MJ_SKIPINNER_BEGIN;
break; break;
/* /*
...@@ -519,9 +517,9 @@ ExecMergeJoin(MergeJoin *node) ...@@ -519,9 +517,9 @@ ExecMergeJoin(MergeJoin *node)
ExecMarkPos(innerPlan); ExecMarkPos(innerPlan);
MarkInnerTuple(mergestate->mj_InnerTupleSlot, mergestate); MarkInnerTuple(node->mj_InnerTupleSlot, node);
mergestate->mj_JoinState = EXEC_MJ_JOINTEST; node->mj_JoinState = EXEC_MJ_JOINTEST;
break; break;
/* /*
...@@ -538,18 +536,18 @@ ExecMergeJoin(MergeJoin *node) ...@@ -538,18 +536,18 @@ ExecMergeJoin(MergeJoin *node)
ResetExprContext(econtext); ResetExprContext(econtext);
outerTupleSlot = mergestate->mj_OuterTupleSlot; outerTupleSlot = node->mj_OuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot; econtext->ecxt_outertuple = outerTupleSlot;
innerTupleSlot = mergestate->mj_InnerTupleSlot; innerTupleSlot = node->mj_InnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot;
qualResult = ExecQual(mergeclauses, econtext, false); qualResult = ExecQual(mergeclauses, econtext, false);
MJ_DEBUG_QUAL(mergeclauses, qualResult); MJ_DEBUG_QUAL(mergeclauses, qualResult);
if (qualResult) if (qualResult)
mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES; node->mj_JoinState = EXEC_MJ_JOINTUPLES;
else else
mergestate->mj_JoinState = EXEC_MJ_NEXTOUTER; node->mj_JoinState = EXEC_MJ_NEXTOUTER;
break; break;
/* /*
...@@ -560,7 +558,7 @@ ExecMergeJoin(MergeJoin *node) ...@@ -560,7 +558,7 @@ ExecMergeJoin(MergeJoin *node)
case EXEC_MJ_JOINTUPLES: case EXEC_MJ_JOINTUPLES:
MJ_printf("ExecMergeJoin: EXEC_MJ_JOINTUPLES\n"); MJ_printf("ExecMergeJoin: EXEC_MJ_JOINTUPLES\n");
mergestate->mj_JoinState = EXEC_MJ_NEXTINNER; node->mj_JoinState = EXEC_MJ_NEXTINNER;
/* /*
* Check the extra qual conditions to see if we actually * Check the extra qual conditions to see if we actually
...@@ -582,8 +580,8 @@ ExecMergeJoin(MergeJoin *node) ...@@ -582,8 +580,8 @@ ExecMergeJoin(MergeJoin *node)
if (qualResult) if (qualResult)
{ {
mergestate->mj_MatchedOuter = true; node->mj_MatchedOuter = true;
mergestate->mj_MatchedInner = true; node->mj_MatchedInner = true;
qualResult = (otherqual == NIL || qualResult = (otherqual == NIL ||
ExecQual(otherqual, econtext, false)); ExecQual(otherqual, econtext, false));
...@@ -601,12 +599,12 @@ ExecMergeJoin(MergeJoin *node) ...@@ -601,12 +599,12 @@ ExecMergeJoin(MergeJoin *node)
MJ_printf("ExecMergeJoin: returning tuple\n"); MJ_printf("ExecMergeJoin: returning tuple\n");
result = ExecProject(mergestate->jstate.cs_ProjInfo, result = ExecProject(node->js.ps.ps_ProjInfo,
&isDone); &isDone);
if (isDone != ExprEndResult) if (isDone != ExprEndResult)
{ {
mergestate->jstate.cs_TupFromTlist = node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult); (isDone == ExprMultipleResult);
return result; return result;
} }
...@@ -625,20 +623,20 @@ ExecMergeJoin(MergeJoin *node) ...@@ -625,20 +623,20 @@ ExecMergeJoin(MergeJoin *node)
case EXEC_MJ_NEXTINNER: case EXEC_MJ_NEXTINNER:
MJ_printf("ExecMergeJoin: EXEC_MJ_NEXTINNER\n"); MJ_printf("ExecMergeJoin: EXEC_MJ_NEXTINNER\n");
if (doFillInner && !mergestate->mj_MatchedInner) if (doFillInner && !node->mj_MatchedInner)
{ {
/* /*
* Generate a fake join tuple with nulls for the outer * Generate a fake join tuple with nulls for the outer
* tuple, and return it if it passes the non-join * tuple, and return it if it passes the non-join
* quals. * quals.
*/ */
mergestate->mj_MatchedInner = true; /* do it only once */ node->mj_MatchedInner = true; /* do it only once */
ResetExprContext(econtext); ResetExprContext(econtext);
outerTupleSlot = mergestate->mj_NullOuterTupleSlot; outerTupleSlot = node->mj_NullOuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot; econtext->ecxt_outertuple = outerTupleSlot;
innerTupleSlot = mergestate->mj_InnerTupleSlot; innerTupleSlot = node->mj_InnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot;
if (ExecQual(otherqual, econtext, false)) if (ExecQual(otherqual, econtext, false))
...@@ -653,12 +651,12 @@ ExecMergeJoin(MergeJoin *node) ...@@ -653,12 +651,12 @@ ExecMergeJoin(MergeJoin *node)
MJ_printf("ExecMergeJoin: returning fill tuple\n"); MJ_printf("ExecMergeJoin: returning fill tuple\n");
result = ExecProject(mergestate->jstate.cs_ProjInfo, result = ExecProject(node->js.ps.ps_ProjInfo,
&isDone); &isDone);
if (isDone != ExprEndResult) if (isDone != ExprEndResult)
{ {
mergestate->jstate.cs_TupFromTlist = node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult); (isDone == ExprMultipleResult);
return result; return result;
} }
...@@ -668,15 +666,15 @@ ExecMergeJoin(MergeJoin *node) ...@@ -668,15 +666,15 @@ ExecMergeJoin(MergeJoin *node)
/* /*
* now we get the next inner tuple, if any * now we get the next inner tuple, if any
*/ */
innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node); innerTupleSlot = ExecProcNode(innerPlan);
mergestate->mj_InnerTupleSlot = innerTupleSlot; node->mj_InnerTupleSlot = innerTupleSlot;
MJ_DEBUG_PROC_NODE(innerTupleSlot); MJ_DEBUG_PROC_NODE(innerTupleSlot);
mergestate->mj_MatchedInner = false; node->mj_MatchedInner = false;
if (TupIsNull(innerTupleSlot)) if (TupIsNull(innerTupleSlot))
mergestate->mj_JoinState = EXEC_MJ_NEXTOUTER; node->mj_JoinState = EXEC_MJ_NEXTOUTER;
else else
mergestate->mj_JoinState = EXEC_MJ_JOINTEST; node->mj_JoinState = EXEC_MJ_JOINTEST;
break; break;
/*------------------------------------------- /*-------------------------------------------
...@@ -701,20 +699,20 @@ ExecMergeJoin(MergeJoin *node) ...@@ -701,20 +699,20 @@ ExecMergeJoin(MergeJoin *node)
case EXEC_MJ_NEXTOUTER: case EXEC_MJ_NEXTOUTER:
MJ_printf("ExecMergeJoin: EXEC_MJ_NEXTOUTER\n"); MJ_printf("ExecMergeJoin: EXEC_MJ_NEXTOUTER\n");
if (doFillOuter && !mergestate->mj_MatchedOuter) if (doFillOuter && !node->mj_MatchedOuter)
{ {
/* /*
* Generate a fake join tuple with nulls for the inner * Generate a fake join tuple with nulls for the inner
* tuple, and return it if it passes the non-join * tuple, and return it if it passes the non-join
* quals. * quals.
*/ */
mergestate->mj_MatchedOuter = true; /* do it only once */ node->mj_MatchedOuter = true; /* do it only once */
ResetExprContext(econtext); ResetExprContext(econtext);
outerTupleSlot = mergestate->mj_OuterTupleSlot; outerTupleSlot = node->mj_OuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot; econtext->ecxt_outertuple = outerTupleSlot;
innerTupleSlot = mergestate->mj_NullInnerTupleSlot; innerTupleSlot = node->mj_NullInnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot;
if (ExecQual(otherqual, econtext, false)) if (ExecQual(otherqual, econtext, false))
...@@ -729,12 +727,12 @@ ExecMergeJoin(MergeJoin *node) ...@@ -729,12 +727,12 @@ ExecMergeJoin(MergeJoin *node)
MJ_printf("ExecMergeJoin: returning fill tuple\n"); MJ_printf("ExecMergeJoin: returning fill tuple\n");
result = ExecProject(mergestate->jstate.cs_ProjInfo, result = ExecProject(node->js.ps.ps_ProjInfo,
&isDone); &isDone);
if (isDone != ExprEndResult) if (isDone != ExprEndResult)
{ {
mergestate->jstate.cs_TupFromTlist = node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult); (isDone == ExprMultipleResult);
return result; return result;
} }
...@@ -744,10 +742,10 @@ ExecMergeJoin(MergeJoin *node) ...@@ -744,10 +742,10 @@ ExecMergeJoin(MergeJoin *node)
/* /*
* now we get the next outer tuple, if any * now we get the next outer tuple, if any
*/ */
outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node); outerTupleSlot = ExecProcNode(outerPlan);
mergestate->mj_OuterTupleSlot = outerTupleSlot; node->mj_OuterTupleSlot = outerTupleSlot;
MJ_DEBUG_PROC_NODE(outerTupleSlot); MJ_DEBUG_PROC_NODE(outerTupleSlot);
mergestate->mj_MatchedOuter = false; node->mj_MatchedOuter = false;
/* /*
* if the outer tuple is null then we are done with the * if the outer tuple is null then we are done with the
...@@ -756,21 +754,21 @@ ExecMergeJoin(MergeJoin *node) ...@@ -756,21 +754,21 @@ ExecMergeJoin(MergeJoin *node)
if (TupIsNull(outerTupleSlot)) if (TupIsNull(outerTupleSlot))
{ {
MJ_printf("ExecMergeJoin: end of outer subplan\n"); MJ_printf("ExecMergeJoin: end of outer subplan\n");
innerTupleSlot = mergestate->mj_InnerTupleSlot; innerTupleSlot = node->mj_InnerTupleSlot;
if (doFillInner && !TupIsNull(innerTupleSlot)) if (doFillInner && !TupIsNull(innerTupleSlot))
{ {
/* /*
* Need to emit right-join tuples for remaining * Need to emit right-join tuples for remaining
* inner tuples. * inner tuples.
*/ */
mergestate->mj_JoinState = EXEC_MJ_ENDOUTER; node->mj_JoinState = EXEC_MJ_ENDOUTER;
break; break;
} }
/* Otherwise we're done. */ /* Otherwise we're done. */
return NULL; return NULL;
} }
mergestate->mj_JoinState = EXEC_MJ_TESTOUTER; node->mj_JoinState = EXEC_MJ_TESTOUTER;
break; break;
/*-------------------------------------------------------- /*--------------------------------------------------------
...@@ -816,9 +814,9 @@ ExecMergeJoin(MergeJoin *node) ...@@ -816,9 +814,9 @@ ExecMergeJoin(MergeJoin *node)
*/ */
ResetExprContext(econtext); ResetExprContext(econtext);
outerTupleSlot = mergestate->mj_OuterTupleSlot; outerTupleSlot = node->mj_OuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot; econtext->ecxt_outertuple = outerTupleSlot;
innerTupleSlot = mergestate->mj_MarkedTupleSlot; innerTupleSlot = node->mj_MarkedTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot;
qualResult = ExecQual(mergeclauses, econtext, false); qualResult = ExecQual(mergeclauses, econtext, false);
...@@ -843,7 +841,7 @@ ExecMergeJoin(MergeJoin *node) ...@@ -843,7 +841,7 @@ ExecMergeJoin(MergeJoin *node)
* the extra joinquals. * the extra joinquals.
*/ */
ExecRestrPos(innerPlan); ExecRestrPos(innerPlan);
mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES; node->mj_JoinState = EXEC_MJ_JOINTUPLES;
} }
else else
{ {
...@@ -862,7 +860,7 @@ ExecMergeJoin(MergeJoin *node) ...@@ -862,7 +860,7 @@ ExecMergeJoin(MergeJoin *node)
* larger than our marked inner tuples. So we're done. * larger than our marked inner tuples. So we're done.
* ---------------- * ----------------
*/ */
innerTupleSlot = mergestate->mj_InnerTupleSlot; innerTupleSlot = node->mj_InnerTupleSlot;
if (TupIsNull(innerTupleSlot)) if (TupIsNull(innerTupleSlot))
{ {
if (doFillOuter) if (doFillOuter)
...@@ -871,7 +869,7 @@ ExecMergeJoin(MergeJoin *node) ...@@ -871,7 +869,7 @@ ExecMergeJoin(MergeJoin *node)
* Need to emit left-join tuples for remaining * Need to emit left-join tuples for remaining
* outer tuples. * outer tuples.
*/ */
mergestate->mj_JoinState = EXEC_MJ_ENDINNER; node->mj_JoinState = EXEC_MJ_ENDINNER;
break; break;
} }
/* Otherwise we're done. */ /* Otherwise we're done. */
...@@ -879,7 +877,7 @@ ExecMergeJoin(MergeJoin *node) ...@@ -879,7 +877,7 @@ ExecMergeJoin(MergeJoin *node)
} }
/* continue on to skip outer tuples */ /* continue on to skip outer tuples */
mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER_BEGIN; node->mj_JoinState = EXEC_MJ_SKIPOUTER_BEGIN;
} }
break; break;
...@@ -913,9 +911,9 @@ ExecMergeJoin(MergeJoin *node) ...@@ -913,9 +911,9 @@ ExecMergeJoin(MergeJoin *node)
*/ */
ResetExprContext(econtext); ResetExprContext(econtext);
outerTupleSlot = mergestate->mj_OuterTupleSlot; outerTupleSlot = node->mj_OuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot; econtext->ecxt_outertuple = outerTupleSlot;
innerTupleSlot = mergestate->mj_InnerTupleSlot; innerTupleSlot = node->mj_InnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot;
qualResult = ExecQual(mergeclauses, econtext, false); qualResult = ExecQual(mergeclauses, econtext, false);
...@@ -925,13 +923,13 @@ ExecMergeJoin(MergeJoin *node) ...@@ -925,13 +923,13 @@ ExecMergeJoin(MergeJoin *node)
{ {
ExecMarkPos(innerPlan); ExecMarkPos(innerPlan);
MarkInnerTuple(innerTupleSlot, mergestate); MarkInnerTuple(innerTupleSlot, node);
mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES; node->mj_JoinState = EXEC_MJ_JOINTUPLES;
break; break;
} }
mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER_TEST; node->mj_JoinState = EXEC_MJ_SKIPOUTER_TEST;
break; break;
case EXEC_MJ_SKIPOUTER_TEST: case EXEC_MJ_SKIPOUTER_TEST:
...@@ -940,9 +938,9 @@ ExecMergeJoin(MergeJoin *node) ...@@ -940,9 +938,9 @@ ExecMergeJoin(MergeJoin *node)
/* /*
* ok, now test the skip qualification * ok, now test the skip qualification
*/ */
outerTupleSlot = mergestate->mj_OuterTupleSlot; outerTupleSlot = node->mj_OuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot; econtext->ecxt_outertuple = outerTupleSlot;
innerTupleSlot = mergestate->mj_InnerTupleSlot; innerTupleSlot = node->mj_InnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot;
compareResult = MergeCompare(mergeclauses, compareResult = MergeCompare(mergeclauses,
...@@ -957,7 +955,7 @@ ExecMergeJoin(MergeJoin *node) ...@@ -957,7 +955,7 @@ ExecMergeJoin(MergeJoin *node)
*/ */
if (compareResult) if (compareResult)
{ {
mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER_ADVANCE; node->mj_JoinState = EXEC_MJ_SKIPOUTER_ADVANCE;
break; break;
} }
...@@ -973,9 +971,9 @@ ExecMergeJoin(MergeJoin *node) ...@@ -973,9 +971,9 @@ ExecMergeJoin(MergeJoin *node)
MJ_DEBUG_MERGE_COMPARE(innerSkipQual, compareResult); MJ_DEBUG_MERGE_COMPARE(innerSkipQual, compareResult);
if (compareResult) if (compareResult)
mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_BEGIN; node->mj_JoinState = EXEC_MJ_SKIPINNER_BEGIN;
else else
mergestate->mj_JoinState = EXEC_MJ_JOINMARK; node->mj_JoinState = EXEC_MJ_JOINMARK;
break; break;
/* /*
...@@ -985,20 +983,20 @@ ExecMergeJoin(MergeJoin *node) ...@@ -985,20 +983,20 @@ ExecMergeJoin(MergeJoin *node)
case EXEC_MJ_SKIPOUTER_ADVANCE: case EXEC_MJ_SKIPOUTER_ADVANCE:
MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPOUTER_ADVANCE\n"); MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPOUTER_ADVANCE\n");
if (doFillOuter && !mergestate->mj_MatchedOuter) if (doFillOuter && !node->mj_MatchedOuter)
{ {
/* /*
* Generate a fake join tuple with nulls for the inner * Generate a fake join tuple with nulls for the inner
* tuple, and return it if it passes the non-join * tuple, and return it if it passes the non-join
* quals. * quals.
*/ */
mergestate->mj_MatchedOuter = true; /* do it only once */ node->mj_MatchedOuter = true; /* do it only once */
ResetExprContext(econtext); ResetExprContext(econtext);
outerTupleSlot = mergestate->mj_OuterTupleSlot; outerTupleSlot = node->mj_OuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot; econtext->ecxt_outertuple = outerTupleSlot;
innerTupleSlot = mergestate->mj_NullInnerTupleSlot; innerTupleSlot = node->mj_NullInnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot;
if (ExecQual(otherqual, econtext, false)) if (ExecQual(otherqual, econtext, false))
...@@ -1013,12 +1011,12 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1013,12 +1011,12 @@ ExecMergeJoin(MergeJoin *node)
MJ_printf("ExecMergeJoin: returning fill tuple\n"); MJ_printf("ExecMergeJoin: returning fill tuple\n");
result = ExecProject(mergestate->jstate.cs_ProjInfo, result = ExecProject(node->js.ps.ps_ProjInfo,
&isDone); &isDone);
if (isDone != ExprEndResult) if (isDone != ExprEndResult)
{ {
mergestate->jstate.cs_TupFromTlist = node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult); (isDone == ExprMultipleResult);
return result; return result;
} }
...@@ -1028,10 +1026,10 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1028,10 +1026,10 @@ ExecMergeJoin(MergeJoin *node)
/* /*
* now we get the next outer tuple, if any * now we get the next outer tuple, if any
*/ */
outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node); outerTupleSlot = ExecProcNode(outerPlan);
mergestate->mj_OuterTupleSlot = outerTupleSlot; node->mj_OuterTupleSlot = outerTupleSlot;
MJ_DEBUG_PROC_NODE(outerTupleSlot); MJ_DEBUG_PROC_NODE(outerTupleSlot);
mergestate->mj_MatchedOuter = false; node->mj_MatchedOuter = false;
/* /*
* if the outer tuple is null then we are done with the * if the outer tuple is null then we are done with the
...@@ -1040,14 +1038,14 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1040,14 +1038,14 @@ ExecMergeJoin(MergeJoin *node)
if (TupIsNull(outerTupleSlot)) if (TupIsNull(outerTupleSlot))
{ {
MJ_printf("ExecMergeJoin: end of outer subplan\n"); MJ_printf("ExecMergeJoin: end of outer subplan\n");
innerTupleSlot = mergestate->mj_InnerTupleSlot; innerTupleSlot = node->mj_InnerTupleSlot;
if (doFillInner && !TupIsNull(innerTupleSlot)) if (doFillInner && !TupIsNull(innerTupleSlot))
{ {
/* /*
* Need to emit right-join tuples for remaining * Need to emit right-join tuples for remaining
* inner tuples. * inner tuples.
*/ */
mergestate->mj_JoinState = EXEC_MJ_ENDOUTER; node->mj_JoinState = EXEC_MJ_ENDOUTER;
break; break;
} }
/* Otherwise we're done. */ /* Otherwise we're done. */
...@@ -1057,7 +1055,7 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1057,7 +1055,7 @@ ExecMergeJoin(MergeJoin *node)
/* /*
* otherwise test the new tuple against the skip qual. * otherwise test the new tuple against the skip qual.
*/ */
mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER_TEST; node->mj_JoinState = EXEC_MJ_SKIPOUTER_TEST;
break; break;
/*----------------------------------------------------------- /*-----------------------------------------------------------
...@@ -1090,9 +1088,9 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1090,9 +1088,9 @@ ExecMergeJoin(MergeJoin *node)
*/ */
ResetExprContext(econtext); ResetExprContext(econtext);
outerTupleSlot = mergestate->mj_OuterTupleSlot; outerTupleSlot = node->mj_OuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot; econtext->ecxt_outertuple = outerTupleSlot;
innerTupleSlot = mergestate->mj_InnerTupleSlot; innerTupleSlot = node->mj_InnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot;
qualResult = ExecQual(mergeclauses, econtext, false); qualResult = ExecQual(mergeclauses, econtext, false);
...@@ -1102,13 +1100,13 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1102,13 +1100,13 @@ ExecMergeJoin(MergeJoin *node)
{ {
ExecMarkPos(innerPlan); ExecMarkPos(innerPlan);
MarkInnerTuple(innerTupleSlot, mergestate); MarkInnerTuple(innerTupleSlot, node);
mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES; node->mj_JoinState = EXEC_MJ_JOINTUPLES;
break; break;
} }
mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_TEST; node->mj_JoinState = EXEC_MJ_SKIPINNER_TEST;
break; break;
case EXEC_MJ_SKIPINNER_TEST: case EXEC_MJ_SKIPINNER_TEST:
...@@ -1117,9 +1115,9 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1117,9 +1115,9 @@ ExecMergeJoin(MergeJoin *node)
/* /*
* ok, now test the skip qualification * ok, now test the skip qualification
*/ */
outerTupleSlot = mergestate->mj_OuterTupleSlot; outerTupleSlot = node->mj_OuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot; econtext->ecxt_outertuple = outerTupleSlot;
innerTupleSlot = mergestate->mj_InnerTupleSlot; innerTupleSlot = node->mj_InnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot;
compareResult = MergeCompare(mergeclauses, compareResult = MergeCompare(mergeclauses,
...@@ -1134,7 +1132,7 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1134,7 +1132,7 @@ ExecMergeJoin(MergeJoin *node)
*/ */
if (compareResult) if (compareResult)
{ {
mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_ADVANCE; node->mj_JoinState = EXEC_MJ_SKIPINNER_ADVANCE;
break; break;
} }
...@@ -1150,9 +1148,9 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1150,9 +1148,9 @@ ExecMergeJoin(MergeJoin *node)
MJ_DEBUG_MERGE_COMPARE(outerSkipQual, compareResult); MJ_DEBUG_MERGE_COMPARE(outerSkipQual, compareResult);
if (compareResult) if (compareResult)
mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER_BEGIN; node->mj_JoinState = EXEC_MJ_SKIPOUTER_BEGIN;
else else
mergestate->mj_JoinState = EXEC_MJ_JOINMARK; node->mj_JoinState = EXEC_MJ_JOINMARK;
break; break;
/* /*
...@@ -1162,20 +1160,20 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1162,20 +1160,20 @@ ExecMergeJoin(MergeJoin *node)
case EXEC_MJ_SKIPINNER_ADVANCE: case EXEC_MJ_SKIPINNER_ADVANCE:
MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPINNER_ADVANCE\n"); MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPINNER_ADVANCE\n");
if (doFillInner && !mergestate->mj_MatchedInner) if (doFillInner && !node->mj_MatchedInner)
{ {
/* /*
* Generate a fake join tuple with nulls for the outer * Generate a fake join tuple with nulls for the outer
* tuple, and return it if it passes the non-join * tuple, and return it if it passes the non-join
* quals. * quals.
*/ */
mergestate->mj_MatchedInner = true; /* do it only once */ node->mj_MatchedInner = true; /* do it only once */
ResetExprContext(econtext); ResetExprContext(econtext);
outerTupleSlot = mergestate->mj_NullOuterTupleSlot; outerTupleSlot = node->mj_NullOuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot; econtext->ecxt_outertuple = outerTupleSlot;
innerTupleSlot = mergestate->mj_InnerTupleSlot; innerTupleSlot = node->mj_InnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot;
if (ExecQual(otherqual, econtext, false)) if (ExecQual(otherqual, econtext, false))
...@@ -1190,12 +1188,12 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1190,12 +1188,12 @@ ExecMergeJoin(MergeJoin *node)
MJ_printf("ExecMergeJoin: returning fill tuple\n"); MJ_printf("ExecMergeJoin: returning fill tuple\n");
result = ExecProject(mergestate->jstate.cs_ProjInfo, result = ExecProject(node->js.ps.ps_ProjInfo,
&isDone); &isDone);
if (isDone != ExprEndResult) if (isDone != ExprEndResult)
{ {
mergestate->jstate.cs_TupFromTlist = node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult); (isDone == ExprMultipleResult);
return result; return result;
} }
...@@ -1205,10 +1203,10 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1205,10 +1203,10 @@ ExecMergeJoin(MergeJoin *node)
/* /*
* now we get the next inner tuple, if any * now we get the next inner tuple, if any
*/ */
innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node); innerTupleSlot = ExecProcNode(innerPlan);
mergestate->mj_InnerTupleSlot = innerTupleSlot; node->mj_InnerTupleSlot = innerTupleSlot;
MJ_DEBUG_PROC_NODE(innerTupleSlot); MJ_DEBUG_PROC_NODE(innerTupleSlot);
mergestate->mj_MatchedInner = false; node->mj_MatchedInner = false;
/* /*
* if the inner tuple is null then we are done with the * if the inner tuple is null then we are done with the
...@@ -1217,14 +1215,14 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1217,14 +1215,14 @@ ExecMergeJoin(MergeJoin *node)
if (TupIsNull(innerTupleSlot)) if (TupIsNull(innerTupleSlot))
{ {
MJ_printf("ExecMergeJoin: end of inner subplan\n"); MJ_printf("ExecMergeJoin: end of inner subplan\n");
outerTupleSlot = mergestate->mj_OuterTupleSlot; outerTupleSlot = node->mj_OuterTupleSlot;
if (doFillOuter && !TupIsNull(outerTupleSlot)) if (doFillOuter && !TupIsNull(outerTupleSlot))
{ {
/* /*
* Need to emit left-join tuples for remaining * Need to emit left-join tuples for remaining
* outer tuples. * outer tuples.
*/ */
mergestate->mj_JoinState = EXEC_MJ_ENDINNER; node->mj_JoinState = EXEC_MJ_ENDINNER;
break; break;
} }
/* Otherwise we're done. */ /* Otherwise we're done. */
...@@ -1234,7 +1232,7 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1234,7 +1232,7 @@ ExecMergeJoin(MergeJoin *node)
/* /*
* otherwise test the new tuple against the skip qual. * otherwise test the new tuple against the skip qual.
*/ */
mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_TEST; node->mj_JoinState = EXEC_MJ_SKIPINNER_TEST;
break; break;
/* /*
...@@ -1247,20 +1245,20 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1247,20 +1245,20 @@ ExecMergeJoin(MergeJoin *node)
Assert(doFillInner); Assert(doFillInner);
if (!mergestate->mj_MatchedInner) if (!node->mj_MatchedInner)
{ {
/* /*
* Generate a fake join tuple with nulls for the outer * Generate a fake join tuple with nulls for the outer
* tuple, and return it if it passes the non-join * tuple, and return it if it passes the non-join
* quals. * quals.
*/ */
mergestate->mj_MatchedInner = true; /* do it only once */ node->mj_MatchedInner = true; /* do it only once */
ResetExprContext(econtext); ResetExprContext(econtext);
outerTupleSlot = mergestate->mj_NullOuterTupleSlot; outerTupleSlot = node->mj_NullOuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot; econtext->ecxt_outertuple = outerTupleSlot;
innerTupleSlot = mergestate->mj_InnerTupleSlot; innerTupleSlot = node->mj_InnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot;
if (ExecQual(otherqual, econtext, false)) if (ExecQual(otherqual, econtext, false))
...@@ -1275,12 +1273,12 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1275,12 +1273,12 @@ ExecMergeJoin(MergeJoin *node)
MJ_printf("ExecMergeJoin: returning fill tuple\n"); MJ_printf("ExecMergeJoin: returning fill tuple\n");
result = ExecProject(mergestate->jstate.cs_ProjInfo, result = ExecProject(node->js.ps.ps_ProjInfo,
&isDone); &isDone);
if (isDone != ExprEndResult) if (isDone != ExprEndResult)
{ {
mergestate->jstate.cs_TupFromTlist = node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult); (isDone == ExprMultipleResult);
return result; return result;
} }
...@@ -1290,10 +1288,10 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1290,10 +1288,10 @@ ExecMergeJoin(MergeJoin *node)
/* /*
* now we get the next inner tuple, if any * now we get the next inner tuple, if any
*/ */
innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node); innerTupleSlot = ExecProcNode(innerPlan);
mergestate->mj_InnerTupleSlot = innerTupleSlot; node->mj_InnerTupleSlot = innerTupleSlot;
MJ_DEBUG_PROC_NODE(innerTupleSlot); MJ_DEBUG_PROC_NODE(innerTupleSlot);
mergestate->mj_MatchedInner = false; node->mj_MatchedInner = false;
if (TupIsNull(innerTupleSlot)) if (TupIsNull(innerTupleSlot))
{ {
...@@ -1314,20 +1312,20 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1314,20 +1312,20 @@ ExecMergeJoin(MergeJoin *node)
Assert(doFillOuter); Assert(doFillOuter);
if (!mergestate->mj_MatchedOuter) if (!node->mj_MatchedOuter)
{ {
/* /*
* Generate a fake join tuple with nulls for the inner * Generate a fake join tuple with nulls for the inner
* tuple, and return it if it passes the non-join * tuple, and return it if it passes the non-join
* quals. * quals.
*/ */
mergestate->mj_MatchedOuter = true; /* do it only once */ node->mj_MatchedOuter = true; /* do it only once */
ResetExprContext(econtext); ResetExprContext(econtext);
outerTupleSlot = mergestate->mj_OuterTupleSlot; outerTupleSlot = node->mj_OuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot; econtext->ecxt_outertuple = outerTupleSlot;
innerTupleSlot = mergestate->mj_NullInnerTupleSlot; innerTupleSlot = node->mj_NullInnerTupleSlot;
econtext->ecxt_innertuple = innerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot;
if (ExecQual(otherqual, econtext, false)) if (ExecQual(otherqual, econtext, false))
...@@ -1342,12 +1340,12 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1342,12 +1340,12 @@ ExecMergeJoin(MergeJoin *node)
MJ_printf("ExecMergeJoin: returning fill tuple\n"); MJ_printf("ExecMergeJoin: returning fill tuple\n");
result = ExecProject(mergestate->jstate.cs_ProjInfo, result = ExecProject(node->js.ps.ps_ProjInfo,
&isDone); &isDone);
if (isDone != ExprEndResult) if (isDone != ExprEndResult)
{ {
mergestate->jstate.cs_TupFromTlist = node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult); (isDone == ExprMultipleResult);
return result; return result;
} }
...@@ -1357,10 +1355,10 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1357,10 +1355,10 @@ ExecMergeJoin(MergeJoin *node)
/* /*
* now we get the next outer tuple, if any * now we get the next outer tuple, if any
*/ */
outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node); outerTupleSlot = ExecProcNode(outerPlan);
mergestate->mj_OuterTupleSlot = outerTupleSlot; node->mj_OuterTupleSlot = outerTupleSlot;
MJ_DEBUG_PROC_NODE(outerTupleSlot); MJ_DEBUG_PROC_NODE(outerTupleSlot);
mergestate->mj_MatchedOuter = false; node->mj_MatchedOuter = false;
if (TupIsNull(outerTupleSlot)) if (TupIsNull(outerTupleSlot))
{ {
...@@ -1377,7 +1375,7 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1377,7 +1375,7 @@ ExecMergeJoin(MergeJoin *node)
*/ */
default: default:
elog(WARNING, "ExecMergeJoin: invalid join state %d, aborting", elog(WARNING, "ExecMergeJoin: invalid join state %d, aborting",
mergestate->mj_JoinState); node->mj_JoinState);
return NULL; return NULL;
} }
} }
...@@ -1385,14 +1383,10 @@ ExecMergeJoin(MergeJoin *node) ...@@ -1385,14 +1383,10 @@ ExecMergeJoin(MergeJoin *node)
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecInitMergeJoin * ExecInitMergeJoin
*
* old comments
* Creates the run-time state information for the node and
* sets the relation id to contain relevant decriptors.
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
bool MergeJoinState *
ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent) ExecInitMergeJoin(MergeJoin *node, EState *estate)
{ {
MergeJoinState *mergestate; MergeJoinState *mergestate;
...@@ -1400,40 +1394,52 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent) ...@@ -1400,40 +1394,52 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
"initializing node"); "initializing node");
/* /*
* assign the node's execution state and get the range table and * create state structure
* direction from it
*/
node->join.plan.state = estate;
/*
* create new merge state for node
*/ */
mergestate = makeNode(MergeJoinState); mergestate = makeNode(MergeJoinState);
node->mergestate = mergestate; mergestate->js.ps.plan = (Plan *) node;
mergestate->js.ps.state = estate;
/* /*
* Miscellaneous initialization * Miscellaneous initialization
* *
* create expression context for node * create expression context for node
*/ */
ExecAssignExprContext(estate, &mergestate->jstate); ExecAssignExprContext(estate, &mergestate->js.ps);
/* /*
* initialize subplans * initialize child expressions
*/ */
ExecInitNode(outerPlan((Plan *) node), estate, (Plan *) node); mergestate->js.ps.targetlist = (List *)
ExecInitNode(innerPlan((Plan *) node), estate, (Plan *) node); ExecInitExpr((Node *) node->join.plan.targetlist,
(PlanState *) mergestate);
mergestate->js.ps.qual = (List *)
ExecInitExpr((Node *) node->join.plan.qual,
(PlanState *) mergestate);
mergestate->js.jointype = node->join.jointype;
mergestate->js.joinqual = (List *)
ExecInitExpr((Node *) node->join.joinqual,
(PlanState *) mergestate);
mergestate->mergeclauses = (List *)
ExecInitExpr((Node *) node->mergeclauses,
(PlanState *) mergestate);
/*
* initialize child nodes
*/
outerPlanState(mergestate) = ExecInitNode(outerPlan(node), estate);
innerPlanState(mergestate) = ExecInitNode(innerPlan(node), estate);
#define MERGEJOIN_NSLOTS 4 #define MERGEJOIN_NSLOTS 4
/* /*
* tuple table initialization * tuple table initialization
*/ */
ExecInitResultTupleSlot(estate, &mergestate->jstate); ExecInitResultTupleSlot(estate, &mergestate->js.ps);
mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate); mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate);
ExecSetSlotDescriptor(mergestate->mj_MarkedTupleSlot, ExecSetSlotDescriptor(mergestate->mj_MarkedTupleSlot,
ExecGetTupType(innerPlan((Plan *) node)), ExecGetTupType(innerPlanState(mergestate)),
false); false);
switch (node->join.jointype) switch (node->join.jointype)
...@@ -1443,12 +1449,12 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent) ...@@ -1443,12 +1449,12 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
case JOIN_LEFT: case JOIN_LEFT:
mergestate->mj_NullInnerTupleSlot = mergestate->mj_NullInnerTupleSlot =
ExecInitNullTupleSlot(estate, ExecInitNullTupleSlot(estate,
ExecGetTupType(innerPlan((Plan *) node))); ExecGetTupType(innerPlanState(mergestate)));
break; break;
case JOIN_RIGHT: case JOIN_RIGHT:
mergestate->mj_NullOuterTupleSlot = mergestate->mj_NullOuterTupleSlot =
ExecInitNullTupleSlot(estate, ExecInitNullTupleSlot(estate,
ExecGetTupType(outerPlan((Plan *) node))); ExecGetTupType(outerPlanState(mergestate)));
/* /*
* Can't handle right or full join with non-nil extra * Can't handle right or full join with non-nil extra
...@@ -1460,10 +1466,10 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent) ...@@ -1460,10 +1466,10 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
case JOIN_FULL: case JOIN_FULL:
mergestate->mj_NullOuterTupleSlot = mergestate->mj_NullOuterTupleSlot =
ExecInitNullTupleSlot(estate, ExecInitNullTupleSlot(estate,
ExecGetTupType(outerPlan((Plan *) node))); ExecGetTupType(outerPlanState(mergestate)));
mergestate->mj_NullInnerTupleSlot = mergestate->mj_NullInnerTupleSlot =
ExecInitNullTupleSlot(estate, ExecInitNullTupleSlot(estate,
ExecGetTupType(innerPlan((Plan *) node))); ExecGetTupType(innerPlanState(mergestate)));
/* /*
* Can't handle right or full join with non-nil extra * Can't handle right or full join with non-nil extra
...@@ -1480,8 +1486,8 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent) ...@@ -1480,8 +1486,8 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
/* /*
* initialize tuple type and projection info * initialize tuple type and projection info
*/ */
ExecAssignResultTypeFromTL((Plan *) node, &mergestate->jstate); ExecAssignResultTypeFromTL(&mergestate->js.ps);
ExecAssignProjectionInfo((Plan *) node, &mergestate->jstate); ExecAssignProjectionInfo(&mergestate->js.ps);
/* /*
* form merge skip qualifications * form merge skip qualifications
...@@ -1500,7 +1506,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent) ...@@ -1500,7 +1506,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
* initialize join state * initialize join state
*/ */
mergestate->mj_JoinState = EXEC_MJ_INITIALIZE; mergestate->mj_JoinState = EXEC_MJ_INITIALIZE;
mergestate->jstate.cs_TupFromTlist = false; mergestate->js.ps.ps_TupFromTlist = false;
mergestate->mj_MatchedOuter = false; mergestate->mj_MatchedOuter = false;
mergestate->mj_MatchedInner = false; mergestate->mj_MatchedInner = false;
mergestate->mj_OuterTupleSlot = NULL; mergestate->mj_OuterTupleSlot = NULL;
...@@ -1512,7 +1518,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent) ...@@ -1512,7 +1518,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent)
MJ1_printf("ExecInitMergeJoin: %s\n", MJ1_printf("ExecInitMergeJoin: %s\n",
"node initialized"); "node initialized");
return TRUE; return mergestate;
} }
int int
...@@ -1531,65 +1537,52 @@ ExecCountSlotsMergeJoin(MergeJoin *node) ...@@ -1531,65 +1537,52 @@ ExecCountSlotsMergeJoin(MergeJoin *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecEndMergeJoin(MergeJoin *node) ExecEndMergeJoin(MergeJoinState *node)
{ {
MergeJoinState *mergestate;
MJ1_printf("ExecEndMergeJoin: %s\n", MJ1_printf("ExecEndMergeJoin: %s\n",
"ending node processing"); "ending node processing");
/*
* get state information from the node
*/
mergestate = node->mergestate;
/* /*
* Free the projection info and the scan attribute info * Free the projection info and the scan attribute info
*
* Note: we don't ExecFreeResultType(mergestate) because the rule manager
* depends on the tupType returned by ExecMain(). So for now, this is
* freed at end-transaction time. -cim 6/2/91
*/ */
ExecFreeProjectionInfo(&mergestate->jstate); ExecFreeProjectionInfo(&node->js.ps);
ExecFreeExprContext(&mergestate->jstate); ExecFreeExprContext(&node->js.ps);
/* /*
* shut down the subplans * shut down the subplans
*/ */
ExecEndNode((Plan *) innerPlan((Plan *) node), (Plan *) node); ExecEndNode(innerPlanState(node));
ExecEndNode((Plan *) outerPlan((Plan *) node), (Plan *) node); ExecEndNode(outerPlanState(node));
/* /*
* clean out the tuple table * clean out the tuple table
*/ */
ExecClearTuple(mergestate->jstate.cs_ResultTupleSlot); ExecClearTuple(node->js.ps.ps_ResultTupleSlot);
ExecClearTuple(mergestate->mj_MarkedTupleSlot); ExecClearTuple(node->mj_MarkedTupleSlot);
MJ1_printf("ExecEndMergeJoin: %s\n", MJ1_printf("ExecEndMergeJoin: %s\n",
"node processing ended"); "node processing ended");
} }
void void
ExecReScanMergeJoin(MergeJoin *node, ExprContext *exprCtxt, Plan *parent) ExecReScanMergeJoin(MergeJoinState *node, ExprContext *exprCtxt)
{ {
MergeJoinState *mergestate = node->mergestate; ExecClearTuple(node->mj_MarkedTupleSlot);
ExecClearTuple(mergestate->mj_MarkedTupleSlot);
mergestate->mj_JoinState = EXEC_MJ_INITIALIZE; node->mj_JoinState = EXEC_MJ_INITIALIZE;
mergestate->jstate.cs_TupFromTlist = false; node->js.ps.ps_TupFromTlist = false;
mergestate->mj_MatchedOuter = false; node->mj_MatchedOuter = false;
mergestate->mj_MatchedInner = false; node->mj_MatchedInner = false;
mergestate->mj_OuterTupleSlot = NULL; node->mj_OuterTupleSlot = NULL;
mergestate->mj_InnerTupleSlot = NULL; node->mj_InnerTupleSlot = NULL;
/* /*
* if chgParam of subnodes is not null then plans will be re-scanned * if chgParam of subnodes is not null then plans will be re-scanned
* by first ExecProcNode. * by 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);
if (((Plan *) node)->righttree->chgParam == NULL) if (((PlanState *) node)->righttree->chgParam == NULL)
ExecReScan(((Plan *) node)->righttree, exprCtxt, (Plan *) node); ExecReScan(((PlanState *) node)->righttree, exprCtxt);
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeNestloop.c,v 1.26 2002/06/20 20:29:28 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeNestloop.c,v 1.27 2002/12/05 15:50:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -57,11 +57,10 @@ ...@@ -57,11 +57,10 @@
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
TupleTableSlot * TupleTableSlot *
ExecNestLoop(NestLoop *node) ExecNestLoop(NestLoopState *node)
{ {
NestLoopState *nlstate; PlanState *innerPlan;
Plan *innerPlan; PlanState *outerPlan;
Plan *outerPlan;
TupleTableSlot *outerTupleSlot; TupleTableSlot *outerTupleSlot;
TupleTableSlot *innerTupleSlot; TupleTableSlot *innerTupleSlot;
List *joinqual; List *joinqual;
...@@ -73,17 +72,16 @@ ExecNestLoop(NestLoop *node) ...@@ -73,17 +72,16 @@ ExecNestLoop(NestLoop *node)
*/ */
ENL1_printf("getting info from node"); ENL1_printf("getting info from node");
nlstate = node->nlstate; joinqual = node->js.joinqual;
joinqual = node->join.joinqual; otherqual = node->js.ps.qual;
otherqual = node->join.plan.qual; outerPlan = outerPlanState(node);
outerPlan = outerPlan((Plan *) node); innerPlan = innerPlanState(node);
innerPlan = innerPlan((Plan *) node); econtext = node->js.ps.ps_ExprContext;
econtext = nlstate->jstate.cs_ExprContext;
/* /*
* get the current outer tuple * get the current outer tuple
*/ */
outerTupleSlot = nlstate->jstate.cs_OuterTupleSlot; outerTupleSlot = node->js.ps.ps_OuterTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot; econtext->ecxt_outertuple = outerTupleSlot;
/* /*
...@@ -91,16 +89,16 @@ ExecNestLoop(NestLoop *node) ...@@ -91,16 +89,16 @@ ExecNestLoop(NestLoop *node)
* join tuple (because there is a function-returning-set in the * join 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 (nlstate->jstate.cs_TupFromTlist) if (node->js.ps.ps_TupFromTlist)
{ {
TupleTableSlot *result; TupleTableSlot *result;
ExprDoneCond isDone; ExprDoneCond isDone;
result = ExecProject(nlstate->jstate.cs_ProjInfo, &isDone); result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
if (isDone == ExprMultipleResult) if (isDone == ExprMultipleResult)
return result; return result;
/* Done with that source tuple... */ /* Done with that source tuple... */
nlstate->jstate.cs_TupFromTlist = false; node->js.ps.ps_TupFromTlist = false;
} }
/* /*
...@@ -122,10 +120,10 @@ ExecNestLoop(NestLoop *node) ...@@ -122,10 +120,10 @@ ExecNestLoop(NestLoop *node)
* If we don't have an outer tuple, get the next one and reset the * If we don't have an outer tuple, get the next one and reset the
* inner scan. * inner scan.
*/ */
if (nlstate->nl_NeedNewOuter) if (node->nl_NeedNewOuter)
{ {
ENL1_printf("getting new outer tuple"); ENL1_printf("getting new outer tuple");
outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node); outerTupleSlot = ExecProcNode(outerPlan);
/* /*
* if there are no more outer tuples, then the join is * if there are no more outer tuples, then the join is
...@@ -138,10 +136,10 @@ ExecNestLoop(NestLoop *node) ...@@ -138,10 +136,10 @@ ExecNestLoop(NestLoop *node)
} }
ENL1_printf("saving new outer tuple information"); ENL1_printf("saving new outer tuple information");
nlstate->jstate.cs_OuterTupleSlot = outerTupleSlot; node->js.ps.ps_OuterTupleSlot = outerTupleSlot;
econtext->ecxt_outertuple = outerTupleSlot; econtext->ecxt_outertuple = outerTupleSlot;
nlstate->nl_NeedNewOuter = false; node->nl_NeedNewOuter = false;
nlstate->nl_MatchedOuter = false; node->nl_MatchedOuter = false;
/* /*
* now rescan the inner plan * now rescan the inner plan
...@@ -153,7 +151,7 @@ ExecNestLoop(NestLoop *node) ...@@ -153,7 +151,7 @@ ExecNestLoop(NestLoop *node)
* outer tuple (e.g. in index scans), that's why we pass our * outer tuple (e.g. in index scans), that's why we pass our
* expr context. * expr context.
*/ */
ExecReScan(innerPlan, econtext, (Plan *) node); ExecReScan(innerPlan, econtext);
} }
/* /*
...@@ -161,17 +159,17 @@ ExecNestLoop(NestLoop *node) ...@@ -161,17 +159,17 @@ ExecNestLoop(NestLoop *node)
*/ */
ENL1_printf("getting new inner tuple"); ENL1_printf("getting new inner tuple");
innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node); innerTupleSlot = ExecProcNode(innerPlan);
econtext->ecxt_innertuple = innerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot;
if (TupIsNull(innerTupleSlot)) if (TupIsNull(innerTupleSlot))
{ {
ENL1_printf("no inner tuple, need new outer tuple"); ENL1_printf("no inner tuple, need new outer tuple");
nlstate->nl_NeedNewOuter = true; node->nl_NeedNewOuter = true;
if (!nlstate->nl_MatchedOuter && if (!node->nl_MatchedOuter &&
node->join.jointype == JOIN_LEFT) node->js.jointype == JOIN_LEFT)
{ {
/* /*
* We are doing an outer join and there were no join * We are doing an outer join and there were no join
...@@ -179,7 +177,7 @@ ExecNestLoop(NestLoop *node) ...@@ -179,7 +177,7 @@ ExecNestLoop(NestLoop *node)
* tuple with nulls for the inner tuple, and return it if * tuple with nulls for the inner tuple, and return it if
* it passes the non-join quals. * it passes the non-join quals.
*/ */
econtext->ecxt_innertuple = nlstate->nl_NullInnerTupleSlot; econtext->ecxt_innertuple = node->nl_NullInnerTupleSlot;
ENL1_printf("testing qualification for outer-join tuple"); ENL1_printf("testing qualification for outer-join tuple");
...@@ -195,11 +193,11 @@ ExecNestLoop(NestLoop *node) ...@@ -195,11 +193,11 @@ ExecNestLoop(NestLoop *node)
ENL1_printf("qualification succeeded, projecting tuple"); ENL1_printf("qualification succeeded, projecting tuple");
result = ExecProject(nlstate->jstate.cs_ProjInfo, &isDone); result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
if (isDone != ExprEndResult) if (isDone != ExprEndResult)
{ {
nlstate->jstate.cs_TupFromTlist = node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult); (isDone == ExprMultipleResult);
return result; return result;
} }
...@@ -224,7 +222,7 @@ ExecNestLoop(NestLoop *node) ...@@ -224,7 +222,7 @@ ExecNestLoop(NestLoop *node)
if (ExecQual(joinqual, econtext, false)) if (ExecQual(joinqual, econtext, false))
{ {
nlstate->nl_MatchedOuter = true; node->nl_MatchedOuter = true;
if (otherqual == NIL || ExecQual(otherqual, econtext, false)) if (otherqual == NIL || ExecQual(otherqual, econtext, false))
{ {
...@@ -238,11 +236,11 @@ ExecNestLoop(NestLoop *node) ...@@ -238,11 +236,11 @@ ExecNestLoop(NestLoop *node)
ENL1_printf("qualification succeeded, projecting tuple"); ENL1_printf("qualification succeeded, projecting tuple");
result = ExecProject(nlstate->jstate.cs_ProjInfo, &isDone); result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
if (isDone != ExprEndResult) if (isDone != ExprEndResult)
{ {
nlstate->jstate.cs_TupFromTlist = node->js.ps.ps_TupFromTlist =
(isDone == ExprMultipleResult); (isDone == ExprMultipleResult);
return result; return result;
} }
...@@ -260,14 +258,10 @@ ExecNestLoop(NestLoop *node) ...@@ -260,14 +258,10 @@ ExecNestLoop(NestLoop *node)
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecInitNestLoop * ExecInitNestLoop
*
* Creates the run-time state information for the nestloop node
* produced by the planner and initailizes inner and outer relations
* (child nodes).
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
bool NestLoopState *
ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent) ExecInitNestLoop(NestLoop *node, EState *estate)
{ {
NestLoopState *nlstate; NestLoopState *nlstate;
...@@ -275,35 +269,45 @@ ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent) ...@@ -275,35 +269,45 @@ ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent)
"initializing node"); "initializing node");
/* /*
* assign execution state to node * create state structure
*/
node->join.plan.state = estate;
/*
* create new nest loop state
*/ */
nlstate = makeNode(NestLoopState); nlstate = makeNode(NestLoopState);
node->nlstate = nlstate; nlstate->js.ps.plan = (Plan *) node;
nlstate->js.ps.state = estate;
/* /*
* Miscellaneous initialization * Miscellaneous initialization
* *
* create expression context for node * create expression context for node
*/ */
ExecAssignExprContext(estate, &nlstate->jstate); ExecAssignExprContext(estate, &nlstate->js.ps);
/*
* initialize child expressions
*/
nlstate->js.ps.targetlist = (List *)
ExecInitExpr((Node *) node->join.plan.targetlist,
(PlanState *) nlstate);
nlstate->js.ps.qual = (List *)
ExecInitExpr((Node *) node->join.plan.qual,
(PlanState *) nlstate);
nlstate->js.jointype = node->join.jointype;
nlstate->js.joinqual = (List *)
ExecInitExpr((Node *) node->join.joinqual,
(PlanState *) nlstate);
/* /*
* now initialize children * initialize child nodes
*/ */
ExecInitNode(outerPlan((Plan *) node), estate, (Plan *) node); outerPlanState(nlstate) = ExecInitNode(outerPlan(node), estate);
ExecInitNode(innerPlan((Plan *) node), estate, (Plan *) node); innerPlanState(nlstate) = ExecInitNode(innerPlan(node), estate);
#define NESTLOOP_NSLOTS 2 #define NESTLOOP_NSLOTS 2
/* /*
* tuple table initialization * tuple table initialization
*/ */
ExecInitResultTupleSlot(estate, &nlstate->jstate); ExecInitResultTupleSlot(estate, &nlstate->js.ps);
switch (node->join.jointype) switch (node->join.jointype)
{ {
...@@ -312,7 +316,7 @@ ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent) ...@@ -312,7 +316,7 @@ ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent)
case JOIN_LEFT: case JOIN_LEFT:
nlstate->nl_NullInnerTupleSlot = nlstate->nl_NullInnerTupleSlot =
ExecInitNullTupleSlot(estate, ExecInitNullTupleSlot(estate,
ExecGetTupType(innerPlan((Plan *) node))); ExecGetTupType(innerPlanState(nlstate)));
break; break;
default: default:
elog(ERROR, "ExecInitNestLoop: unsupported join type %d", elog(ERROR, "ExecInitNestLoop: unsupported join type %d",
...@@ -322,20 +326,21 @@ ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent) ...@@ -322,20 +326,21 @@ ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent)
/* /*
* initialize tuple type and projection info * initialize tuple type and projection info
*/ */
ExecAssignResultTypeFromTL((Plan *) node, &nlstate->jstate); ExecAssignResultTypeFromTL(&nlstate->js.ps);
ExecAssignProjectionInfo((Plan *) node, &nlstate->jstate); ExecAssignProjectionInfo(&nlstate->js.ps);
/* /*
* finally, wipe the current outer tuple clean. * finally, wipe the current outer tuple clean.
*/ */
nlstate->jstate.cs_OuterTupleSlot = NULL; nlstate->js.ps.ps_OuterTupleSlot = NULL;
nlstate->jstate.cs_TupFromTlist = false; nlstate->js.ps.ps_TupFromTlist = false;
nlstate->nl_NeedNewOuter = true; nlstate->nl_NeedNewOuter = true;
nlstate->nl_MatchedOuter = false; nlstate->nl_MatchedOuter = false;
NL1_printf("ExecInitNestLoop: %s\n", NL1_printf("ExecInitNestLoop: %s\n",
"node initialized"); "node initialized");
return TRUE;
return nlstate;
} }
int int
...@@ -353,38 +358,27 @@ ExecCountSlotsNestLoop(NestLoop *node) ...@@ -353,38 +358,27 @@ ExecCountSlotsNestLoop(NestLoop *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecEndNestLoop(NestLoop *node) ExecEndNestLoop(NestLoopState *node)
{ {
NestLoopState *nlstate;
NL1_printf("ExecEndNestLoop: %s\n", NL1_printf("ExecEndNestLoop: %s\n",
"ending node processing"); "ending node processing");
/*
* get info from the node
*/
nlstate = node->nlstate;
/* /*
* Free the projection info * Free the projection info
*
* Note: we don't ExecFreeResultType(nlstate) because the rule manager
* depends on the tupType returned by ExecMain(). So for now, this is
* freed at end-transaction time. -cim 6/2/91
*/ */
ExecFreeProjectionInfo(&nlstate->jstate); ExecFreeProjectionInfo(&node->js.ps);
ExecFreeExprContext(&nlstate->jstate); ExecFreeExprContext(&node->js.ps);
/* /*
* close down subplans * close down subplans
*/ */
ExecEndNode(outerPlan((Plan *) node), (Plan *) node); ExecEndNode(outerPlanState(node));
ExecEndNode(innerPlan((Plan *) node), (Plan *) node); ExecEndNode(innerPlanState(node));
/* /*
* clean out the tuple table * clean out the tuple table
*/ */
ExecClearTuple(nlstate->jstate.cs_ResultTupleSlot); ExecClearTuple(node->js.ps.ps_ResultTupleSlot);
NL1_printf("ExecEndNestLoop: %s\n", NL1_printf("ExecEndNestLoop: %s\n",
"node processing ended"); "node processing ended");
...@@ -395,10 +389,9 @@ ExecEndNestLoop(NestLoop *node) ...@@ -395,10 +389,9 @@ ExecEndNestLoop(NestLoop *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecReScanNestLoop(NestLoop *node, ExprContext *exprCtxt, Plan *parent) ExecReScanNestLoop(NestLoopState *node, ExprContext *exprCtxt)
{ {
NestLoopState *nlstate = node->nlstate; PlanState *outerPlan = outerPlanState(node);
Plan *outerPlan = outerPlan((Plan *) node);
/* /*
* If outerPlan->chgParam is not null then plan will be automatically * If outerPlan->chgParam is not null then plan will be automatically
...@@ -408,11 +401,11 @@ ExecReScanNestLoop(NestLoop *node, ExprContext *exprCtxt, Plan *parent) ...@@ -408,11 +401,11 @@ ExecReScanNestLoop(NestLoop *node, ExprContext *exprCtxt, Plan *parent)
* run-time keys... * run-time keys...
*/ */
if (outerPlan->chgParam == NULL) if (outerPlan->chgParam == NULL)
ExecReScan(outerPlan, exprCtxt, (Plan *) node); ExecReScan(outerPlan, exprCtxt);
/* let outerPlan to free its result tuple ... */ /* let outerPlan to free its result tuple ... */
nlstate->jstate.cs_OuterTupleSlot = NULL; node->js.ps.ps_OuterTupleSlot = NULL;
nlstate->jstate.cs_TupFromTlist = false; node->js.ps.ps_TupFromTlist = false;
nlstate->nl_NeedNewOuter = true; node->nl_NeedNewOuter = true;
nlstate->nl_MatchedOuter = false; node->nl_MatchedOuter = false;
} }
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeResult.c,v 1.21 2002/06/20 20:29:28 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeResult.c,v 1.22 2002/12/05 15:50:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -60,34 +60,29 @@ ...@@ -60,34 +60,29 @@
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
TupleTableSlot * TupleTableSlot *
ExecResult(Result *node) ExecResult(ResultState *node)
{ {
ResultState *resstate;
TupleTableSlot *outerTupleSlot; TupleTableSlot *outerTupleSlot;
TupleTableSlot *resultSlot; TupleTableSlot *resultSlot;
Plan *outerPlan; PlanState *outerPlan;
ExprContext *econtext; ExprContext *econtext;
ExprDoneCond isDone; ExprDoneCond isDone;
/* econtext = node->ps.ps_ExprContext;
* initialize the result node's state
*/
resstate = node->resstate;
econtext = resstate->cstate.cs_ExprContext;
/* /*
* check constant qualifications like (2 > 1), if not already done * check constant qualifications like (2 > 1), if not already done
*/ */
if (resstate->rs_checkqual) if (node->rs_checkqual)
{ {
bool qualResult = ExecQual((List *) node->resconstantqual, bool qualResult = ExecQual((List *) node->resconstantqual,
econtext, econtext,
false); false);
resstate->rs_checkqual = false; node->rs_checkqual = false;
if (qualResult == false) if (!qualResult)
{ {
resstate->rs_done = true; node->rs_done = true;
return NULL; return NULL;
} }
} }
...@@ -97,13 +92,13 @@ ExecResult(Result *node) ...@@ -97,13 +92,13 @@ ExecResult(Result *node)
* 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 (resstate->cstate.cs_TupFromTlist) if (node->ps.ps_TupFromTlist)
{ {
resultSlot = ExecProject(resstate->cstate.cs_ProjInfo, &isDone); resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
if (isDone == ExprMultipleResult) if (isDone == ExprMultipleResult)
return resultSlot; return resultSlot;
/* Done with that source tuple... */ /* Done with that source tuple... */
resstate->cstate.cs_TupFromTlist = false; node->ps.ps_TupFromTlist = false;
} }
/* /*
...@@ -119,9 +114,9 @@ ExecResult(Result *node) ...@@ -119,9 +114,9 @@ ExecResult(Result *node)
* called, OR that we failed the constant qual check. Either way, now * called, OR that we failed the constant qual check. Either way, now
* we are through. * we are through.
*/ */
while (!resstate->rs_done) while (!node->rs_done)
{ {
outerPlan = outerPlan(node); outerPlan = outerPlanState(node);
if (outerPlan != NULL) if (outerPlan != NULL)
{ {
...@@ -129,12 +124,12 @@ ExecResult(Result *node) ...@@ -129,12 +124,12 @@ ExecResult(Result *node)
* retrieve tuples from the outer plan until there are no * retrieve tuples from the outer plan until there are no
* more. * more.
*/ */
outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node); outerTupleSlot = ExecProcNode(outerPlan);
if (TupIsNull(outerTupleSlot)) if (TupIsNull(outerTupleSlot))
return NULL; return NULL;
resstate->cstate.cs_OuterTupleSlot = outerTupleSlot; node->ps.ps_OuterTupleSlot = outerTupleSlot;
/* /*
* XXX gross hack. use outer tuple as scan tuple for * XXX gross hack. use outer tuple as scan tuple for
...@@ -149,7 +144,7 @@ ExecResult(Result *node) ...@@ -149,7 +144,7 @@ ExecResult(Result *node)
* if we don't have an outer plan, then we are just generating * if we don't have an outer plan, then we are just generating
* the results from a constant target list. Do it only once. * the results from a constant target list. Do it only once.
*/ */
resstate->rs_done = true; node->rs_done = true;
} }
/* /*
...@@ -157,11 +152,11 @@ ExecResult(Result *node) ...@@ -157,11 +152,11 @@ ExecResult(Result *node)
* unless the projection produces an empty set, in which case we * unless the projection produces an empty set, in which case we
* must loop back to see if there are more outerPlan tuples. * must loop back to see if there are more outerPlan tuples.
*/ */
resultSlot = ExecProject(resstate->cstate.cs_ProjInfo, &isDone); resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
if (isDone != ExprEndResult) if (isDone != ExprEndResult)
{ {
resstate->cstate.cs_TupFromTlist = (isDone == ExprMultipleResult); node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
return resultSlot; return resultSlot;
} }
} }
...@@ -177,42 +172,51 @@ ExecResult(Result *node) ...@@ -177,42 +172,51 @@ ExecResult(Result *node)
* (child nodes). * (child nodes).
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
bool ResultState *
ExecInitResult(Result *node, EState *estate, Plan *parent) ExecInitResult(Result *node, EState *estate)
{ {
ResultState *resstate; ResultState *resstate;
/* /*
* assign execution state to node * create state structure
*/
node->plan.state = estate;
/*
* create new ResultState for node
*/ */
resstate = makeNode(ResultState); resstate = makeNode(ResultState);
resstate->ps.plan = (Plan *) node;
resstate->ps.state = estate;
resstate->rs_done = false; resstate->rs_done = false;
resstate->rs_checkqual = (node->resconstantqual == NULL) ? false : true; resstate->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
node->resstate = resstate;
/* /*
* Miscellaneous initialization * Miscellaneous initialization
* *
* create expression context for node * create expression context for node
*/ */
ExecAssignExprContext(estate, &resstate->cstate); ExecAssignExprContext(estate, &resstate->ps);
#define RESULT_NSLOTS 1 #define RESULT_NSLOTS 1
/* /*
* tuple table initialization * tuple table initialization
*/ */
ExecInitResultTupleSlot(estate, &resstate->cstate); ExecInitResultTupleSlot(estate, &resstate->ps);
/* /*
* then initialize children * initialize child expressions
*/ */
ExecInitNode(outerPlan(node), estate, (Plan *) node); resstate->ps.targetlist = (List *)
ExecInitExpr((Node *) node->plan.targetlist,
(PlanState *) resstate);
resstate->ps.qual = (List *)
ExecInitExpr((Node *) node->plan.qual,
(PlanState *) resstate);
resstate->resconstantqual = ExecInitExpr(node->resconstantqual,
(PlanState *) resstate);
/*
* initialize child nodes
*/
outerPlanState(resstate) = ExecInitNode(outerPlan(node), estate);
/* /*
* we don't use inner plan * we don't use inner plan
...@@ -222,10 +226,10 @@ ExecInitResult(Result *node, EState *estate, Plan *parent) ...@@ -222,10 +226,10 @@ ExecInitResult(Result *node, EState *estate, Plan *parent)
/* /*
* initialize tuple type and projection info * initialize tuple type and projection info
*/ */
ExecAssignResultTypeFromTL((Plan *) node, &resstate->cstate); ExecAssignResultTypeFromTL(&resstate->ps);
ExecAssignProjectionInfo((Plan *) node, &resstate->cstate); ExecAssignProjectionInfo(&resstate->ps);
return TRUE; return resstate;
} }
int int
...@@ -241,49 +245,37 @@ ExecCountSlotsResult(Result *node) ...@@ -241,49 +245,37 @@ ExecCountSlotsResult(Result *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecEndResult(Result *node) ExecEndResult(ResultState *node)
{ {
ResultState *resstate;
resstate = node->resstate;
/* /*
* Free the projection info * Free the projection info
*
* Note: we don't ExecFreeResultType(resstate) because the rule manager
* depends on the tupType returned by ExecMain(). So for now, this is
* freed at end-transaction time. -cim 6/2/91
*/ */
ExecFreeProjectionInfo(&resstate->cstate); ExecFreeProjectionInfo(&node->ps);
ExecFreeExprContext(&resstate->cstate); ExecFreeExprContext(&node->ps);
/* /*
* shut down subplans * clean out the tuple table
*/ */
ExecEndNode(outerPlan(node), (Plan *) node); ExecClearTuple(node->ps.ps_ResultTupleSlot);
/* /*
* clean out the tuple table * shut down subplans
*/ */
ExecClearTuple(resstate->cstate.cs_ResultTupleSlot); ExecEndNode(outerPlanState(node));
pfree(resstate);
node->resstate = NULL; /* XXX - new for us - er1p */
} }
void void
ExecReScanResult(Result *node, ExprContext *exprCtxt, Plan *parent) ExecReScanResult(ResultState *node, ExprContext *exprCtxt)
{ {
ResultState *resstate = node->resstate; node->rs_done = false;
node->ps.ps_TupFromTlist = false;
resstate->rs_done = false; node->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
resstate->cstate.cs_TupFromTlist = false;
resstate->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
/* /*
* 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 && 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/nodeSeqscan.c,v 1.38 2002/11/30 05:21:01 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.39 2002/12/05 15:50:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -29,9 +29,8 @@ ...@@ -29,9 +29,8 @@
#include "executor/nodeSeqscan.h" #include "executor/nodeSeqscan.h"
#include "parser/parsetree.h" #include "parser/parsetree.h"
static Oid InitScanRelation(SeqScan *node, EState *estate, static void InitScanRelation(SeqScanState *node, EState *estate);
CommonScanState *scanstate); static TupleTableSlot *SeqNext(SeqScanState *node);
static TupleTableSlot *SeqNext(SeqScan *node);
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* Scan Support * Scan Support
...@@ -44,11 +43,11 @@ static TupleTableSlot *SeqNext(SeqScan *node); ...@@ -44,11 +43,11 @@ static TupleTableSlot *SeqNext(SeqScan *node);
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static TupleTableSlot * static TupleTableSlot *
SeqNext(SeqScan *node) SeqNext(SeqScanState *node)
{ {
HeapTuple tuple; HeapTuple tuple;
HeapScanDesc scandesc; HeapScanDesc scandesc;
CommonScanState *scanstate; Index scanrelid;
EState *estate; EState *estate;
ScanDirection direction; ScanDirection direction;
TupleTableSlot *slot; TupleTableSlot *slot;
...@@ -56,11 +55,11 @@ SeqNext(SeqScan *node) ...@@ -56,11 +55,11 @@ SeqNext(SeqScan *node)
/* /*
* get information from the estate and scan state * get information from the estate and scan state
*/ */
estate = node->plan.state; estate = node->ps.state;
scanstate = node->scanstate; scandesc = node->ss_currentScanDesc;
scandesc = scanstate->css_currentScanDesc; scanrelid = ((SeqScan *) node->ps.plan)->scanrelid;
direction = estate->es_direction; direction = estate->es_direction;
slot = scanstate->css_ScanTupleSlot; slot = node->ss_ScanTupleSlot;
/* /*
* Check if we are evaluating PlanQual for tuple of this relation. * Check if we are evaluating PlanQual for tuple of this relation.
...@@ -69,13 +68,13 @@ SeqNext(SeqScan *node) ...@@ -69,13 +68,13 @@ SeqNext(SeqScan *node)
* switching in Init/ReScan plan... * switching in Init/ReScan plan...
*/ */
if (estate->es_evTuple != NULL && if (estate->es_evTuple != NULL &&
estate->es_evTuple[node->scanrelid - 1] != NULL) estate->es_evTuple[scanrelid - 1] != NULL)
{ {
ExecClearTuple(slot); ExecClearTuple(slot);
if (estate->es_evTupleNull[node->scanrelid - 1]) if (estate->es_evTupleNull[scanrelid - 1])
return slot; /* return empty slot */ return slot; /* return empty slot */
ExecStoreTuple(estate->es_evTuple[node->scanrelid - 1], ExecStoreTuple(estate->es_evTuple[scanrelid - 1],
slot, InvalidBuffer, false); slot, InvalidBuffer, false);
/* /*
...@@ -85,7 +84,7 @@ SeqNext(SeqScan *node) ...@@ -85,7 +84,7 @@ SeqNext(SeqScan *node)
*/ */
/* Flag for the next call that no more tuples */ /* Flag for the next call that no more tuples */
estate->es_evTupleNull[node->scanrelid - 1] = true; estate->es_evTupleNull[scanrelid - 1] = true;
return (slot); return (slot);
} }
...@@ -124,12 +123,12 @@ SeqNext(SeqScan *node) ...@@ -124,12 +123,12 @@ SeqNext(SeqScan *node)
*/ */
TupleTableSlot * TupleTableSlot *
ExecSeqScan(SeqScan *node) ExecSeqScan(SeqScanState *node)
{ {
/* /*
* use SeqNext as access method * use SeqNext as access method
*/ */
return ExecScan(node, (ExecScanAccessMtd) SeqNext); return ExecScan((ScanState *) node, (ExecScanAccessMtd) SeqNext);
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -139,9 +138,8 @@ ExecSeqScan(SeqScan *node) ...@@ -139,9 +138,8 @@ ExecSeqScan(SeqScan *node)
* subplans of scans. * subplans of scans.
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static Oid static void
InitScanRelation(SeqScan *node, EState *estate, InitScanRelation(SeqScanState *node, EState *estate)
CommonScanState *scanstate)
{ {
Index relid; Index relid;
List *rangeTable; List *rangeTable;
...@@ -156,7 +154,7 @@ InitScanRelation(SeqScan *node, EState *estate, ...@@ -156,7 +154,7 @@ InitScanRelation(SeqScan *node, EState *estate,
* *
* We acquire AccessShareLock for the duration of the scan. * We acquire AccessShareLock for the duration of the scan.
*/ */
relid = node->scanrelid; relid = ((SeqScan *) node->ps.plan)->scanrelid;
rangeTable = estate->es_range_table; rangeTable = estate->es_range_table;
rtentry = rt_fetch(relid, rangeTable); rtentry = rt_fetch(relid, rangeTable);
reloid = rtentry->relid; reloid = rtentry->relid;
...@@ -168,12 +166,10 @@ InitScanRelation(SeqScan *node, EState *estate, ...@@ -168,12 +166,10 @@ InitScanRelation(SeqScan *node, EState *estate,
0, 0,
NULL); NULL);
scanstate->css_currentRelation = currentRelation; node->ss_currentRelation = currentRelation;
scanstate->css_currentScanDesc = currentScanDesc; node->ss_currentScanDesc = currentScanDesc;
ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false); ExecAssignScanType(node, RelationGetDescr(currentRelation), false);
return reloid;
} }
...@@ -181,59 +177,64 @@ InitScanRelation(SeqScan *node, EState *estate, ...@@ -181,59 +177,64 @@ InitScanRelation(SeqScan *node, EState *estate,
* ExecInitSeqScan * ExecInitSeqScan
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
bool SeqScanState *
ExecInitSeqScan(SeqScan *node, EState *estate, Plan *parent) ExecInitSeqScan(SeqScan *node, EState *estate)
{ {
CommonScanState *scanstate; SeqScanState *scanstate;
Oid reloid;
/* /*
* Once upon a time it was possible to have an outerPlan of a SeqScan, * Once upon a time it was possible to have an outerPlan of a SeqScan,
* but not any more. * but not any more.
*/ */
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->plan.state = estate;
/* /*
* create new CommonScanState for node * create state structure
*/ */
scanstate = makeNode(CommonScanState); scanstate = makeNode(SeqScanState);
node->scanstate = scanstate; scanstate->ps.plan = (Plan *) node;
scanstate->ps.state = estate;
/* /*
* Miscellaneous initialization * Miscellaneous initialization
* *
* create expression context for node * create expression context for node
*/ */
ExecAssignExprContext(estate, &scanstate->cstate); ExecAssignExprContext(estate, &scanstate->ps);
/*
* initialize child expressions
*/
scanstate->ps.targetlist = (List *)
ExecInitExpr((Node *) node->plan.targetlist,
(PlanState *) scanstate);
scanstate->ps.qual = (List *)
ExecInitExpr((Node *) node->plan.qual,
(PlanState *) scanstate);
#define SEQSCAN_NSLOTS 2 #define SEQSCAN_NSLOTS 2
/* /*
* tuple table initialization * tuple table initialization
*/ */
ExecInitResultTupleSlot(estate, &scanstate->cstate); ExecInitResultTupleSlot(estate, &scanstate->ps);
ExecInitScanTupleSlot(estate, scanstate); ExecInitScanTupleSlot(estate, scanstate);
/* /*
* initialize scan relation * initialize scan relation
*/ */
reloid = InitScanRelation(node, estate, scanstate); InitScanRelation(scanstate, estate);
scanstate->cstate.cs_TupFromTlist = false; scanstate->ps.ps_TupFromTlist = false;
/* /*
* initialize tuple type * initialize tuple type
*/ */
ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate); ExecAssignResultTypeFromTL(&scanstate->ps);
ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate); ExecAssignProjectionInfo(&scanstate->ps);
return TRUE; return scanstate;
} }
int int
...@@ -251,34 +252,34 @@ ExecCountSlotsSeqScan(SeqScan *node) ...@@ -251,34 +252,34 @@ ExecCountSlotsSeqScan(SeqScan *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecEndSeqScan(SeqScan *node) ExecEndSeqScan(SeqScanState *node)
{ {
CommonScanState *scanstate;
Relation relation; Relation relation;
HeapScanDesc scanDesc; HeapScanDesc scanDesc;
/* /*
* get information from node * get information from node
*/ */
scanstate = node->scanstate; relation = node->ss_currentRelation;
relation = scanstate->css_currentRelation; scanDesc = node->ss_currentScanDesc;
scanDesc = scanstate->css_currentScanDesc;
/* /*
* 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->cstate); ExecFreeProjectionInfo(&node->ps);
ExecFreeExprContext(&scanstate->cstate); ExecFreeExprContext(&node->ps);
/* /*
* close heap scan * close heap scan
*/ */
heap_endscan(scanDesc); heap_endscan(scanDesc);
/*
* clean out the tuple table
*/
ExecClearTuple(node->ps.ps_ResultTupleSlot);
ExecClearTuple(node->ss_ScanTupleSlot);
/* /*
* close the heap relation. * close the heap relation.
* *
...@@ -288,12 +289,6 @@ ExecEndSeqScan(SeqScan *node) ...@@ -288,12 +289,6 @@ ExecEndSeqScan(SeqScan *node)
* locking, however.) * locking, however.)
*/ */
heap_close(relation, NoLock); heap_close(relation, NoLock);
/*
* clean out the tuple table
*/
ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
ExecClearTuple(scanstate->css_ScanTupleSlot);
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -308,24 +303,24 @@ ExecEndSeqScan(SeqScan *node) ...@@ -308,24 +303,24 @@ ExecEndSeqScan(SeqScan *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecSeqReScan(SeqScan *node, ExprContext *exprCtxt, Plan *parent) ExecSeqReScan(SeqScanState *node, ExprContext *exprCtxt)
{ {
CommonScanState *scanstate;
EState *estate; EState *estate;
Index scanrelid;
HeapScanDesc scan; HeapScanDesc scan;
scanstate = node->scanstate; estate = node->ps.state;
estate = node->plan.state; scanrelid = ((SeqScan *) node->ps.plan)->scanrelid;
/* If this is re-scanning of PlanQual ... */ /* If this is re-scanning of PlanQual ... */
if (estate->es_evTuple != NULL && if (estate->es_evTuple != NULL &&
estate->es_evTuple[node->scanrelid - 1] != NULL) estate->es_evTuple[scanrelid - 1] != NULL)
{ {
estate->es_evTupleNull[node->scanrelid - 1] = false; estate->es_evTupleNull[scanrelid - 1] = false;
return; return;
} }
scan = scanstate->css_currentScanDesc; scan = node->ss_currentScanDesc;
heap_rescan(scan, /* scan desc */ heap_rescan(scan, /* scan desc */
NULL); /* new scan keys */ NULL); /* new scan keys */
...@@ -338,13 +333,11 @@ ExecSeqReScan(SeqScan *node, ExprContext *exprCtxt, Plan *parent) ...@@ -338,13 +333,11 @@ ExecSeqReScan(SeqScan *node, ExprContext *exprCtxt, Plan *parent)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecSeqMarkPos(SeqScan *node) ExecSeqMarkPos(SeqScanState *node)
{ {
CommonScanState *scanstate;
HeapScanDesc scan; HeapScanDesc scan;
scanstate = node->scanstate; scan = node->ss_currentScanDesc;
scan = scanstate->css_currentScanDesc;
heap_markpos(scan); heap_markpos(scan);
} }
...@@ -355,12 +348,10 @@ ExecSeqMarkPos(SeqScan *node) ...@@ -355,12 +348,10 @@ ExecSeqMarkPos(SeqScan *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecSeqRestrPos(SeqScan *node) ExecSeqRestrPos(SeqScanState *node)
{ {
CommonScanState *scanstate;
HeapScanDesc scan; HeapScanDesc scan;
scanstate = node->scanstate; scan = node->ss_currentScanDesc;
scan = scanstate->css_currentScanDesc;
heap_restrpos(scan); heap_restrpos(scan);
} }
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSetOp.c,v 1.6 2002/06/20 20:29:28 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSetOp.c,v 1.7 2002/12/05 15:50:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -44,28 +44,27 @@ ...@@ -44,28 +44,27 @@
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
TupleTableSlot * /* return: a tuple or NULL */ TupleTableSlot * /* return: a tuple or NULL */
ExecSetOp(SetOp *node) ExecSetOp(SetOpState *node)
{ {
SetOpState *setopstate; SetOp *plannode = (SetOp *) node->ps.plan;
TupleTableSlot *resultTupleSlot; TupleTableSlot *resultTupleSlot;
Plan *outerPlan; PlanState *outerPlan;
TupleDesc tupDesc; TupleDesc tupDesc;
/* /*
* get information from the node * get information from the node
*/ */
setopstate = node->setopstate; outerPlan = outerPlanState(node);
outerPlan = outerPlan((Plan *) node); resultTupleSlot = node->ps.ps_ResultTupleSlot;
resultTupleSlot = setopstate->cstate.cs_ResultTupleSlot; tupDesc = ExecGetResultType(&node->ps);
tupDesc = ExecGetResultType(&setopstate->cstate);
/* /*
* If the previously-returned tuple needs to be returned more than * If the previously-returned tuple needs to be returned more than
* once, keep returning it. * once, keep returning it.
*/ */
if (setopstate->numOutput > 0) if (node->numOutput > 0)
{ {
setopstate->numOutput--; node->numOutput--;
return resultTupleSlot; return resultTupleSlot;
} }
...@@ -88,15 +87,15 @@ ExecSetOp(SetOp *node) ...@@ -88,15 +87,15 @@ ExecSetOp(SetOp *node)
/* /*
* fetch a tuple from the outer subplan, unless we already did. * fetch a tuple from the outer subplan, unless we already did.
*/ */
if (setopstate->cstate.cs_OuterTupleSlot == NULL && if (node->ps.ps_OuterTupleSlot == NULL &&
!setopstate->subplan_done) !node->subplan_done)
{ {
setopstate->cstate.cs_OuterTupleSlot = node->ps.ps_OuterTupleSlot =
ExecProcNode(outerPlan, (Plan *) node); ExecProcNode(outerPlan);
if (TupIsNull(setopstate->cstate.cs_OuterTupleSlot)) if (TupIsNull(node->ps.ps_OuterTupleSlot))
setopstate->subplan_done = true; node->subplan_done = true;
} }
inputTupleSlot = setopstate->cstate.cs_OuterTupleSlot; inputTupleSlot = node->ps.ps_OuterTupleSlot;
if (TupIsNull(resultTupleSlot)) if (TupIsNull(resultTupleSlot))
{ {
...@@ -104,18 +103,18 @@ ExecSetOp(SetOp *node) ...@@ -104,18 +103,18 @@ ExecSetOp(SetOp *node)
* First of group: save a copy in result slot, and reset * First of group: save a copy in result slot, and reset
* duplicate-counters for new group. * duplicate-counters for new group.
*/ */
if (setopstate->subplan_done) if (node->subplan_done)
return NULL; /* no more tuples */ return NULL; /* no more tuples */
ExecStoreTuple(heap_copytuple(inputTupleSlot->val), ExecStoreTuple(heap_copytuple(inputTupleSlot->val),
resultTupleSlot, resultTupleSlot,
InvalidBuffer, InvalidBuffer,
true); /* free copied tuple at true); /* free copied tuple at
* ExecClearTuple */ * ExecClearTuple */
setopstate->numLeft = 0; node->numLeft = 0;
setopstate->numRight = 0; node->numRight = 0;
endOfGroup = false; endOfGroup = false;
} }
else if (setopstate->subplan_done) else if (node->subplan_done)
{ {
/* /*
* Reached end of input, so finish processing final group * Reached end of input, so finish processing final group
...@@ -131,9 +130,9 @@ ExecSetOp(SetOp *node) ...@@ -131,9 +130,9 @@ ExecSetOp(SetOp *node)
if (execTuplesMatch(inputTupleSlot->val, if (execTuplesMatch(inputTupleSlot->val,
resultTupleSlot->val, resultTupleSlot->val,
tupDesc, tupDesc,
node->numCols, node->dupColIdx, plannode->numCols, plannode->dupColIdx,
setopstate->eqfunctions, node->eqfunctions,
setopstate->tempContext)) node->tempContext))
endOfGroup = false; endOfGroup = false;
else else
endOfGroup = true; endOfGroup = true;
...@@ -146,37 +145,37 @@ ExecSetOp(SetOp *node) ...@@ -146,37 +145,37 @@ ExecSetOp(SetOp *node)
* Decide how many copies (if any) to emit. This logic is * Decide how many copies (if any) to emit. This logic is
* straight from the SQL92 specification. * straight from the SQL92 specification.
*/ */
switch (node->cmd) switch (plannode->cmd)
{ {
case SETOPCMD_INTERSECT: case SETOPCMD_INTERSECT:
if (setopstate->numLeft > 0 && setopstate->numRight > 0) if (node->numLeft > 0 && node->numRight > 0)
setopstate->numOutput = 1; node->numOutput = 1;
else else
setopstate->numOutput = 0; node->numOutput = 0;
break; break;
case SETOPCMD_INTERSECT_ALL: case SETOPCMD_INTERSECT_ALL:
setopstate->numOutput = node->numOutput =
(setopstate->numLeft < setopstate->numRight) ? (node->numLeft < node->numRight) ?
setopstate->numLeft : setopstate->numRight; node->numLeft : node->numRight;
break; break;
case SETOPCMD_EXCEPT: case SETOPCMD_EXCEPT:
if (setopstate->numLeft > 0 && setopstate->numRight == 0) if (node->numLeft > 0 && node->numRight == 0)
setopstate->numOutput = 1; node->numOutput = 1;
else else
setopstate->numOutput = 0; node->numOutput = 0;
break; break;
case SETOPCMD_EXCEPT_ALL: case SETOPCMD_EXCEPT_ALL:
setopstate->numOutput = node->numOutput =
(setopstate->numLeft < setopstate->numRight) ? (node->numLeft < node->numRight) ?
0 : (setopstate->numLeft - setopstate->numRight); 0 : (node->numLeft - node->numRight);
break; break;
default: default:
elog(ERROR, "ExecSetOp: bogus command code %d", elog(ERROR, "ExecSetOp: bogus command code %d",
(int) node->cmd); (int) plannode->cmd);
break; break;
} }
/* Fall out of for-loop if we have tuples to emit */ /* Fall out of for-loop if we have tuples to emit */
if (setopstate->numOutput > 0) if (node->numOutput > 0)
break; break;
/* Else flag that we have no current tuple, and loop around */ /* Else flag that we have no current tuple, and loop around */
ExecClearTuple(resultTupleSlot); ExecClearTuple(resultTupleSlot);
...@@ -191,16 +190,16 @@ ExecSetOp(SetOp *node) ...@@ -191,16 +190,16 @@ ExecSetOp(SetOp *node)
bool isNull; bool isNull;
flag = DatumGetInt32(heap_getattr(inputTupleSlot->val, flag = DatumGetInt32(heap_getattr(inputTupleSlot->val,
node->flagColIdx, plannode->flagColIdx,
tupDesc, tupDesc,
&isNull)); &isNull));
Assert(!isNull); Assert(!isNull);
if (flag) if (flag)
setopstate->numRight++; node->numRight++;
else else
setopstate->numLeft++; node->numLeft++;
/* Set flag to fetch a new input tuple, and loop around */ /* Set flag to fetch a new input tuple, and loop around */
setopstate->cstate.cs_OuterTupleSlot = NULL; node->ps.ps_OuterTupleSlot = NULL;
} }
} }
...@@ -208,8 +207,8 @@ ExecSetOp(SetOp *node) ...@@ -208,8 +207,8 @@ ExecSetOp(SetOp *node)
* If we fall out of loop, then we need to emit at least one copy of * If we fall out of loop, then we need to emit at least one copy of
* resultTuple. * resultTuple.
*/ */
Assert(setopstate->numOutput > 0); Assert(node->numOutput > 0);
setopstate->numOutput--; node->numOutput--;
return resultTupleSlot; return resultTupleSlot;
} }
...@@ -220,23 +219,19 @@ ExecSetOp(SetOp *node) ...@@ -220,23 +219,19 @@ ExecSetOp(SetOp *node)
* the node's subplan. * the node's subplan.
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
bool /* return: initialization status */ SetOpState *
ExecInitSetOp(SetOp *node, EState *estate, Plan *parent) ExecInitSetOp(SetOp *node, EState *estate)
{ {
SetOpState *setopstate; SetOpState *setopstate;
Plan *outerPlan;
/* /*
* assign execution state to node * create state structure
*/
node->plan.state = estate;
/*
* create new SetOpState for node
*/ */
setopstate = makeNode(SetOpState); setopstate = makeNode(SetOpState);
node->setopstate = setopstate; setopstate->ps.plan = (Plan *) node;
setopstate->cstate.cs_OuterTupleSlot = NULL; setopstate->ps.state = estate;
setopstate->ps.ps_OuterTupleSlot = NULL;
setopstate->subplan_done = false; setopstate->subplan_done = false;
setopstate->numOutput = 0; setopstate->numOutput = 0;
...@@ -259,30 +254,29 @@ ExecInitSetOp(SetOp *node, EState *estate, Plan *parent) ...@@ -259,30 +254,29 @@ ExecInitSetOp(SetOp *node, EState *estate, Plan *parent)
/* /*
* Tuple table initialization * Tuple table initialization
*/ */
ExecInitResultTupleSlot(estate, &setopstate->cstate); ExecInitResultTupleSlot(estate, &setopstate->ps);
/* /*
* then initialize outer plan * then initialize outer plan
*/ */
outerPlan = outerPlan((Plan *) node); outerPlanState(setopstate) = ExecInitNode(outerPlan(node), estate);
ExecInitNode(outerPlan, estate, (Plan *) node);
/* /*
* setop nodes do no projections, so initialize projection info for * setop nodes do no projections, so initialize projection info for
* this node appropriately * this node appropriately
*/ */
ExecAssignResultTypeFromOuterPlan((Plan *) node, &setopstate->cstate); ExecAssignResultTypeFromOuterPlan(&setopstate->ps);
setopstate->cstate.cs_ProjInfo = NULL; setopstate->ps.ps_ProjInfo = NULL;
/* /*
* Precompute fmgr lookup data for inner loop * Precompute fmgr lookup data for inner loop
*/ */
setopstate->eqfunctions = setopstate->eqfunctions =
execTuplesMatchPrepare(ExecGetResultType(&setopstate->cstate), execTuplesMatchPrepare(ExecGetResultType(&setopstate->ps),
node->numCols, node->numCols,
node->dupColIdx); node->dupColIdx);
return TRUE; return setopstate;
} }
int int
...@@ -301,34 +295,30 @@ ExecCountSlotsSetOp(SetOp *node) ...@@ -301,34 +295,30 @@ ExecCountSlotsSetOp(SetOp *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecEndSetOp(SetOp *node) ExecEndSetOp(SetOpState *node)
{ {
SetOpState *setopstate = node->setopstate; /* clean up tuple table */
ExecClearTuple(node->ps.ps_ResultTupleSlot);
ExecEndNode(outerPlan((Plan *) node), (Plan *) node); node->ps.ps_OuterTupleSlot = NULL;
MemoryContextDelete(setopstate->tempContext); ExecEndNode(outerPlanState(node));
/* clean up tuple table */ MemoryContextDelete(node->tempContext);
ExecClearTuple(setopstate->cstate.cs_ResultTupleSlot);
setopstate->cstate.cs_OuterTupleSlot = NULL;
} }
void void
ExecReScanSetOp(SetOp *node, ExprContext *exprCtxt, Plan *parent) ExecReScanSetOp(SetOpState *node, ExprContext *exprCtxt)
{ {
SetOpState *setopstate = node->setopstate; ExecClearTuple(node->ps.ps_ResultTupleSlot);
node->ps.ps_OuterTupleSlot = NULL;
ExecClearTuple(setopstate->cstate.cs_ResultTupleSlot); node->subplan_done = false;
setopstate->cstate.cs_OuterTupleSlot = NULL; node->numOutput = 0;
setopstate->subplan_done = false;
setopstate->numOutput = 0;
/* /*
* 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);
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSort.c,v 1.40 2002/11/13 00:39:47 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSort.c,v 1.41 2002/12/05 15:50:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -88,10 +88,9 @@ ExtractSortKeys(Sort *sortnode, ...@@ -88,10 +88,9 @@ ExtractSortKeys(Sort *sortnode,
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
TupleTableSlot * TupleTableSlot *
ExecSort(Sort *node) ExecSort(SortState *node)
{ {
EState *estate; EState *estate;
SortState *sortstate;
ScanDirection dir; ScanDirection dir;
Tuplesortstate *tuplesortstate; Tuplesortstate *tuplesortstate;
HeapTuple heapTuple; HeapTuple heapTuple;
...@@ -104,10 +103,9 @@ ExecSort(Sort *node) ...@@ -104,10 +103,9 @@ ExecSort(Sort *node)
SO1_printf("ExecSort: %s\n", SO1_printf("ExecSort: %s\n",
"entering routine"); "entering routine");
sortstate = node->sortstate; estate = node->ss.ps.state;
estate = node->plan.state;
dir = estate->es_direction; dir = estate->es_direction;
tuplesortstate = (Tuplesortstate *) sortstate->tuplesortstate; tuplesortstate = (Tuplesortstate *) node->tuplesortstate;
/* /*
* If first time through, read all tuples from outer plan and pass * If first time through, read all tuples from outer plan and pass
...@@ -115,9 +113,10 @@ ExecSort(Sort *node) ...@@ -115,9 +113,10 @@ ExecSort(Sort *node)
* tuplesort. * tuplesort.
*/ */
if (!sortstate->sort_Done) if (!node->sort_Done)
{ {
Plan *outerNode; Sort *plannode = (Sort *) node->ss.ps.plan;
PlanState *outerNode;
TupleDesc tupDesc; TupleDesc tupDesc;
Oid *sortOperators; Oid *sortOperators;
AttrNumber *attNums; AttrNumber *attNums;
...@@ -127,8 +126,7 @@ ExecSort(Sort *node) ...@@ -127,8 +126,7 @@ ExecSort(Sort *node)
/* /*
* Want to scan subplan in the forward direction while creating * Want to scan subplan in the forward direction while creating
* the sorted data. (Does setting my direction actually affect * the sorted data.
* the subplan? I bet this is useless code...)
*/ */
estate->es_direction = ForwardScanDirection; estate->es_direction = ForwardScanDirection;
...@@ -138,15 +136,15 @@ ExecSort(Sort *node) ...@@ -138,15 +136,15 @@ ExecSort(Sort *node)
SO1_printf("ExecSort: %s\n", SO1_printf("ExecSort: %s\n",
"calling tuplesort_begin"); "calling tuplesort_begin");
outerNode = outerPlan((Plan *) node); outerNode = outerPlanState(node);
tupDesc = ExecGetTupType(outerNode); tupDesc = ExecGetTupType(outerNode);
ExtractSortKeys(node, &sortOperators, &attNums); ExtractSortKeys(plannode, &sortOperators, &attNums);
tuplesortstate = tuplesort_begin_heap(tupDesc, node->keycount, tuplesortstate = tuplesort_begin_heap(tupDesc, plannode->keycount,
sortOperators, attNums, sortOperators, attNums,
true /* randomAccess */ ); true /* randomAccess */ );
sortstate->tuplesortstate = (void *) tuplesortstate; node->tuplesortstate = (void *) tuplesortstate;
pfree(sortOperators); pfree(sortOperators);
pfree(attNums); pfree(attNums);
...@@ -157,7 +155,7 @@ ExecSort(Sort *node) ...@@ -157,7 +155,7 @@ ExecSort(Sort *node)
for (;;) for (;;)
{ {
slot = ExecProcNode(outerNode, (Plan *) node); slot = ExecProcNode(outerNode);
if (TupIsNull(slot)) if (TupIsNull(slot))
break; break;
...@@ -178,12 +176,12 @@ ExecSort(Sort *node) ...@@ -178,12 +176,12 @@ ExecSort(Sort *node)
/* /*
* make sure the tuple descriptor is up to date (is this needed?) * make sure the tuple descriptor is up to date (is this needed?)
*/ */
ExecAssignResultType(&sortstate->csstate.cstate, tupDesc, false); ExecAssignResultType(&node->ss.ps, tupDesc, false);
/* /*
* finally set the sorted flag to true * finally set the sorted flag to true
*/ */
sortstate->sort_Done = true; node->sort_Done = true;
SO1_printf("ExecSort: %s\n", "sorting done"); SO1_printf("ExecSort: %s\n", "sorting done");
} }
...@@ -198,7 +196,7 @@ ExecSort(Sort *node) ...@@ -198,7 +196,7 @@ ExecSort(Sort *node)
ScanDirectionIsForward(dir), ScanDirectionIsForward(dir),
&should_free); &should_free);
slot = sortstate->csstate.cstate.cs_ResultTupleSlot; slot = node->ss.ps.ps_ResultTupleSlot;
return ExecStoreTuple(heapTuple, slot, InvalidBuffer, should_free); return ExecStoreTuple(heapTuple, slot, InvalidBuffer, should_free);
} }
...@@ -209,29 +207,24 @@ ExecSort(Sort *node) ...@@ -209,29 +207,24 @@ ExecSort(Sort *node)
* produced by the planner and initailizes its outer subtree. * produced by the planner and initailizes its outer subtree.
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
bool SortState *
ExecInitSort(Sort *node, EState *estate, Plan *parent) ExecInitSort(Sort *node, EState *estate)
{ {
SortState *sortstate; SortState *sortstate;
Plan *outerPlan;
SO1_printf("ExecInitSort: %s\n", SO1_printf("ExecInitSort: %s\n",
"initializing sort node"); "initializing sort node");
/*
* assign the node's execution state
*/
node->plan.state = estate;
/* /*
* create state structure * create state structure
*/ */
sortstate = makeNode(SortState); sortstate = makeNode(SortState);
sortstate->ss.ps.plan = (Plan *) node;
sortstate->ss.ps.state = estate;
sortstate->sort_Done = false; sortstate->sort_Done = false;
sortstate->tuplesortstate = NULL; sortstate->tuplesortstate = NULL;
node->sortstate = sortstate;
/* /*
* Miscellaneous initialization * Miscellaneous initialization
* *
...@@ -246,27 +239,26 @@ ExecInitSort(Sort *node, EState *estate, Plan *parent) ...@@ -246,27 +239,26 @@ ExecInitSort(Sort *node, EState *estate, Plan *parent)
* *
* sort nodes only return scan tuples from their sorted relation. * sort nodes only return scan tuples from their sorted relation.
*/ */
ExecInitResultTupleSlot(estate, &sortstate->csstate.cstate); ExecInitResultTupleSlot(estate, &sortstate->ss.ps);
ExecInitScanTupleSlot(estate, &sortstate->csstate); ExecInitScanTupleSlot(estate, &sortstate->ss);
/* /*
* initializes child nodes * initializes child nodes
*/ */
outerPlan = outerPlan((Plan *) node); outerPlanState(sortstate) = ExecInitNode(outerPlan(node), estate);
ExecInitNode(outerPlan, estate, (Plan *) node);
/* /*
* 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, &sortstate->csstate.cstate); ExecAssignResultTypeFromOuterPlan(&sortstate->ss.ps);
ExecAssignScanTypeFromOuterPlan((Plan *) node, &sortstate->csstate); ExecAssignScanTypeFromOuterPlan(&sortstate->ss);
sortstate->csstate.cstate.cs_ProjInfo = NULL; sortstate->ss.ps.ps_ProjInfo = NULL;
SO1_printf("ExecInitSort: %s\n", SO1_printf("ExecInitSort: %s\n",
"sort node initialized"); "sort node initialized");
return TRUE; return sortstate;
} }
int int
...@@ -282,39 +274,27 @@ ExecCountSlotsSort(Sort *node) ...@@ -282,39 +274,27 @@ ExecCountSlotsSort(Sort *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecEndSort(Sort *node) ExecEndSort(SortState *node)
{ {
SortState *sortstate;
Plan *outerPlan;
/*
* get info from the sort state
*/
SO1_printf("ExecEndSort: %s\n", SO1_printf("ExecEndSort: %s\n",
"shutting down sort node"); "shutting down sort node");
sortstate = node->sortstate;
/* /*
* shut down the subplan * clean out the tuple table
*/ */
outerPlan = outerPlan((Plan *) node); ExecClearTuple(node->ss.ss_ScanTupleSlot);
ExecEndNode(outerPlan, (Plan *) node);
/* /*
* clean out the tuple table * shut down the subplan
*/ */
ExecClearTuple(sortstate->csstate.css_ScanTupleSlot); ExecEndNode(outerPlanState(node));
/* /*
* Release tuplesort resources * Release tuplesort resources
*/ */
if (sortstate->tuplesortstate != NULL) if (node->tuplesortstate != NULL)
tuplesort_end((Tuplesortstate *) sortstate->tuplesortstate); tuplesort_end((Tuplesortstate *) node->tuplesortstate);
sortstate->tuplesortstate = NULL; node->tuplesortstate = NULL;
pfree(sortstate);
node->sortstate = NULL;
SO1_printf("ExecEndSort: %s\n", SO1_printf("ExecEndSort: %s\n",
"sort node shutdown"); "sort node shutdown");
...@@ -327,17 +307,15 @@ ExecEndSort(Sort *node) ...@@ -327,17 +307,15 @@ ExecEndSort(Sort *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecSortMarkPos(Sort *node) ExecSortMarkPos(SortState *node)
{ {
SortState *sortstate = node->sortstate;
/* /*
* if we haven't sorted yet, just return * if we haven't sorted yet, just return
*/ */
if (!sortstate->sort_Done) if (!node->sort_Done)
return; return;
tuplesort_markpos((Tuplesortstate *) sortstate->tuplesortstate); tuplesort_markpos((Tuplesortstate *) node->tuplesortstate);
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -347,36 +325,32 @@ ExecSortMarkPos(Sort *node) ...@@ -347,36 +325,32 @@ ExecSortMarkPos(Sort *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecSortRestrPos(Sort *node) ExecSortRestrPos(SortState *node)
{ {
SortState *sortstate = node->sortstate;
/* /*
* if we haven't sorted yet, just return. * if we haven't sorted yet, just return.
*/ */
if (!sortstate->sort_Done) if (!node->sort_Done)
return; return;
/* /*
* restore the scan to the previously marked position * restore the scan to the previously marked position
*/ */
tuplesort_restorepos((Tuplesortstate *) sortstate->tuplesortstate); tuplesort_restorepos((Tuplesortstate *) node->tuplesortstate);
} }
void void
ExecReScanSort(Sort *node, ExprContext *exprCtxt, Plan *parent) ExecReScanSort(SortState *node, ExprContext *exprCtxt)
{ {
SortState *sortstate = node->sortstate;
/* /*
* If we haven't sorted yet, just return. If outerplan' chgParam is * If we haven't sorted yet, just return. If outerplan' chgParam is
* not NULL then it will be re-scanned by ExecProcNode, else - no * not NULL then it will be re-scanned by ExecProcNode, else - no
* reason to re-scan it at all. * reason to re-scan it at all.
*/ */
if (!sortstate->sort_Done) if (!node->sort_Done)
return; return;
ExecClearTuple(sortstate->csstate.cstate.cs_ResultTupleSlot); ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
/* /*
* If subnode is to be rescanned then we forget previous sort results; * If subnode is to be rescanned then we forget previous sort results;
...@@ -384,12 +358,12 @@ ExecReScanSort(Sort *node, ExprContext *exprCtxt, Plan *parent) ...@@ -384,12 +358,12 @@ ExecReScanSort(Sort *node, ExprContext *exprCtxt, Plan *parent)
* *
* Otherwise we can just rewind and rescan the sorted output. * Otherwise we can just rewind and rescan the sorted output.
*/ */
if (((Plan *) node)->lefttree->chgParam != NULL) if (((PlanState *) node)->lefttree->chgParam != NULL)
{ {
sortstate->sort_Done = false; node->sort_Done = false;
tuplesort_end((Tuplesortstate *) sortstate->tuplesortstate); tuplesort_end((Tuplesortstate *) node->tuplesortstate);
sortstate->tuplesortstate = NULL; node->tuplesortstate = NULL;
} }
else else
tuplesort_rescan((Tuplesortstate *) sortstate->tuplesortstate); tuplesort_rescan((Tuplesortstate *) node->tuplesortstate);
} }
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.34 2002/11/26 03:01:57 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.35 2002/12/05 15:50:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -27,14 +27,15 @@ ...@@ -27,14 +27,15 @@
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecSubPlan(node) * ExecSubPlan(node)
*
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
Datum Datum
ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull) ExecSubPlan(SubPlanState *node, List *pvar,
ExprContext *econtext, bool *isNull)
{ {
Plan *plan = node->plan; PlanState *planstate = node->planstate;
SubLink *sublink = node->sublink; SubPlan *subplan = (SubPlan *) node->ps.plan;
SubLink *sublink = subplan->sublink;
SubLinkType subLinkType = sublink->subLinkType; SubLinkType subLinkType = sublink->subLinkType;
bool useor = sublink->useor; bool useor = sublink->useor;
MemoryContext oldcontext; MemoryContext oldcontext;
...@@ -49,15 +50,15 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull) ...@@ -49,15 +50,15 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull)
*/ */
oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory); oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
if (node->setParam != NIL) if (subplan->setParam != NIL)
elog(ERROR, "ExecSubPlan: can't set parent params from subquery"); elog(ERROR, "ExecSubPlan: can't set parent params from subquery");
/* /*
* Set Params of this plan from parent plan correlation Vars * Set Params of this plan from parent plan correlation Vars
*/ */
if (node->parParam != NIL) if (subplan->parParam != NIL)
{ {
foreach(lst, node->parParam) foreach(lst, subplan->parParam)
{ {
ParamExecData *prm; ParamExecData *prm;
...@@ -69,11 +70,12 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull) ...@@ -69,11 +70,12 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull)
NULL); NULL);
pvar = lnext(pvar); pvar = lnext(pvar);
} }
plan->chgParam = nconc(plan->chgParam, listCopy(node->parParam)); planstate->chgParam = nconc(planstate->chgParam,
listCopy(subplan->parParam));
} }
Assert(pvar == NIL); Assert(pvar == NIL);
ExecReScan(plan, NULL, NULL); ExecReScan(planstate, NULL);
/* /*
* For all sublink types except EXPR_SUBLINK, the result is boolean as * For all sublink types except EXPR_SUBLINK, the result is boolean as
...@@ -96,9 +98,9 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull) ...@@ -96,9 +98,9 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull)
result = BoolGetDatum(subLinkType == ALL_SUBLINK); result = BoolGetDatum(subLinkType == ALL_SUBLINK);
*isNull = false; *isNull = false;
for (slot = ExecProcNode(plan, NULL); for (slot = ExecProcNode(planstate);
!TupIsNull(slot); !TupIsNull(slot);
slot = ExecProcNode(plan, NULL)) slot = ExecProcNode(planstate))
{ {
HeapTuple tup = slot->val; HeapTuple tup = slot->val;
TupleDesc tdesc = slot->ttc_tupleDescriptor; TupleDesc tdesc = slot->ttc_tupleDescriptor;
...@@ -283,13 +285,37 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull) ...@@ -283,13 +285,37 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull)
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecInitSubPlan * ExecInitSubPlan
*
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
bool SubPlanState *
ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent) ExecInitSubPlan(SubPlan *node, EState *estate)
{ {
EState *sp_estate = CreateExecutorState(); SubPlanState *subplanstate;
EState *sp_estate;
/*
* Do access checking on the rangetable entries in the subquery.
* Here, we assume the subquery is a SELECT.
*/
ExecCheckRTPerms(node->rtable, CMD_SELECT);
/*
* create state structure
*/
subplanstate = makeNode(SubPlanState);
subplanstate->ps.plan = (Plan *) node;
subplanstate->ps.state = estate;
subplanstate->needShutdown = false;
subplanstate->curTuple = NULL;
/* XXX temporary hack */
node->pstate = subplanstate;
/*
* create an EState for the subplan
*/
sp_estate = CreateExecutorState();
sp_estate->es_range_table = node->rtable; sp_estate->es_range_table = node->rtable;
sp_estate->es_param_list_info = estate->es_param_list_info; sp_estate->es_param_list_info = estate->es_param_list_info;
...@@ -297,14 +323,14 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent) ...@@ -297,14 +323,14 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent)
sp_estate->es_tupleTable = sp_estate->es_tupleTable =
ExecCreateTupleTable(ExecCountSlotsNode(node->plan) + 10); ExecCreateTupleTable(ExecCountSlotsNode(node->plan) + 10);
sp_estate->es_snapshot = estate->es_snapshot; sp_estate->es_snapshot = estate->es_snapshot;
sp_estate->es_instrument = estate->es_instrument;
node->needShutdown = false; /*
node->curTuple = NULL; * Start up the subplan
*/
if (!ExecInitNode(node->plan, sp_estate, parent)) subplanstate->planstate = ExecInitNode(node->plan, sp_estate);
return false;
node->needShutdown = true; /* now we need to shutdown the subplan */ subplanstate->needShutdown = true; /* now we need to shutdown the subplan */
/* /*
* If this plan is un-correlated or undirect correlated one and want * If this plan is un-correlated or undirect correlated one and want
...@@ -318,7 +344,7 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent) ...@@ -318,7 +344,7 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent)
{ {
ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]); ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
prm->execPlan = node; prm->execPlan = subplanstate;
} }
/* /*
...@@ -328,7 +354,7 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent) ...@@ -328,7 +354,7 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent)
*/ */
} }
return true; return subplanstate;
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -345,10 +371,12 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent) ...@@ -345,10 +371,12 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecSetParamPlan(SubPlan *node, ExprContext *econtext) ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
{ {
Plan *plan = node->plan; PlanState *planstate = node->planstate;
SubLink *sublink = node->sublink; SubPlan *subplan = (SubPlan *) node->ps.plan;
SubLink *sublink = subplan->sublink;
EState *estate = node->ps.state;
MemoryContext oldcontext; MemoryContext oldcontext;
TupleTableSlot *slot; TupleTableSlot *slot;
List *lst; List *lst;
...@@ -364,12 +392,12 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext) ...@@ -364,12 +392,12 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
sublink->subLinkType == ALL_SUBLINK) sublink->subLinkType == ALL_SUBLINK)
elog(ERROR, "ExecSetParamPlan: ANY/ALL subselect unsupported"); elog(ERROR, "ExecSetParamPlan: ANY/ALL subselect unsupported");
if (plan->chgParam != NULL) if (planstate->chgParam != NULL)
ExecReScan(plan, NULL, NULL); ExecReScan(planstate, NULL);
for (slot = ExecProcNode(plan, NULL); for (slot = ExecProcNode(planstate);
!TupIsNull(slot); !TupIsNull(slot);
slot = ExecProcNode(plan, NULL)) slot = ExecProcNode(planstate))
{ {
HeapTuple tup = slot->val; HeapTuple tup = slot->val;
TupleDesc tdesc = slot->ttc_tupleDescriptor; TupleDesc tdesc = slot->ttc_tupleDescriptor;
...@@ -377,7 +405,7 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext) ...@@ -377,7 +405,7 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
if (sublink->subLinkType == EXISTS_SUBLINK) if (sublink->subLinkType == EXISTS_SUBLINK)
{ {
ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(node->setParam)]); ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(subplan->setParam)]);
prm->execPlan = NULL; prm->execPlan = NULL;
prm->value = BoolGetDatum(true); prm->value = BoolGetDatum(true);
...@@ -404,9 +432,9 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext) ...@@ -404,9 +432,9 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
heap_freetuple(node->curTuple); heap_freetuple(node->curTuple);
node->curTuple = tup; node->curTuple = tup;
foreach(lst, node->setParam) foreach(lst, subplan->setParam)
{ {
ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(lst)]); ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
prm->execPlan = NULL; prm->execPlan = NULL;
prm->value = heap_getattr(tup, i, tdesc, &(prm->isnull)); prm->value = heap_getattr(tup, i, tdesc, &(prm->isnull));
...@@ -418,7 +446,7 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext) ...@@ -418,7 +446,7 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
{ {
if (sublink->subLinkType == EXISTS_SUBLINK) if (sublink->subLinkType == EXISTS_SUBLINK)
{ {
ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(node->setParam)]); ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(subplan->setParam)]);
prm->execPlan = NULL; prm->execPlan = NULL;
prm->value = BoolGetDatum(false); prm->value = BoolGetDatum(false);
...@@ -426,9 +454,9 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext) ...@@ -426,9 +454,9 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
} }
else else
{ {
foreach(lst, node->setParam) foreach(lst, subplan->setParam)
{ {
ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(lst)]); ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
prm->execPlan = NULL; prm->execPlan = NULL;
prm->value = (Datum) 0; prm->value = (Datum) 0;
...@@ -437,9 +465,9 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext) ...@@ -437,9 +465,9 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
} }
} }
if (plan->extParam == NULL) /* un-correlated ... */ if (planstate->plan->extParam == NULL) /* un-correlated ... */
{ {
ExecEndNode(plan, NULL); ExecEndNode(planstate);
node->needShutdown = false; node->needShutdown = false;
} }
...@@ -451,11 +479,11 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext) ...@@ -451,11 +479,11 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecEndSubPlan(SubPlan *node) ExecEndSubPlan(SubPlanState *node)
{ {
if (node->needShutdown) if (node->needShutdown)
{ {
ExecEndNode(node->plan, NULL); ExecEndNode(node->planstate);
node->needShutdown = false; node->needShutdown = false;
} }
if (node->curTuple) if (node->curTuple)
...@@ -466,33 +494,34 @@ ExecEndSubPlan(SubPlan *node) ...@@ -466,33 +494,34 @@ ExecEndSubPlan(SubPlan *node)
} }
void void
ExecReScanSetParamPlan(SubPlan *node, Plan *parent) ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent)
{ {
Plan *plan = node->plan; PlanState *planstate = node->planstate;
SubPlan *subplan = (SubPlan *) node->ps.plan;
EState *estate = node->ps.state;
List *lst; List *lst;
if (node->parParam != NULL) if (subplan->parParam != NULL)
elog(ERROR, "ExecReScanSetParamPlan: direct correlated subquery unsupported, yet"); elog(ERROR, "ExecReScanSetParamPlan: direct correlated subquery unsupported, yet");
if (node->setParam == NULL) if (subplan->setParam == NULL)
elog(ERROR, "ExecReScanSetParamPlan: setParam list is NULL"); elog(ERROR, "ExecReScanSetParamPlan: setParam list is NULL");
if (plan->extParam == NULL) if (planstate->plan->extParam == NULL)
elog(ERROR, "ExecReScanSetParamPlan: extParam list of plan is NULL"); elog(ERROR, "ExecReScanSetParamPlan: extParam list of plan is NULL");
/* /*
* Don't actual re-scan: ExecSetParamPlan does re-scan if * Don't actual re-scan: ExecSetParamPlan does re-scan if
* node->plan->chgParam is not NULL... ExecReScan (plan, NULL, NULL); * subplan->plan->chgParam is not NULL... ExecReScan (planstate, NULL);
*/ */
/* /*
* Mark this subplan's output parameters as needing recalculation * Mark this subplan's output parameters as needing recalculation
*/ */
foreach(lst, node->setParam) foreach(lst, subplan->setParam)
{ {
ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(lst)]); ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
prm->execPlan = node; prm->execPlan = node;
} }
parent->chgParam = nconc(parent->chgParam, listCopy(node->setParam)); parent->chgParam = nconc(parent->chgParam, listCopy(subplan->setParam));
} }
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.13 2002/06/20 20:29:28 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.14 2002/12/05 15:50:33 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#include "parser/parsetree.h" #include "parser/parsetree.h"
#include "tcop/pquery.h" #include "tcop/pquery.h"
static TupleTableSlot *SubqueryNext(SubqueryScan *node); static TupleTableSlot *SubqueryNext(SubqueryScanState *node);
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* Scan Support * Scan Support
...@@ -48,9 +48,8 @@ static TupleTableSlot *SubqueryNext(SubqueryScan *node); ...@@ -48,9 +48,8 @@ static TupleTableSlot *SubqueryNext(SubqueryScan *node);
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static TupleTableSlot * static TupleTableSlot *
SubqueryNext(SubqueryScan *node) SubqueryNext(SubqueryScanState *node)
{ {
SubqueryScanState *subquerystate;
EState *estate; EState *estate;
ScanDirection direction; ScanDirection direction;
TupleTableSlot *slot; TupleTableSlot *slot;
...@@ -58,8 +57,7 @@ SubqueryNext(SubqueryScan *node) ...@@ -58,8 +57,7 @@ SubqueryNext(SubqueryScan *node)
/* /*
* get information from the estate and scan state * get information from the estate and scan state
*/ */
estate = node->scan.plan.state; estate = node->ss.ps.state;
subquerystate = (SubqueryScanState *) node->scan.scanstate;
direction = estate->es_direction; direction = estate->es_direction;
/* /*
...@@ -70,11 +68,11 @@ SubqueryNext(SubqueryScan *node) ...@@ -70,11 +68,11 @@ SubqueryNext(SubqueryScan *node)
/* /*
* get the next tuple from the sub-query * get the next tuple from the sub-query
*/ */
subquerystate->sss_SubEState->es_direction = direction; node->sss_SubEState->es_direction = direction;
slot = ExecProcNode(node->subplan, (Plan *) node); slot = ExecProcNode(node->subplan);
subquerystate->csstate.css_ScanTupleSlot = slot; node->ss.ss_ScanTupleSlot = slot;
return slot; return slot;
} }
...@@ -90,20 +88,20 @@ SubqueryNext(SubqueryScan *node) ...@@ -90,20 +88,20 @@ SubqueryNext(SubqueryScan *node)
*/ */
TupleTableSlot * TupleTableSlot *
ExecSubqueryScan(SubqueryScan *node) ExecSubqueryScan(SubqueryScanState *node)
{ {
/* /*
* use SubqueryNext as access method * use SubqueryNext as access method
*/ */
return ExecScan(&node->scan, (ExecScanAccessMtd) SubqueryNext); return ExecScan(&node->ss, (ExecScanAccessMtd) SubqueryNext);
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* ExecInitSubqueryScan * ExecInitSubqueryScan
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
bool SubqueryScanState *
ExecInitSubqueryScan(SubqueryScan *node, EState *estate, Plan *parent) ExecInitSubqueryScan(SubqueryScan *node, EState *estate)
{ {
SubqueryScanState *subquerystate; SubqueryScanState *subquerystate;
RangeTblEntry *rte; RangeTblEntry *rte;
...@@ -112,33 +110,39 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, Plan *parent) ...@@ -112,33 +110,39 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, Plan *parent)
/* /*
* SubqueryScan should not have any "normal" children. * SubqueryScan should not have any "normal" 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 * create state structure
*/
node->scan.plan.state = estate;
/*
* create new SubqueryScanState for node
*/ */
subquerystate = makeNode(SubqueryScanState); subquerystate = makeNode(SubqueryScanState);
node->scan.scanstate = (CommonScanState *) subquerystate; subquerystate->ss.ps.plan = (Plan *) node;
subquerystate->ss.ps.state = estate;
/* /*
* Miscellaneous initialization * Miscellaneous initialization
* *
* create expression context for node * create expression context for node
*/ */
ExecAssignExprContext(estate, &subquerystate->csstate.cstate); ExecAssignExprContext(estate, &subquerystate->ss.ps);
/*
* initialize child expressions
*/
subquerystate->ss.ps.targetlist = (List *)
ExecInitExpr((Node *) node->scan.plan.targetlist,
(PlanState *) subquerystate);
subquerystate->ss.ps.qual = (List *)
ExecInitExpr((Node *) node->scan.plan.qual,
(PlanState *) subquerystate);
#define SUBQUERYSCAN_NSLOTS 1 #define SUBQUERYSCAN_NSLOTS 1
/* /*
* tuple table initialization * tuple table initialization
*/ */
ExecInitResultTupleSlot(estate, &subquerystate->csstate.cstate); ExecInitResultTupleSlot(estate, &subquerystate->ss.ps);
/* /*
* initialize subquery * initialize subquery
...@@ -157,20 +161,20 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, Plan *parent) ...@@ -157,20 +161,20 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, Plan *parent)
sp_estate->es_tupleTable = sp_estate->es_tupleTable =
ExecCreateTupleTable(ExecCountSlotsNode(node->subplan) + 10); ExecCreateTupleTable(ExecCountSlotsNode(node->subplan) + 10);
sp_estate->es_snapshot = estate->es_snapshot; sp_estate->es_snapshot = estate->es_snapshot;
sp_estate->es_instrument = estate->es_instrument;
if (!ExecInitNode(node->subplan, sp_estate, (Plan *) node)) subquerystate->subplan = ExecInitNode(node->subplan, sp_estate);
return false;
subquerystate->csstate.css_ScanTupleSlot = NULL; subquerystate->ss.ss_ScanTupleSlot = NULL;
subquerystate->csstate.cstate.cs_TupFromTlist = false; subquerystate->ss.ps.ps_TupFromTlist = false;
/* /*
* initialize tuple type * initialize tuple type
*/ */
ExecAssignResultTypeFromTL((Plan *) node, &subquerystate->csstate.cstate); ExecAssignResultTypeFromTL(&subquerystate->ss.ps);
ExecAssignProjectionInfo((Plan *) node, &subquerystate->csstate.cstate); ExecAssignProjectionInfo(&subquerystate->ss.ps);
return TRUE; return subquerystate;
} }
int int
...@@ -191,42 +195,31 @@ ExecCountSlotsSubqueryScan(SubqueryScan *node) ...@@ -191,42 +195,31 @@ ExecCountSlotsSubqueryScan(SubqueryScan *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecEndSubqueryScan(SubqueryScan *node) ExecEndSubqueryScan(SubqueryScanState *node)
{ {
SubqueryScanState *subquerystate;
/* /*
* get information from node * Free the projection info and the scan attribute info
*/ */
subquerystate = (SubqueryScanState *) node->scan.scanstate; ExecFreeProjectionInfo(&node->ss.ps);
ExecFreeExprContext(&node->ss.ps);
/* /*
* Free the projection info and the scan attribute info * clean out the upper tuple table
*
* Note: we don't ExecFreeResultType(subquerystate) because the rule
* manager depends on the tupType returned by ExecMain(). So for now,
* this is freed at end-transaction time. -cim 6/2/91
*/ */
ExecFreeProjectionInfo(&subquerystate->csstate.cstate); ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecFreeExprContext(&subquerystate->csstate.cstate);
/* /*
* close down subquery * close down subquery
*/ */
ExecEndNode(node->subplan, (Plan *) node); ExecEndNode(node->subplan);
/* /*
* clean up subquery's tuple table * clean up subquery's tuple table
*/ */
subquerystate->csstate.css_ScanTupleSlot = NULL; node->ss.ss_ScanTupleSlot = NULL;
ExecDropTupleTable(subquerystate->sss_SubEState->es_tupleTable, true); ExecDropTupleTable(node->sss_SubEState->es_tupleTable, true);
/* XXX we seem to be leaking the sub-EState... */ /* XXX we seem to be leaking the sub-EState... */
/*
* clean out the upper tuple table
*/
ExecClearTuple(subquerystate->csstate.cstate.cs_ResultTupleSlot);
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -236,27 +229,25 @@ ExecEndSubqueryScan(SubqueryScan *node) ...@@ -236,27 +229,25 @@ ExecEndSubqueryScan(SubqueryScan *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecSubqueryReScan(SubqueryScan *node, ExprContext *exprCtxt, Plan *parent) ExecSubqueryReScan(SubqueryScanState *node, ExprContext *exprCtxt)
{ {
SubqueryScanState *subquerystate;
EState *estate; EState *estate;
subquerystate = (SubqueryScanState *) node->scan.scanstate; estate = node->ss.ps.state;
estate = node->scan.plan.state;
/* /*
* ExecReScan doesn't know about my subplan, so I have to do * ExecReScan doesn't know about my subplan, so I have to do
* changed-parameter signaling myself. * changed-parameter signaling myself.
*/ */
if (node->scan.plan.chgParam != NULL) if (node->ss.ps.chgParam != NULL)
SetChangedParamList(node->subplan, node->scan.plan.chgParam); SetChangedParamList(node->subplan, node->ss.ps.chgParam);
/* /*
* 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 (node->subplan->chgParam == NULL) if (node->subplan->chgParam == NULL)
ExecReScan(node->subplan, NULL, (Plan *) node); ExecReScan(node->subplan, NULL);
subquerystate->csstate.css_ScanTupleSlot = NULL; node->ss.ss_ScanTupleSlot = NULL;
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.27 2002/11/30 05:21:01 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.28 2002/12/05 15:50:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include "parser/parsetree.h" #include "parser/parsetree.h"
static int TidListCreate(List *, ExprContext *, ItemPointerData[]); static int TidListCreate(List *, ExprContext *, ItemPointerData[]);
static TupleTableSlot *TidNext(TidScan *node); static TupleTableSlot *TidNext(TidScanState *node);
static int static int
TidListCreate(List *evalList, ExprContext *econtext, ItemPointerData tidList[]) TidListCreate(List *evalList, ExprContext *econtext, ItemPointerData tidList[])
...@@ -65,19 +65,17 @@ TidListCreate(List *evalList, ExprContext *econtext, ItemPointerData tidList[]) ...@@ -65,19 +65,17 @@ TidListCreate(List *evalList, ExprContext *econtext, ItemPointerData tidList[])
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
static TupleTableSlot * static TupleTableSlot *
TidNext(TidScan *node) TidNext(TidScanState *node)
{ {
EState *estate; EState *estate;
CommonScanState *scanstate;
TidScanState *tidstate;
ScanDirection direction; ScanDirection direction;
Snapshot snapshot; Snapshot snapshot;
Relation heapRelation; Relation heapRelation;
HeapTuple tuple; HeapTuple tuple;
TupleTableSlot *slot; TupleTableSlot *slot;
Index scanrelid;
Buffer buffer = InvalidBuffer; Buffer buffer = InvalidBuffer;
int numTids; int numTids;
bool bBackward; bool bBackward;
int tidNumber; int tidNumber;
ItemPointerData *tidList; ItemPointerData *tidList;
...@@ -85,15 +83,14 @@ TidNext(TidScan *node) ...@@ -85,15 +83,14 @@ TidNext(TidScan *node)
/* /*
* extract necessary information from tid scan node * extract necessary information from tid scan node
*/ */
estate = node->scan.plan.state; estate = node->ss.ps.state;
direction = estate->es_direction; direction = estate->es_direction;
snapshot = estate->es_snapshot; snapshot = estate->es_snapshot;
scanstate = node->scan.scanstate; heapRelation = node->ss.ss_currentRelation;
tidstate = node->tidstate; numTids = node->tss_NumTids;
heapRelation = scanstate->css_currentRelation; tidList = node->tss_TidList;
numTids = tidstate->tss_NumTids; slot = node->ss.ss_ScanTupleSlot;
tidList = tidstate->tss_TidList; scanrelid = ((TidScan *) node->ss.ps.plan)->scan.scanrelid;
slot = scanstate->css_ScanTupleSlot;
/* /*
* Check if we are evaluating PlanQual for tuple of this relation. * Check if we are evaluating PlanQual for tuple of this relation.
...@@ -102,10 +99,10 @@ TidNext(TidScan *node) ...@@ -102,10 +99,10 @@ TidNext(TidScan *node)
* switching in Init/ReScan plan... * switching in Init/ReScan plan...
*/ */
if (estate->es_evTuple != NULL && if (estate->es_evTuple != NULL &&
estate->es_evTuple[node->scan.scanrelid - 1] != NULL) estate->es_evTuple[scanrelid - 1] != NULL)
{ {
ExecClearTuple(slot); ExecClearTuple(slot);
if (estate->es_evTupleNull[node->scan.scanrelid - 1]) if (estate->es_evTupleNull[scanrelid - 1])
return slot; /* return empty slot */ return slot; /* return empty slot */
/* /*
...@@ -113,15 +110,15 @@ TidNext(TidScan *node) ...@@ -113,15 +110,15 @@ TidNext(TidScan *node)
* list? In runtime-key case this is not certain, is it? * list? In runtime-key case this is not certain, is it?
*/ */
ExecStoreTuple(estate->es_evTuple[node->scan.scanrelid - 1], ExecStoreTuple(estate->es_evTuple[scanrelid - 1],
slot, InvalidBuffer, false); slot, InvalidBuffer, false);
/* Flag for the next call that no more tuples */ /* Flag for the next call that no more tuples */
estate->es_evTupleNull[node->scan.scanrelid - 1] = true; estate->es_evTupleNull[scanrelid - 1] = true;
return (slot); return (slot);
} }
tuple = &(tidstate->tss_htup); tuple = &(node->tss_htup);
/* /*
* ok, now that we have what we need, fetch an tid tuple. if scanning * ok, now that we have what we need, fetch an tid tuple. if scanning
...@@ -131,26 +128,26 @@ TidNext(TidScan *node) ...@@ -131,26 +128,26 @@ TidNext(TidScan *node)
bBackward = ScanDirectionIsBackward(direction); bBackward = ScanDirectionIsBackward(direction);
if (bBackward) if (bBackward)
{ {
tidNumber = numTids - tidstate->tss_TidPtr - 1; tidNumber = numTids - node->tss_TidPtr - 1;
if (tidNumber < 0) if (tidNumber < 0)
{ {
tidNumber = 0; tidNumber = 0;
tidstate->tss_TidPtr = numTids - 1; node->tss_TidPtr = numTids - 1;
} }
} }
else else
{ {
if ((tidNumber = tidstate->tss_TidPtr) < 0) if ((tidNumber = node->tss_TidPtr) < 0)
{ {
tidNumber = 0; tidNumber = 0;
tidstate->tss_TidPtr = 0; node->tss_TidPtr = 0;
} }
} }
while (tidNumber < numTids) while (tidNumber < numTids)
{ {
bool slot_is_valid = false; bool slot_is_valid = false;
tuple->t_self = tidList[tidstate->tss_TidPtr]; tuple->t_self = tidList[node->tss_TidPtr];
if (heap_fetch(heapRelation, snapshot, tuple, &buffer, false, NULL)) if (heap_fetch(heapRelation, snapshot, tuple, &buffer, false, NULL))
{ {
bool prev_matches = false; bool prev_matches = false;
...@@ -181,7 +178,7 @@ TidNext(TidScan *node) ...@@ -181,7 +178,7 @@ TidNext(TidScan *node)
* do this by passing the tuple through ExecQual and look for * do this by passing the tuple through ExecQual and look for
* failure with all previous qualifications. * failure with all previous qualifications.
*/ */
for (prev_tid = 0; prev_tid < tidstate->tss_TidPtr; for (prev_tid = 0; prev_tid < node->tss_TidPtr;
prev_tid++) prev_tid++)
{ {
if (ItemPointerEquals(&tidList[prev_tid], &tuple->t_self)) if (ItemPointerEquals(&tidList[prev_tid], &tuple->t_self))
...@@ -197,9 +194,9 @@ TidNext(TidScan *node) ...@@ -197,9 +194,9 @@ TidNext(TidScan *node)
} }
tidNumber++; tidNumber++;
if (bBackward) if (bBackward)
tidstate->tss_TidPtr--; node->tss_TidPtr--;
else else
tidstate->tss_TidPtr++; node->tss_TidPtr++;
if (slot_is_valid) if (slot_is_valid)
return slot; return slot;
} }
...@@ -231,12 +228,12 @@ TidNext(TidScan *node) ...@@ -231,12 +228,12 @@ TidNext(TidScan *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
TupleTableSlot * TupleTableSlot *
ExecTidScan(TidScan *node) ExecTidScan(TidScanState *node)
{ {
/* /*
* use TidNext as access method * use TidNext as access method
*/ */
return ExecScan(&node->scan, (ExecScanAccessMtd) TidNext); return ExecScan(&node->ss, (ExecScanAccessMtd) TidNext);
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -244,42 +241,30 @@ ExecTidScan(TidScan *node) ...@@ -244,42 +241,30 @@ ExecTidScan(TidScan *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecTidReScan(TidScan *node, ExprContext *exprCtxt, Plan *parent) ExecTidReScan(TidScanState *node, ExprContext *exprCtxt)
{ {
EState *estate; EState *estate;
TidScanState *tidstate;
ItemPointerData *tidList; ItemPointerData *tidList;
Index scanrelid;
estate = node->scan.plan.state; estate = node->ss.ps.state;
tidstate = node->tidstate; tidList = node->tss_TidList;
tidList = tidstate->tss_TidList; scanrelid = ((TidScan *) node->ss.ps.plan)->scan.scanrelid;
/* If we are being passed an outer tuple, save it for runtime key calc */ /* If we are being passed an outer tuple, save it for runtime key calc */
if (exprCtxt != NULL) if (exprCtxt != NULL)
node->scan.scanstate->cstate.cs_ExprContext->ecxt_outertuple = node->ss.ps.ps_ExprContext->ecxt_outertuple =
exprCtxt->ecxt_outertuple; exprCtxt->ecxt_outertuple;
/* do runtime calc of target TIDs, if needed */
if (node->needRescan)
tidstate->tss_NumTids =
TidListCreate(node->tideval,
node->scan.scanstate->cstate.cs_ExprContext,
tidList);
/* If this is re-scanning of PlanQual ... */ /* If this is re-scanning of PlanQual ... */
if (estate->es_evTuple != NULL && if (estate->es_evTuple != NULL &&
estate->es_evTuple[node->scan.scanrelid - 1] != NULL) estate->es_evTuple[scanrelid - 1] != NULL)
{ {
estate->es_evTupleNull[node->scan.scanrelid - 1] = false; estate->es_evTupleNull[scanrelid - 1] = false;
return; return;
} }
tidstate->tss_TidPtr = -1; node->tss_TidPtr = -1;
/*
* perhaps return something meaningful
*/
return;
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -290,18 +275,13 @@ ExecTidReScan(TidScan *node, ExprContext *exprCtxt, Plan *parent) ...@@ -290,18 +275,13 @@ ExecTidReScan(TidScan *node, ExprContext *exprCtxt, Plan *parent)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecEndTidScan(TidScan *node) ExecEndTidScan(TidScanState *node)
{ {
CommonScanState *scanstate;
TidScanState *tidstate;
/* /*
* extract information from the node * extract information from the node
*/ */
scanstate = node->scan.scanstate; if (node && node->tss_TidList)
tidstate = node->tidstate; pfree(node->tss_TidList);
if (tidstate && tidstate->tss_TidList)
pfree(tidstate->tss_TidList);
/* /*
* Free the projection info and the scan attribute info * Free the projection info and the scan attribute info
...@@ -310,8 +290,14 @@ ExecEndTidScan(TidScan *node) ...@@ -310,8 +290,14 @@ ExecEndTidScan(TidScan *node)
* depends on the tupType returned by ExecMain(). So for now, this is * depends on the tupType returned by ExecMain(). So for now, this is
* freed at end-transaction time. -cim 6/2/91 * freed at end-transaction time. -cim 6/2/91
*/ */
ExecFreeProjectionInfo(&scanstate->cstate); ExecFreeProjectionInfo(&node->ss.ps);
ExecFreeExprContext(&scanstate->cstate); ExecFreeExprContext(&node->ss.ps);
/*
* clear out tuple table slots
*/
ExecClearTuple(node->ss.ps.ps_ResultTupleSlot);
ExecClearTuple(node->ss.ss_ScanTupleSlot);
/* /*
* close the heap relation. * close the heap relation.
...@@ -320,13 +306,7 @@ ExecEndTidScan(TidScan *node) ...@@ -320,13 +306,7 @@ ExecEndTidScan(TidScan *node)
* ExecInitTidScan. This lock should be held till end of transaction. * ExecInitTidScan. This lock should be held till end of transaction.
* (There is a faction that considers this too much locking, however.) * (There is a faction that considers this too much locking, however.)
*/ */
heap_close(scanstate->css_currentRelation, NoLock); heap_close(node->ss.ss_currentRelation, NoLock);
/*
* clear out tuple table slots
*/
ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
ExecClearTuple(scanstate->css_ScanTupleSlot);
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -337,12 +317,9 @@ ExecEndTidScan(TidScan *node) ...@@ -337,12 +317,9 @@ ExecEndTidScan(TidScan *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecTidMarkPos(TidScan *node) ExecTidMarkPos(TidScanState *node)
{ {
TidScanState *tidstate; node->tss_MarkTidPtr = node->tss_TidPtr;
tidstate = node->tidstate;
tidstate->tss_MarkTidPtr = tidstate->tss_TidPtr;
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -355,12 +332,9 @@ ExecTidMarkPos(TidScan *node) ...@@ -355,12 +332,9 @@ ExecTidMarkPos(TidScan *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecTidRestrPos(TidScan *node) ExecTidRestrPos(TidScanState *node)
{ {
TidScanState *tidstate; node->tss_TidPtr = node->tss_MarkTidPtr;
tidstate = node->tidstate;
tidstate->tss_TidPtr = tidstate->tss_MarkTidPtr;
} }
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -374,11 +348,10 @@ ExecTidRestrPos(TidScan *node) ...@@ -374,11 +348,10 @@ ExecTidRestrPos(TidScan *node)
* estate: the execution state initialized in InitPlan. * estate: the execution state initialized in InitPlan.
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
bool TidScanState *
ExecInitTidScan(TidScan *node, EState *estate, Plan *parent) ExecInitTidScan(TidScan *node, EState *estate)
{ {
TidScanState *tidstate; TidScanState *tidstate;
CommonScanState *scanstate;
ItemPointerData *tidList; ItemPointerData *tidList;
int numTids; int numTids;
int tidPtr; int tidPtr;
...@@ -390,55 +363,49 @@ ExecInitTidScan(TidScan *node, EState *estate, Plan *parent) ...@@ -390,55 +363,49 @@ ExecInitTidScan(TidScan *node, EState *estate, Plan *parent)
List *execParam = NIL; List *execParam = NIL;
/* /*
* assign execution state to node * create state structure
*/ */
node->scan.plan.state = estate; tidstate = makeNode(TidScanState);
tidstate->ss.ps.plan = (Plan *) node;
tidstate->ss.ps.state = estate;
/* /*
* Part 1) initialize scan state * Miscellaneous initialization
* *
* create new CommonScanState for node * create expression context for node
*/ */
scanstate = makeNode(CommonScanState); ExecAssignExprContext(estate, &tidstate->ss.ps);
node->scan.scanstate = scanstate;
/* /*
* Miscellaneous initialization * initialize child expressions
*
* create expression context for node
*/ */
ExecAssignExprContext(estate, &scanstate->cstate); tidstate->ss.ps.targetlist = (List *)
ExecInitExpr((Node *) node->scan.plan.targetlist,
(PlanState *) tidstate);
tidstate->ss.ps.qual = (List *)
ExecInitExpr((Node *) node->scan.plan.qual,
(PlanState *) tidstate);
#define TIDSCAN_NSLOTS 2 #define TIDSCAN_NSLOTS 2
/* /*
* tuple table initialization * tuple table initialization
*/ */
ExecInitResultTupleSlot(estate, &scanstate->cstate); ExecInitResultTupleSlot(estate, &tidstate->ss.ps);
ExecInitScanTupleSlot(estate, scanstate); ExecInitScanTupleSlot(estate, &tidstate->ss);
/* /*
* initialize projection info. result type comes from scan desc * initialize projection info. result type comes from scan desc
* below.. * below..
*/ */
ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate); ExecAssignProjectionInfo(&tidstate->ss.ps);
/*
* Part 2) initialize tid scan state
*
* create new TidScanState for node
*/
tidstate = makeNode(TidScanState);
node->tidstate = tidstate;
/* /*
* get the tid node information * get the tid node information
*/ */
tidList = (ItemPointerData *) palloc(length(node->tideval) * sizeof(ItemPointerData)); tidList = (ItemPointerData *) palloc(length(node->tideval) * sizeof(ItemPointerData));
numTids = 0;
if (!node->needRescan)
numTids = TidListCreate(node->tideval, numTids = TidListCreate(node->tideval,
scanstate->cstate.cs_ExprContext, tidstate->ss.ps.ps_ExprContext,
tidList); tidList);
tidPtr = -1; tidPtr = -1;
...@@ -465,25 +432,25 @@ ExecInitTidScan(TidScan *node, EState *estate, Plan *parent) ...@@ -465,25 +432,25 @@ ExecInitTidScan(TidScan *node, EState *estate, Plan *parent)
currentRelation = heap_open(reloid, AccessShareLock); currentRelation = heap_open(reloid, AccessShareLock);
scanstate->css_currentRelation = currentRelation; tidstate->ss.ss_currentRelation = currentRelation;
scanstate->css_currentScanDesc = NULL; /* no heap scan here */ tidstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */
/* /*
* get the scan type from the relation descriptor. * get the scan type from the relation descriptor.
*/ */
ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false); ExecAssignScanType(&tidstate->ss, RelationGetDescr(currentRelation), false);
ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate); ExecAssignResultTypeFromTL(&tidstate->ss.ps);
/* /*
* if there are some PARAM_EXEC in skankeys then force tid rescan on * if there are some PARAM_EXEC in skankeys then force tid rescan on
* first scan. * first scan.
*/ */
((Plan *) node)->chgParam = execParam; tidstate->ss.ps.chgParam = execParam;
/* /*
* all done. * all done.
*/ */
return TRUE; return tidstate;
} }
int int
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeUnique.c,v 1.34 2002/06/20 20:29:28 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeUnique.c,v 1.35 2002/12/05 15:50:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
* NOTES * NOTES
* Assumes tuples returned from subplan arrive in * Assumes tuples returned from subplan arrive in
* sorted order. * sorted order.
*
*/ */
#include "postgres.h" #include "postgres.h"
...@@ -39,21 +38,20 @@ ...@@ -39,21 +38,20 @@
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
TupleTableSlot * /* return: a tuple or NULL */ TupleTableSlot * /* return: a tuple or NULL */
ExecUnique(Unique *node) ExecUnique(UniqueState *node)
{ {
UniqueState *uniquestate; Unique *plannode = (Unique *) node->ps.plan;
TupleTableSlot *resultTupleSlot; TupleTableSlot *resultTupleSlot;
TupleTableSlot *slot; TupleTableSlot *slot;
Plan *outerPlan; PlanState *outerPlan;
TupleDesc tupDesc; TupleDesc tupDesc;
/* /*
* get information from the node * get information from the node
*/ */
uniquestate = node->uniquestate; outerPlan = outerPlanState(node);
outerPlan = outerPlan((Plan *) node); resultTupleSlot = node->ps.ps_ResultTupleSlot;
resultTupleSlot = uniquestate->cstate.cs_ResultTupleSlot; tupDesc = ExecGetResultType(&node->ps);
tupDesc = ExecGetResultType(&uniquestate->cstate);
/* /*
* now loop, returning only non-duplicate tuples. We assume that the * now loop, returning only non-duplicate tuples. We assume that the
...@@ -64,14 +62,14 @@ ExecUnique(Unique *node) ...@@ -64,14 +62,14 @@ ExecUnique(Unique *node)
/* /*
* fetch a tuple from the outer subplan * fetch a tuple from the outer subplan
*/ */
slot = ExecProcNode(outerPlan, (Plan *) node); slot = ExecProcNode(outerPlan);
if (TupIsNull(slot)) if (TupIsNull(slot))
return NULL; return NULL;
/* /*
* Always return the first tuple from the subplan. * Always return the first tuple from the subplan.
*/ */
if (uniquestate->priorTuple == NULL) if (node->priorTuple == NULL)
break; break;
/* /*
...@@ -79,11 +77,11 @@ ExecUnique(Unique *node) ...@@ -79,11 +77,11 @@ ExecUnique(Unique *node)
* match. If so then we loop back and fetch another new tuple * match. If so then we loop back and fetch another new tuple
* from the subplan. * from the subplan.
*/ */
if (!execTuplesMatch(slot->val, uniquestate->priorTuple, if (!execTuplesMatch(slot->val, node->priorTuple,
tupDesc, tupDesc,
node->numCols, node->uniqColIdx, plannode->numCols, plannode->uniqColIdx,
uniquestate->eqfunctions, node->eqfunctions,
uniquestate->tempContext)) node->tempContext))
break; break;
} }
...@@ -99,11 +97,11 @@ ExecUnique(Unique *node) ...@@ -99,11 +97,11 @@ ExecUnique(Unique *node)
* handling in execMain.c). We assume that the caller will no longer * handling in execMain.c). We assume that the caller will no longer
* be interested in the current tuple after he next calls us. * be interested in the current tuple after he next calls us.
*/ */
if (uniquestate->priorTuple != NULL) if (node->priorTuple != NULL)
heap_freetuple(uniquestate->priorTuple); heap_freetuple(node->priorTuple);
uniquestate->priorTuple = heap_copytuple(slot->val); node->priorTuple = heap_copytuple(slot->val);
ExecStoreTuple(uniquestate->priorTuple, ExecStoreTuple(node->priorTuple,
resultTupleSlot, resultTupleSlot,
InvalidBuffer, InvalidBuffer,
false); /* tuple does not belong to slot */ false); /* tuple does not belong to slot */
...@@ -118,22 +116,18 @@ ExecUnique(Unique *node) ...@@ -118,22 +116,18 @@ ExecUnique(Unique *node)
* the node's subplan. * the node's subplan.
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
bool /* return: initialization status */ UniqueState *
ExecInitUnique(Unique *node, EState *estate, Plan *parent) ExecInitUnique(Unique *node, EState *estate)
{ {
UniqueState *uniquestate; UniqueState *uniquestate;
Plan *outerPlan;
/*
* assign execution state to node
*/
node->plan.state = estate;
/* /*
* create new UniqueState for node * create state structure
*/ */
uniquestate = makeNode(UniqueState); uniquestate = makeNode(UniqueState);
node->uniquestate = uniquestate; uniquestate->ps.plan = (Plan *) node;
uniquestate->ps.state = estate;
uniquestate->priorTuple = NULL; uniquestate->priorTuple = NULL;
/* /*
...@@ -155,30 +149,29 @@ ExecInitUnique(Unique *node, EState *estate, Plan *parent) ...@@ -155,30 +149,29 @@ ExecInitUnique(Unique *node, EState *estate, Plan *parent)
/* /*
* Tuple table initialization * Tuple table initialization
*/ */
ExecInitResultTupleSlot(estate, &uniquestate->cstate); ExecInitResultTupleSlot(estate, &uniquestate->ps);
/* /*
* then initialize outer plan * then initialize outer plan
*/ */
outerPlan = outerPlan((Plan *) node); outerPlanState(uniquestate) = ExecInitNode(outerPlan(node), estate);
ExecInitNode(outerPlan, estate, (Plan *) node);
/* /*
* unique nodes do no projections, so initialize projection info for * unique nodes do no projections, so initialize projection info for
* this node appropriately * this node appropriately
*/ */
ExecAssignResultTypeFromOuterPlan((Plan *) node, &uniquestate->cstate); ExecAssignResultTypeFromOuterPlan(&uniquestate->ps);
uniquestate->cstate.cs_ProjInfo = NULL; uniquestate->ps.ps_ProjInfo = NULL;
/* /*
* Precompute fmgr lookup data for inner loop * Precompute fmgr lookup data for inner loop
*/ */
uniquestate->eqfunctions = uniquestate->eqfunctions =
execTuplesMatchPrepare(ExecGetResultType(&uniquestate->cstate), execTuplesMatchPrepare(ExecGetResultType(&uniquestate->ps),
node->numCols, node->numCols,
node->uniqColIdx); node->uniqColIdx);
return TRUE; return uniquestate;
} }
int int
...@@ -197,41 +190,36 @@ ExecCountSlotsUnique(Unique *node) ...@@ -197,41 +190,36 @@ ExecCountSlotsUnique(Unique *node)
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
void void
ExecEndUnique(Unique *node) ExecEndUnique(UniqueState *node)
{ {
UniqueState *uniquestate = node->uniquestate;
ExecEndNode(outerPlan((Plan *) node), (Plan *) node);
MemoryContextDelete(uniquestate->tempContext);
/* clean up tuple table */ /* clean up tuple table */
ExecClearTuple(uniquestate->cstate.cs_ResultTupleSlot); ExecClearTuple(node->ps.ps_ResultTupleSlot);
if (uniquestate->priorTuple != NULL) if (node->priorTuple != NULL)
{ {
heap_freetuple(uniquestate->priorTuple); heap_freetuple(node->priorTuple);
uniquestate->priorTuple = NULL; node->priorTuple = NULL;
} }
ExecEndNode(outerPlanState(node));
MemoryContextDelete(node->tempContext);
} }
void void
ExecReScanUnique(Unique *node, ExprContext *exprCtxt, Plan *parent) ExecReScanUnique(UniqueState *node, ExprContext *exprCtxt)
{ {
UniqueState *uniquestate = node->uniquestate; ExecClearTuple(node->ps.ps_ResultTupleSlot);
if (node->priorTuple != NULL)
ExecClearTuple(uniquestate->cstate.cs_ResultTupleSlot);
if (uniquestate->priorTuple != NULL)
{ {
heap_freetuple(uniquestate->priorTuple); heap_freetuple(node->priorTuple);
uniquestate->priorTuple = NULL; node->priorTuple = NULL;
} }
/* /*
* 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);
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.78 2002/11/13 00:39:47 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.79 2002/12/05 15:50:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -33,7 +33,7 @@ static int _SPI_connected = -1; ...@@ -33,7 +33,7 @@ static int _SPI_connected = -1;
static int _SPI_curid = -1; static int _SPI_curid = -1;
static int _SPI_execute(char *src, int tcount, _SPI_plan *plan); static int _SPI_execute(char *src, int tcount, _SPI_plan *plan);
static int _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount); static int _SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount);
static int _SPI_execute_plan(_SPI_plan *plan, static int _SPI_execute_plan(_SPI_plan *plan,
Datum *Values, char *Nulls, int tcount); Datum *Values, char *Nulls, int tcount);
...@@ -705,9 +705,8 @@ SPI_cursor_open(char *name, void *plan, Datum *Values, char *Nulls) ...@@ -705,9 +705,8 @@ SPI_cursor_open(char *name, void *plan, Datum *Values, char *Nulls)
List *ptlist = spiplan->ptlist; List *ptlist = spiplan->ptlist;
Query *queryTree; Query *queryTree;
Plan *planTree; Plan *planTree;
ParamListInfo paramLI;
QueryDesc *queryDesc; QueryDesc *queryDesc;
EState *eState;
TupleDesc attinfo;
MemoryContext oldcontext; MemoryContext oldcontext;
Portal portal; Portal portal;
char portalname[64]; char portalname[64];
...@@ -774,28 +773,21 @@ SPI_cursor_open(char *name, void *plan, Datum *Values, char *Nulls) ...@@ -774,28 +773,21 @@ SPI_cursor_open(char *name, void *plan, Datum *Values, char *Nulls)
queryTree->into->relname = pstrdup(name); queryTree->into->relname = pstrdup(name);
queryTree->isBinary = false; queryTree->isBinary = false;
/* Create the QueryDesc object and the executor state */ /* If the plan has parameters, set them up */
queryDesc = CreateQueryDesc(queryTree, planTree, SPI, NULL);
eState = CreateExecutorState();
/* If the plan has parameters, put them into the executor state */
if (spiplan->nargs > 0) if (spiplan->nargs > 0)
{ {
ParamListInfo paramLI;
paramLI = (ParamListInfo) palloc0((spiplan->nargs + 1) * paramLI = (ParamListInfo) palloc0((spiplan->nargs + 1) *
sizeof(ParamListInfoData)); sizeof(ParamListInfoData));
eState->es_param_list_info = paramLI; for (k = 0; k < spiplan->nargs; k++)
for (k = 0; k < spiplan->nargs; paramLI++, k++)
{ {
paramLI->kind = PARAM_NUM; paramLI[k].kind = PARAM_NUM;
paramLI->id = k + 1; paramLI[k].id = k + 1;
paramLI->isnull = (Nulls && Nulls[k] == 'n'); paramLI[k].isnull = (Nulls && Nulls[k] == 'n');
if (paramLI->isnull) if (paramLI[k].isnull)
{ {
/* nulls just copy */ /* nulls just copy */
paramLI->value = Values[k]; paramLI[k].value = Values[k];
} }
else else
{ {
...@@ -805,20 +797,24 @@ SPI_cursor_open(char *name, void *plan, Datum *Values, char *Nulls) ...@@ -805,20 +797,24 @@ SPI_cursor_open(char *name, void *plan, Datum *Values, char *Nulls)
get_typlenbyval(spiplan->argtypes[k], get_typlenbyval(spiplan->argtypes[k],
&paramTypLen, &paramTypByVal); &paramTypLen, &paramTypByVal);
paramLI->value = datumCopy(Values[k], paramLI[k].value = datumCopy(Values[k],
paramTypByVal, paramTypLen); paramTypByVal, paramTypLen);
} }
} }
paramLI->kind = PARAM_INVALID; paramLI[k].kind = PARAM_INVALID;
} }
else else
eState->es_param_list_info = NULL; paramLI = NULL;
/* Create the QueryDesc object */
queryDesc = CreateQueryDesc(queryTree, planTree, SPI, NULL,
paramLI, false);
/* Start the executor */ /* Start the executor */
attinfo = ExecutorStart(queryDesc, eState); ExecutorStart(queryDesc);
/* Put all the objects into the portal */ /* Arrange to shut down the executor if portal is dropped */
PortalSetQuery(portal, queryDesc, attinfo, eState, PortalCleanup); PortalSetQuery(portal, queryDesc, PortalCleanup);
/* Switch back to the callers memory context */ /* Switch back to the callers memory context */
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);
...@@ -1042,7 +1038,6 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan) ...@@ -1042,7 +1038,6 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
Plan *planTree; Plan *planTree;
bool canSetResult; bool canSetResult;
QueryDesc *qdesc; QueryDesc *qdesc;
EState *state;
planTree = pg_plan_query(queryTree); planTree = pg_plan_query(queryTree);
plan_list = lappend(plan_list, planTree); plan_list = lappend(plan_list, planTree);
...@@ -1089,9 +1084,9 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan) ...@@ -1089,9 +1084,9 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
else if (plan == NULL) else if (plan == NULL)
{ {
qdesc = CreateQueryDesc(queryTree, planTree, qdesc = CreateQueryDesc(queryTree, planTree,
canSetResult ? SPI : None, NULL); canSetResult ? SPI : None,
state = CreateExecutorState(); NULL, NULL, false);
res = _SPI_pquery(qdesc, state, canSetResult ? tcount : 0); res = _SPI_pquery(qdesc, true, canSetResult ? tcount : 0);
if (res < 0) if (res < 0)
return res; return res;
CommandCounterIncrement(); CommandCounterIncrement();
...@@ -1099,8 +1094,9 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan) ...@@ -1099,8 +1094,9 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
else else
{ {
qdesc = CreateQueryDesc(queryTree, planTree, qdesc = CreateQueryDesc(queryTree, planTree,
canSetResult ? SPI : None, NULL); canSetResult ? SPI : None,
res = _SPI_pquery(qdesc, NULL, 0); NULL, NULL, false);
res = _SPI_pquery(qdesc, false, 0);
if (res < 0) if (res < 0)
return res; return res;
} }
...@@ -1152,7 +1148,6 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount) ...@@ -1152,7 +1148,6 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount)
Plan *planTree; Plan *planTree;
bool canSetResult; bool canSetResult;
QueryDesc *qdesc; QueryDesc *qdesc;
EState *state;
planTree = lfirst(plan_list); planTree = lfirst(plan_list);
plan_list = lnext(plan_list); plan_list = lnext(plan_list);
...@@ -1183,30 +1178,31 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount) ...@@ -1183,30 +1178,31 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount)
} }
else else
{ {
qdesc = CreateQueryDesc(queryTree, planTree, ParamListInfo paramLI;
canSetResult ? SPI : None, NULL);
state = CreateExecutorState();
if (nargs > 0) if (nargs > 0)
{ {
ParamListInfo paramLI;
int k; int k;
paramLI = (ParamListInfo) paramLI = (ParamListInfo)
palloc0((nargs + 1) * sizeof(ParamListInfoData)); palloc0((nargs + 1) * sizeof(ParamListInfoData));
state->es_param_list_info = paramLI; for (k = 0; k < plan->nargs; k++)
for (k = 0; k < plan->nargs; paramLI++, k++)
{ {
paramLI->kind = PARAM_NUM; paramLI[k].kind = PARAM_NUM;
paramLI->id = k + 1; paramLI[k].id = k + 1;
paramLI->isnull = (Nulls && Nulls[k] == 'n'); paramLI[k].isnull = (Nulls && Nulls[k] == 'n');
paramLI->value = Values[k]; paramLI[k].value = Values[k];
} }
paramLI->kind = PARAM_INVALID; paramLI[k].kind = PARAM_INVALID;
} }
else else
state->es_param_list_info = NULL; paramLI = NULL;
res = _SPI_pquery(qdesc, state, canSetResult ? tcount : 0);
qdesc = CreateQueryDesc(queryTree, planTree,
canSetResult ? SPI : None,
NULL, paramLI, false);
res = _SPI_pquery(qdesc, true, canSetResult ? tcount : 0);
if (res < 0) if (res < 0)
return res; return res;
CommandCounterIncrement(); CommandCounterIncrement();
...@@ -1218,7 +1214,7 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount) ...@@ -1218,7 +1214,7 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount)
} }
static int static int
_SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount) _SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount)
{ {
Query *parseTree = queryDesc->parsetree; Query *parseTree = queryDesc->parsetree;
int operation = queryDesc->operation; int operation = queryDesc->operation;
...@@ -1262,7 +1258,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount) ...@@ -1262,7 +1258,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
return SPI_ERROR_OPUNKNOWN; return SPI_ERROR_OPUNKNOWN;
} }
if (state == NULL) /* plan preparation, don't execute */ if (!runit) /* plan preparation, don't execute */
return res; return res;
#ifdef SPI_EXECUTOR_STATS #ifdef SPI_EXECUTOR_STATS
...@@ -1270,20 +1266,20 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount) ...@@ -1270,20 +1266,20 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
ResetUsage(); ResetUsage();
#endif #endif
ExecutorStart(queryDesc, state); ExecutorStart(queryDesc);
/* /*
* Don't work currently --- need to rearrange callers so that we * Don't work currently --- need to rearrange callers so that we
* prepare the portal before doing CreateExecutorState() etc. See * prepare the portal before doing ExecutorStart() etc. See
* pquery.c for the correct order of operations. * pquery.c for the correct order of operations.
*/ */
if (isRetrieveIntoPortal) if (isRetrieveIntoPortal)
elog(FATAL, "SPI_select: retrieve into portal not implemented"); elog(FATAL, "SPI_select: retrieve into portal not implemented");
ExecutorRun(queryDesc, state, ForwardScanDirection, (long) tcount); ExecutorRun(queryDesc, ForwardScanDirection, (long) tcount);
_SPI_current->processed = state->es_processed; _SPI_current->processed = queryDesc->estate->es_processed;
save_lastoid = state->es_lastoid; save_lastoid = queryDesc->estate->es_lastoid;
if (operation == CMD_SELECT && queryDesc->dest == SPI) if (operation == CMD_SELECT && queryDesc->dest == SPI)
{ {
...@@ -1291,7 +1287,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount) ...@@ -1291,7 +1287,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
elog(FATAL, "SPI_select: # of processed tuples check failed"); elog(FATAL, "SPI_select: # of processed tuples check failed");
} }
ExecutorEnd(queryDesc, state); ExecutorEnd(queryDesc);
#ifdef SPI_EXECUTOR_STATS #ifdef SPI_EXECUTOR_STATS
if (ShowExecutorStats) if (ShowExecutorStats)
...@@ -1342,7 +1338,7 @@ _SPI_cursor_operation(Portal portal, bool forward, int count, ...@@ -1342,7 +1338,7 @@ _SPI_cursor_operation(Portal portal, bool forward, int count,
oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal)); oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
querydesc = PortalGetQueryDesc(portal); querydesc = PortalGetQueryDesc(portal);
estate = PortalGetState(portal); estate = querydesc->estate;
/* Save the queries command destination and set it to SPI (for fetch) */ /* Save the queries command destination and set it to SPI (for fetch) */
/* or None (for move) */ /* or None (for move) */
...@@ -1357,7 +1353,7 @@ _SPI_cursor_operation(Portal portal, bool forward, int count, ...@@ -1357,7 +1353,7 @@ _SPI_cursor_operation(Portal portal, bool forward, int count,
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 */
...@@ -1371,7 +1367,7 @@ _SPI_cursor_operation(Portal portal, bool forward, int count, ...@@ -1371,7 +1367,7 @@ _SPI_cursor_operation(Portal portal, bool forward, int count,
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 */
......
...@@ -3,27 +3,28 @@ ...@@ -3,27 +3,28 @@
* copyfuncs.c * copyfuncs.c
* Copy functions for Postgres tree nodes. * Copy functions for Postgres tree nodes.
* *
* NOTE: a general convention when copying or comparing plan nodes is * NOTE: we currently support copying all node types found in parse and
* that we ignore the executor state subnode. We do not need to look * plan trees. We do not support copying executor state trees; there
* at it because no current uses of copyObject() or equal() need to * is no need for that, and no point in maintaining all the code that
* deal with already-executing plan trees. By leaving the state subnodes * would be needed. We also do not support copying Path trees, mainly
* out, we avoid needing to write copy/compare routines for all the * because the circular linkages between RelOptInfo and Path nodes can't
* different executor state node types. * be handled easily in a simple depth-first traversal.
* *
* *
* 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
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.225 2002/11/30 05:21:01 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.226 2002/12/05 15:50:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres.h" #include "postgres.h"
#include "optimizer/clauses.h" #include "nodes/parsenodes.h"
#include "optimizer/planmain.h" #include "nodes/plannodes.h"
#include "nodes/relation.h"
#include "utils/datum.h" #include "utils/datum.h"
...@@ -58,15 +59,6 @@ ...@@ -58,15 +59,6 @@
memcpy(newnode->fldname, from->fldname, _size); \ memcpy(newnode->fldname, from->fldname, _size); \
} while (0) } while (0)
/* Special hack for fixing subplan lists of Plan nodes (ick) */
#define FIX_SUBPLAN_LINKS(subplanfldname, fldname) \
do { \
if (from->subplanfldname != NIL) \
newnode->subplanfldname = \
nconc(newnode->subplanfldname, \
pull_subplans((Node *) (newnode->fldname))); \
} while (0)
/* /*
* listCopy * listCopy
...@@ -119,19 +111,13 @@ CopyPlanFields(Plan *from, Plan *newnode) ...@@ -119,19 +111,13 @@ CopyPlanFields(Plan *from, Plan *newnode)
COPY_SCALAR_FIELD(total_cost); COPY_SCALAR_FIELD(total_cost);
COPY_SCALAR_FIELD(plan_rows); COPY_SCALAR_FIELD(plan_rows);
COPY_SCALAR_FIELD(plan_width); COPY_SCALAR_FIELD(plan_width);
/* execution state is NOT copied */
COPY_NODE_FIELD(targetlist); COPY_NODE_FIELD(targetlist);
COPY_NODE_FIELD(qual); COPY_NODE_FIELD(qual);
COPY_NODE_FIELD(lefttree); COPY_NODE_FIELD(lefttree);
COPY_NODE_FIELD(righttree); COPY_NODE_FIELD(righttree);
COPY_NODE_FIELD(initPlan);
COPY_INTLIST_FIELD(extParam); COPY_INTLIST_FIELD(extParam);
COPY_INTLIST_FIELD(locParam); COPY_INTLIST_FIELD(locParam);
COPY_INTLIST_FIELD(chgParam);
COPY_NODE_FIELD(initPlan);
/* subPlan list must point to subplans in the new subtree, not the old */
newnode->subPlan = NIL;
FIX_SUBPLAN_LINKS(subPlan, targetlist);
FIX_SUBPLAN_LINKS(subPlan, qual);
COPY_SCALAR_FIELD(nParamExec); COPY_SCALAR_FIELD(nParamExec);
} }
...@@ -170,9 +156,6 @@ _copyResult(Result *from) ...@@ -170,9 +156,6 @@ _copyResult(Result *from)
*/ */
COPY_NODE_FIELD(resconstantqual); COPY_NODE_FIELD(resconstantqual);
/* subPlan list must point to subplans in the new subtree, not the old */
FIX_SUBPLAN_LINKS(plan.subPlan, resconstantqual);
return newnode; return newnode;
} }
...@@ -266,10 +249,6 @@ _copyIndexScan(IndexScan *from) ...@@ -266,10 +249,6 @@ _copyIndexScan(IndexScan *from)
COPY_NODE_FIELD(indxqualorig); COPY_NODE_FIELD(indxqualorig);
COPY_SCALAR_FIELD(indxorderdir); COPY_SCALAR_FIELD(indxorderdir);
/* subPlan list must point to subplans in the new subtree, not the old */
FIX_SUBPLAN_LINKS(scan.plan.subPlan, indxqual);
FIX_SUBPLAN_LINKS(scan.plan.subPlan, indxqualorig);
return newnode; return newnode;
} }
...@@ -289,12 +268,8 @@ _copyTidScan(TidScan *from) ...@@ -289,12 +268,8 @@ _copyTidScan(TidScan *from)
/* /*
* copy remainder of node * copy remainder of node
*/ */
COPY_SCALAR_FIELD(needRescan);
COPY_NODE_FIELD(tideval); COPY_NODE_FIELD(tideval);
/* subPlan list must point to subplans in the new subtree, not the old */
FIX_SUBPLAN_LINKS(scan.plan.subPlan, tideval);
return newnode; return newnode;
} }
...@@ -348,9 +323,6 @@ CopyJoinFields(Join *from, Join *newnode) ...@@ -348,9 +323,6 @@ CopyJoinFields(Join *from, Join *newnode)
COPY_SCALAR_FIELD(jointype); COPY_SCALAR_FIELD(jointype);
COPY_NODE_FIELD(joinqual); COPY_NODE_FIELD(joinqual);
/* subPlan list must point to subplans in the new subtree, not the old */
FIX_SUBPLAN_LINKS(plan.subPlan, joinqual);
} }
...@@ -406,9 +378,6 @@ _copyMergeJoin(MergeJoin *from) ...@@ -406,9 +378,6 @@ _copyMergeJoin(MergeJoin *from)
*/ */
COPY_NODE_FIELD(mergeclauses); COPY_NODE_FIELD(mergeclauses);
/* subPlan list must point to subplans in the new subtree, not the old */
FIX_SUBPLAN_LINKS(join.plan.subPlan, mergeclauses);
return newnode; return newnode;
} }
...@@ -430,9 +399,6 @@ _copyHashJoin(HashJoin *from) ...@@ -430,9 +399,6 @@ _copyHashJoin(HashJoin *from)
*/ */
COPY_NODE_FIELD(hashclauses); COPY_NODE_FIELD(hashclauses);
/* subPlan list must point to subplans in the new subtree, not the old */
FIX_SUBPLAN_LINKS(join.plan.subPlan, hashclauses);
return newnode; return newnode;
} }
...@@ -531,12 +497,12 @@ _copyUnique(Unique *from) ...@@ -531,12 +497,12 @@ _copyUnique(Unique *from)
} }
/* /*
* _copySetOp * _copyHash
*/ */
static SetOp * static Hash *
_copySetOp(SetOp *from) _copyHash(Hash *from)
{ {
SetOp *newnode = makeNode(SetOp); Hash *newnode = makeNode(Hash);
/* /*
* copy node superclass fields * copy node superclass fields
...@@ -546,21 +512,18 @@ _copySetOp(SetOp *from) ...@@ -546,21 +512,18 @@ _copySetOp(SetOp *from)
/* /*
* copy remainder of node * copy remainder of node
*/ */
COPY_SCALAR_FIELD(cmd); COPY_NODE_FIELD(hashkeys);
COPY_SCALAR_FIELD(numCols);
COPY_POINTER_FIELD(dupColIdx, from->numCols * sizeof(AttrNumber));
COPY_SCALAR_FIELD(flagColIdx);
return newnode; return newnode;
} }
/* /*
* _copyLimit * _copySetOp
*/ */
static Limit * static SetOp *
_copyLimit(Limit *from) _copySetOp(SetOp *from)
{ {
Limit *newnode = makeNode(Limit); SetOp *newnode = makeNode(SetOp);
/* /*
* copy node superclass fields * copy node superclass fields
...@@ -570,19 +533,21 @@ _copyLimit(Limit *from) ...@@ -570,19 +533,21 @@ _copyLimit(Limit *from)
/* /*
* copy remainder of node * copy remainder of node
*/ */
COPY_NODE_FIELD(limitOffset); COPY_SCALAR_FIELD(cmd);
COPY_NODE_FIELD(limitCount); COPY_SCALAR_FIELD(numCols);
COPY_POINTER_FIELD(dupColIdx, from->numCols * sizeof(AttrNumber));
COPY_SCALAR_FIELD(flagColIdx);
return newnode; return newnode;
} }
/* /*
* _copyHash * _copyLimit
*/ */
static Hash * static Limit *
_copyHash(Hash *from) _copyLimit(Limit *from)
{ {
Hash *newnode = makeNode(Hash); Limit *newnode = makeNode(Limit);
/* /*
* copy node superclass fields * copy node superclass fields
...@@ -592,9 +557,8 @@ _copyHash(Hash *from) ...@@ -592,9 +557,8 @@ _copyHash(Hash *from)
/* /*
* copy remainder of node * copy remainder of node
*/ */
COPY_NODE_FIELD(hashkeys); COPY_NODE_FIELD(limitOffset);
COPY_NODE_FIELD(limitCount);
/* XXX could the hashkeys contain subplans? Not at present... */
return newnode; return newnode;
} }
...@@ -611,10 +575,6 @@ _copySubPlan(SubPlan *from) ...@@ -611,10 +575,6 @@ _copySubPlan(SubPlan *from)
COPY_INTLIST_FIELD(parParam); COPY_INTLIST_FIELD(parParam);
COPY_NODE_FIELD(sublink); COPY_NODE_FIELD(sublink);
/* do not copy execution state */
newnode->needShutdown = false;
newnode->curTuple = NULL;
return newnode; return newnode;
} }
...@@ -933,313 +893,11 @@ _copyArrayRef(ArrayRef *from) ...@@ -933,313 +893,11 @@ _copyArrayRef(ArrayRef *from)
/* **************************************************************** /* ****************************************************************
* relation.h copy functions * relation.h copy functions
* *
* XXX the code to copy RelOptInfo and Path nodes is really completely bogus, * We don't support copying RelOptInfo, IndexOptInfo, or Path nodes.
* because it makes no attempt to deal with multiple links from RelOptInfo * There are some subsidiary structs that are useful to copy, though.
* to Paths, nor with back-links from Paths to their parent RelOptInfo.
* Currently, since we never actually try to copy a RelOptInfo, this is okay.
* **************************************************************** * ****************************************************************
*/ */
/*
* _copyRelOptInfo
*/
static RelOptInfo *
_copyRelOptInfo(RelOptInfo *from)
{
RelOptInfo *newnode = makeNode(RelOptInfo);
COPY_SCALAR_FIELD(reloptkind);
COPY_INTLIST_FIELD(relids);
COPY_SCALAR_FIELD(rows);
COPY_SCALAR_FIELD(width);
COPY_NODE_FIELD(targetlist);
COPY_NODE_FIELD(pathlist);
/* XXX cheapest-path fields should point to members of pathlist? */
COPY_NODE_FIELD(cheapest_startup_path);
COPY_NODE_FIELD(cheapest_total_path);
COPY_SCALAR_FIELD(pruneable);
COPY_SCALAR_FIELD(rtekind);
COPY_NODE_FIELD(indexlist);
COPY_SCALAR_FIELD(pages);
COPY_SCALAR_FIELD(tuples);
COPY_NODE_FIELD(subplan);
COPY_SCALAR_FIELD(joinrti);
COPY_INTLIST_FIELD(joinrteids);
COPY_NODE_FIELD(baserestrictinfo);
COPY_SCALAR_FIELD(baserestrictcost);
COPY_INTLIST_FIELD(outerjoinset);
COPY_NODE_FIELD(joininfo);
COPY_INTLIST_FIELD(index_outer_relids);
COPY_NODE_FIELD(index_inner_paths);
return newnode;
}
/*
* _copyIndexOptInfo
*/
static IndexOptInfo *
_copyIndexOptInfo(IndexOptInfo *from)
{
IndexOptInfo *newnode = makeNode(IndexOptInfo);
COPY_SCALAR_FIELD(indexoid);
COPY_SCALAR_FIELD(pages);
COPY_SCALAR_FIELD(tuples);
COPY_SCALAR_FIELD(ncolumns);
COPY_SCALAR_FIELD(nkeys);
if (from->classlist)
{
/* copy the trailing zero too */
COPY_POINTER_FIELD(classlist, (from->ncolumns + 1) * sizeof(Oid));
}
if (from->indexkeys)
{
/* copy the trailing zero too */
COPY_POINTER_FIELD(indexkeys, (from->nkeys + 1) * sizeof(int));
}
if (from->ordering)
{
/* copy the trailing zero too */
COPY_POINTER_FIELD(ordering, (from->ncolumns + 1) * sizeof(Oid));
}
COPY_SCALAR_FIELD(relam);
COPY_SCALAR_FIELD(amcostestimate);
COPY_SCALAR_FIELD(indproc);
COPY_NODE_FIELD(indpred);
COPY_SCALAR_FIELD(unique);
COPY_INTLIST_FIELD(outer_relids);
COPY_NODE_FIELD(inner_paths);
return newnode;
}
/*
* CopyPathFields
*
* This function copies the fields of the Path node. It is used by
* all the copy functions for classes which inherit from Path.
*/
static void
CopyPathFields(Path *from, Path *newnode)
{
/*
* Modify the next line, since it causes the copying to cycle (i.e.
* the parent points right back here! -- JMH, 7/7/92. Old version:
* COPY_NODE_FIELD(parent);
*/
COPY_SCALAR_FIELD(parent);
COPY_SCALAR_FIELD(startup_cost);
COPY_SCALAR_FIELD(total_cost);
COPY_SCALAR_FIELD(pathtype);
COPY_NODE_FIELD(pathkeys);
}
/*
* _copyPath
*/
static Path *
_copyPath(Path *from)
{
Path *newnode = makeNode(Path);
CopyPathFields(from, newnode);
return newnode;
}
/*
* _copyIndexPath
*/
static IndexPath *
_copyIndexPath(IndexPath *from)
{
IndexPath *newnode = makeNode(IndexPath);
/*
* copy node superclass fields
*/
CopyPathFields((Path *) from, (Path *) newnode);
/*
* copy remainder of node
*/
COPY_NODE_FIELD(indexinfo);
COPY_NODE_FIELD(indexqual);
COPY_SCALAR_FIELD(indexscandir);
COPY_SCALAR_FIELD(rows);
return newnode;
}
/*
* _copyTidPath
*/
static TidPath *
_copyTidPath(TidPath *from)
{
TidPath *newnode = makeNode(TidPath);
/*
* copy node superclass fields
*/
CopyPathFields((Path *) from, (Path *) newnode);
/*
* copy remainder of node
*/
COPY_NODE_FIELD(tideval);
COPY_INTLIST_FIELD(unjoined_relids);
return newnode;
}
/*
* _copyAppendPath
*/
static AppendPath *
_copyAppendPath(AppendPath *from)
{
AppendPath *newnode = makeNode(AppendPath);
/*
* copy node superclass fields
*/
CopyPathFields((Path *) from, (Path *) newnode);
/*
* copy remainder of node
*/
COPY_NODE_FIELD(subpaths);
return newnode;
}
/*
* _copyResultPath
*/
static ResultPath *
_copyResultPath(ResultPath *from)
{
ResultPath *newnode = makeNode(ResultPath);
/*
* copy node superclass fields
*/
CopyPathFields((Path *) from, (Path *) newnode);
/*
* copy remainder of node
*/
COPY_NODE_FIELD(subpath);
COPY_NODE_FIELD(constantqual);
return newnode;
}
/*
* _copyMaterialPath
*/
static MaterialPath *
_copyMaterialPath(MaterialPath *from)
{
MaterialPath *newnode = makeNode(MaterialPath);
/*
* copy node superclass fields
*/
CopyPathFields((Path *) from, (Path *) newnode);
/*
* copy remainder of node
*/
COPY_NODE_FIELD(subpath);
return newnode;
}
/*
* CopyJoinPathFields
*
* This function copies the fields of the JoinPath node. It is used by
* all the copy functions for classes which inherit from JoinPath.
*/
static void
CopyJoinPathFields(JoinPath *from, JoinPath *newnode)
{
CopyPathFields((Path *) from, (Path *) newnode);
COPY_SCALAR_FIELD(jointype);
COPY_NODE_FIELD(outerjoinpath);
COPY_NODE_FIELD(innerjoinpath);
COPY_NODE_FIELD(joinrestrictinfo);
}
/*
* _copyNestPath
*/
static NestPath *
_copyNestPath(NestPath *from)
{
NestPath *newnode = makeNode(NestPath);
/*
* copy node superclass fields
*/
CopyJoinPathFields((JoinPath *) from, (JoinPath *) newnode);
return newnode;
}
/*
* _copyMergePath
*/
static MergePath *
_copyMergePath(MergePath *from)
{
MergePath *newnode = makeNode(MergePath);
/*
* copy node superclass fields
*/
CopyJoinPathFields((JoinPath *) from, (JoinPath *) newnode);
/*
* copy remainder of node
*/
COPY_NODE_FIELD(path_mergeclauses);
COPY_NODE_FIELD(outersortkeys);
COPY_NODE_FIELD(innersortkeys);
return newnode;
}
/*
* _copyHashPath
*/
static HashPath *
_copyHashPath(HashPath *from)
{
HashPath *newnode = makeNode(HashPath);
/*
* copy node superclass fields
*/
CopyJoinPathFields((JoinPath *) from, (JoinPath *) newnode);
/*
* copy remainder of node
*/
COPY_NODE_FIELD(path_hashclauses);
return newnode;
}
/* /*
* _copyPathKeyItem * _copyPathKeyItem
*/ */
...@@ -1301,21 +959,6 @@ _copyJoinInfo(JoinInfo *from) ...@@ -1301,21 +959,6 @@ _copyJoinInfo(JoinInfo *from)
return newnode; return newnode;
} }
/*
* _copyInnerIndexscanInfo
*/
static InnerIndexscanInfo *
_copyInnerIndexscanInfo(InnerIndexscanInfo *from)
{
InnerIndexscanInfo *newnode = makeNode(InnerIndexscanInfo);
COPY_INTLIST_FIELD(other_relids);
COPY_SCALAR_FIELD(isouterjoin);
COPY_NODE_FIELD(best_innerpath);
return newnode;
}
/* **************************************************************** /* ****************************************************************
* parsenodes.h copy functions * parsenodes.h copy functions
* **************************************************************** * ****************************************************************
...@@ -1737,7 +1380,8 @@ _copyQuery(Query *from) ...@@ -1737,7 +1380,8 @@ _copyQuery(Query *from)
/* /*
* We do not copy the planner internal fields: base_rel_list, * We do not copy the planner internal fields: base_rel_list,
* other_rel_list, join_rel_list, equi_key_list, query_pathkeys, * other_rel_list, join_rel_list, equi_key_list, query_pathkeys,
* hasJoinRTEs. Not entirely clear if this is right? * hasJoinRTEs. That would get us into copying RelOptInfo/Path
* trees, which we don't want to do.
*/ */
return newnode; return newnode;
...@@ -2683,15 +2327,15 @@ copyObject(void *from) ...@@ -2683,15 +2327,15 @@ copyObject(void *from)
case T_Unique: case T_Unique:
retval = _copyUnique(from); retval = _copyUnique(from);
break; break;
case T_Hash:
retval = _copyHash(from);
break;
case T_SetOp: case T_SetOp:
retval = _copySetOp(from); retval = _copySetOp(from);
break; break;
case T_Limit: case T_Limit:
retval = _copyLimit(from); retval = _copyLimit(from);
break; break;
case T_Hash:
retval = _copyHash(from);
break;
case T_SubPlan: case T_SubPlan:
retval = _copySubPlan(from); retval = _copySubPlan(from);
break; break;
...@@ -2757,39 +2401,6 @@ copyObject(void *from) ...@@ -2757,39 +2401,6 @@ copyObject(void *from)
/* /*
* RELATION NODES * RELATION NODES
*/ */
case T_RelOptInfo:
retval = _copyRelOptInfo(from);
break;
case T_IndexOptInfo:
retval = _copyIndexOptInfo(from);
break;
case T_Path:
retval = _copyPath(from);
break;
case T_IndexPath:
retval = _copyIndexPath(from);
break;
case T_TidPath:
retval = _copyTidPath(from);
break;
case T_AppendPath:
retval = _copyAppendPath(from);
break;
case T_ResultPath:
retval = _copyResultPath(from);
break;
case T_MaterialPath:
retval = _copyMaterialPath(from);
break;
case T_NestPath:
retval = _copyNestPath(from);
break;
case T_MergePath:
retval = _copyMergePath(from);
break;
case T_HashPath:
retval = _copyHashPath(from);
break;
case T_PathKeyItem: case T_PathKeyItem:
retval = _copyPathKeyItem(from); retval = _copyPathKeyItem(from);
break; break;
...@@ -2799,9 +2410,6 @@ copyObject(void *from) ...@@ -2799,9 +2410,6 @@ copyObject(void *from)
case T_JoinInfo: case T_JoinInfo:
retval = _copyJoinInfo(from); retval = _copyJoinInfo(from);
break; break;
case T_InnerIndexscanInfo:
retval = _copyInnerIndexscanInfo(from);
break;
/* /*
* VALUE NODES * VALUE NODES
......
...@@ -3,30 +3,30 @@ ...@@ -3,30 +3,30 @@
* equalfuncs.c * equalfuncs.c
* Equality functions to compare node trees. * Equality functions to compare node trees.
* *
* NOTE: a general convention when copying or comparing plan nodes is * NOTE: we currently support comparing all node types found in parse
* that we ignore the executor state subnode. We do not need to look * trees. We do not support comparing executor state trees; there
* at it because no current uses of copyObject() or equal() need to * is no need for that, and no point in maintaining all the code that
* deal with already-executing plan trees. By leaving the state subnodes * would be needed. We also do not support comparing Path trees, mainly
* out, we avoid needing to write copy/compare routines for all the * because the circular linkages between RelOptInfo and Path nodes can't
* different executor state node types. * be handled easily in a simple depth-first traversal.
* *
* Currently, in fact, equal() doesn't know how to compare Plan nodes * Currently, in fact, equal() doesn't know how to compare Plan trees
* at all, let alone their executor-state subnodes. This will probably * either. This might need to be fixed someday.
* need to be fixed someday, but presently there is no need to compare
* plan trees.
* *
* *
* 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
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.170 2002/11/30 05:21:01 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.171 2002/12/05 15:50:34 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres.h" #include "postgres.h"
#include "nodes/params.h"
#include "nodes/parsenodes.h"
#include "nodes/plannodes.h" #include "nodes/plannodes.h"
#include "nodes/relation.h" #include "nodes/relation.h"
#include "utils/datum.h" #include "utils/datum.h"
...@@ -369,147 +369,6 @@ _equalSubPlan(SubPlan *a, SubPlan *b) ...@@ -369,147 +369,6 @@ _equalSubPlan(SubPlan *a, SubPlan *b)
* Stuff from relation.h * Stuff from relation.h
*/ */
static bool
_equalRelOptInfo(RelOptInfo *a, RelOptInfo *b)
{
/*
* We treat RelOptInfos as equal if they refer to the same base rels
* joined in the same order. Is this appropriate/sufficient?
*/
COMPARE_INTLIST_FIELD(relids);
return true;
}
static bool
_equalIndexOptInfo(IndexOptInfo *a, IndexOptInfo *b)
{
/*
* We treat IndexOptInfos as equal if they refer to the same index. Is
* this sufficient?
*/
COMPARE_SCALAR_FIELD(indexoid);
return true;
}
static bool
_equalPath(Path *a, Path *b)
{
/* This is safe only because _equalRelOptInfo is incomplete... */
COMPARE_NODE_FIELD(parent);
/*
* do not check path costs, since they may not be set yet, and being
* float values there are roundoff error issues anyway...
*/
COMPARE_SCALAR_FIELD(pathtype);
COMPARE_NODE_FIELD(pathkeys);
return true;
}
static bool
_equalIndexPath(IndexPath *a, IndexPath *b)
{
if (!_equalPath((Path *) a, (Path *) b))
return false;
COMPARE_NODE_FIELD(indexinfo);
COMPARE_NODE_FIELD(indexqual);
COMPARE_SCALAR_FIELD(indexscandir);
/*
* Skip 'rows' because of possibility of floating-point roundoff
* error. It should be derivable from the other fields anyway.
*/
return true;
}
static bool
_equalTidPath(TidPath *a, TidPath *b)
{
if (!_equalPath((Path *) a, (Path *) b))
return false;
COMPARE_NODE_FIELD(tideval);
COMPARE_INTLIST_FIELD(unjoined_relids);
return true;
}
static bool
_equalAppendPath(AppendPath *a, AppendPath *b)
{
if (!_equalPath((Path *) a, (Path *) b))
return false;
COMPARE_NODE_FIELD(subpaths);
return true;
}
static bool
_equalResultPath(ResultPath *a, ResultPath *b)
{
if (!_equalPath((Path *) a, (Path *) b))
return false;
COMPARE_NODE_FIELD(subpath);
COMPARE_NODE_FIELD(constantqual);
return true;
}
static bool
_equalMaterialPath(MaterialPath *a, MaterialPath *b)
{
if (!_equalPath((Path *) a, (Path *) b))
return false;
COMPARE_NODE_FIELD(subpath);
return true;
}
static bool
_equalJoinPath(JoinPath *a, JoinPath *b)
{
if (!_equalPath((Path *) a, (Path *) b))
return false;
COMPARE_SCALAR_FIELD(jointype);
COMPARE_NODE_FIELD(outerjoinpath);
COMPARE_NODE_FIELD(innerjoinpath);
COMPARE_NODE_FIELD(joinrestrictinfo);
return true;
}
static bool
_equalNestPath(NestPath *a, NestPath *b)
{
if (!_equalJoinPath((JoinPath *) a, (JoinPath *) b))
return false;
return true;
}
static bool
_equalMergePath(MergePath *a, MergePath *b)
{
if (!_equalJoinPath((JoinPath *) a, (JoinPath *) b))
return false;
COMPARE_NODE_FIELD(path_mergeclauses);
COMPARE_NODE_FIELD(outersortkeys);
COMPARE_NODE_FIELD(innersortkeys);
return true;
}
static bool
_equalHashPath(HashPath *a, HashPath *b)
{
if (!_equalJoinPath((JoinPath *) a, (JoinPath *) b))
return false;
COMPARE_NODE_FIELD(path_hashclauses);
return true;
}
static bool static bool
_equalPathKeyItem(PathKeyItem *a, PathKeyItem *b) _equalPathKeyItem(PathKeyItem *a, PathKeyItem *b)
{ {
...@@ -547,16 +406,6 @@ _equalJoinInfo(JoinInfo *a, JoinInfo *b) ...@@ -547,16 +406,6 @@ _equalJoinInfo(JoinInfo *a, JoinInfo *b)
return true; return true;
} }
static bool
_equalInnerIndexscanInfo(InnerIndexscanInfo *a, InnerIndexscanInfo *b)
{
COMPARE_INTLIST_FIELD(other_relids);
COMPARE_SCALAR_FIELD(isouterjoin);
COMPARE_NODE_FIELD(best_innerpath);
return true;
}
/* /*
* Stuff from parsenodes.h * Stuff from parsenodes.h
...@@ -1711,39 +1560,6 @@ equal(void *a, void *b) ...@@ -1711,39 +1560,6 @@ equal(void *a, void *b)
retval = _equalJoinExpr(a, b); retval = _equalJoinExpr(a, b);
break; break;
case T_RelOptInfo:
retval = _equalRelOptInfo(a, b);
break;
case T_IndexOptInfo:
retval = _equalIndexOptInfo(a, b);
break;
case T_Path:
retval = _equalPath(a, b);
break;
case T_IndexPath:
retval = _equalIndexPath(a, b);
break;
case T_TidPath:
retval = _equalTidPath(a, b);
break;
case T_AppendPath:
retval = _equalAppendPath(a, b);
break;
case T_ResultPath:
retval = _equalResultPath(a, b);
break;
case T_MaterialPath:
retval = _equalMaterialPath(a, b);
break;
case T_NestPath:
retval = _equalNestPath(a, b);
break;
case T_MergePath:
retval = _equalMergePath(a, b);
break;
case T_HashPath:
retval = _equalHashPath(a, b);
break;
case T_PathKeyItem: case T_PathKeyItem:
retval = _equalPathKeyItem(a, b); retval = _equalPathKeyItem(a, b);
break; break;
...@@ -1753,9 +1569,6 @@ equal(void *a, void *b) ...@@ -1753,9 +1569,6 @@ equal(void *a, void *b)
case T_JoinInfo: case T_JoinInfo:
retval = _equalJoinInfo(a, b); retval = _equalJoinInfo(a, b);
break; break;
case T_InnerIndexscanInfo:
retval = _equalInnerIndexscanInfo(a, b);
break;
case T_List: case T_List:
{ {
......
...@@ -8,13 +8,13 @@ ...@@ -8,13 +8,13 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.185 2002/11/30 05:21:02 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.186 2002/12/05 15:50:35 tgl Exp $
* *
* NOTES * NOTES
* Every node type that can appear in stored rules' parsetrees *must* * Every node type that can appear in stored rules' parsetrees *must*
* have an output function defined here (as well as an input function * have an output function defined here (as well as an input function
* in readfuncs.c). For use in debugging, we also provide output * in readfuncs.c). For use in debugging, we also provide output
* functions for nodes that appear in raw parsetrees and plan trees. * functions for nodes that appear in raw parsetrees, path, and plan trees.
* These nodes however need not have input functions. * These nodes however need not have input functions.
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
...@@ -24,10 +24,8 @@ ...@@ -24,10 +24,8 @@
#include <ctype.h> #include <ctype.h>
#include "lib/stringinfo.h" #include "lib/stringinfo.h"
#include "nodes/nodes.h"
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
#include "nodes/plannodes.h" #include "nodes/plannodes.h"
#include "nodes/primnodes.h"
#include "nodes/relation.h" #include "nodes/relation.h"
#include "parser/parse.h" #include "parser/parse.h"
#include "utils/datum.h" #include "utils/datum.h"
...@@ -385,11 +383,9 @@ _outPlanInfo(StringInfo str, Plan *node) ...@@ -385,11 +383,9 @@ _outPlanInfo(StringInfo str, Plan *node)
WRITE_NODE_FIELD(qual); WRITE_NODE_FIELD(qual);
WRITE_NODE_FIELD(lefttree); WRITE_NODE_FIELD(lefttree);
WRITE_NODE_FIELD(righttree); WRITE_NODE_FIELD(righttree);
WRITE_NODE_FIELD(initPlan);
WRITE_INTLIST_FIELD(extParam); WRITE_INTLIST_FIELD(extParam);
WRITE_INTLIST_FIELD(locParam); WRITE_INTLIST_FIELD(locParam);
/* chgParam is execution state too */
WRITE_NODE_FIELD(initPlan);
/* we don't write subPlan; reader must reconstruct list */
WRITE_INT_FIELD(nParamExec); WRITE_INT_FIELD(nParamExec);
} }
...@@ -482,7 +478,6 @@ _outTidScan(StringInfo str, TidScan *node) ...@@ -482,7 +478,6 @@ _outTidScan(StringInfo str, TidScan *node)
_outScanInfo(str, (Scan *) node); _outScanInfo(str, (Scan *) node);
WRITE_BOOL_FIELD(needRescan);
WRITE_NODE_FIELD(tideval); WRITE_NODE_FIELD(tideval);
} }
...@@ -930,6 +925,8 @@ _outRangeTblEntry(StringInfo str, RangeTblEntry *node) ...@@ -930,6 +925,8 @@ _outRangeTblEntry(StringInfo str, RangeTblEntry *node)
/* /*
* print the basic stuff of all nodes that inherit from Path * print the basic stuff of all nodes that inherit from Path
*
* Note we do NOT print the parent, else we'd be in infinite recursion
*/ */
static void static void
_outPathInfo(StringInfo str, Path *node) _outPathInfo(StringInfo str, Path *node)
...@@ -986,7 +983,6 @@ _outTidPath(StringInfo str, TidPath *node) ...@@ -986,7 +983,6 @@ _outTidPath(StringInfo str, TidPath *node)
_outPathInfo(str, (Path *) node); _outPathInfo(str, (Path *) node);
WRITE_NODE_FIELD(tideval); WRITE_NODE_FIELD(tideval);
WRITE_INTLIST_FIELD(unjoined_relids);
} }
static void static void
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.126 2002/11/30 05:21:02 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.127 2002/12/05 15:50:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -602,9 +602,6 @@ create_tidscan_plan(TidPath *best_path, List *tlist, List *scan_clauses) ...@@ -602,9 +602,6 @@ create_tidscan_plan(TidPath *best_path, List *tlist, List *scan_clauses)
scan_relid, scan_relid,
best_path->tideval); best_path->tideval);
if (best_path->unjoined_relids)
scan_plan->needRescan = true;
copy_path_costsize(&scan_plan->scan.plan, &best_path->path); copy_path_costsize(&scan_plan->scan.plan, &best_path->path);
return scan_plan; return scan_plan;
...@@ -1302,13 +1299,11 @@ make_seqscan(List *qptlist, ...@@ -1302,13 +1299,11 @@ make_seqscan(List *qptlist,
Plan *plan = &node->plan; Plan *plan = &node->plan;
/* cost should be inserted by caller */ /* cost should be inserted by caller */
plan->state = (EState *) NULL;
plan->targetlist = qptlist; plan->targetlist = qptlist;
plan->qual = qpqual; plan->qual = qpqual;
plan->lefttree = NULL; plan->lefttree = NULL;
plan->righttree = NULL; plan->righttree = NULL;
node->scanrelid = scanrelid; node->scanrelid = scanrelid;
node->scanstate = (CommonScanState *) NULL;
return node; return node;
} }
...@@ -1326,7 +1321,6 @@ make_indexscan(List *qptlist, ...@@ -1326,7 +1321,6 @@ make_indexscan(List *qptlist,
Plan *plan = &node->scan.plan; Plan *plan = &node->scan.plan;
/* cost should be inserted by caller */ /* cost should be inserted by caller */
plan->state = (EState *) NULL;
plan->targetlist = qptlist; plan->targetlist = qptlist;
plan->qual = qpqual; plan->qual = qpqual;
plan->lefttree = NULL; plan->lefttree = NULL;
...@@ -1336,7 +1330,6 @@ make_indexscan(List *qptlist, ...@@ -1336,7 +1330,6 @@ make_indexscan(List *qptlist,
node->indxqual = indxqual; node->indxqual = indxqual;
node->indxqualorig = indxqualorig; node->indxqualorig = indxqualorig;
node->indxorderdir = indexscandir; node->indxorderdir = indexscandir;
node->scan.scanstate = (CommonScanState *) NULL;
return node; return node;
} }
...@@ -1351,16 +1344,12 @@ make_tidscan(List *qptlist, ...@@ -1351,16 +1344,12 @@ make_tidscan(List *qptlist,
Plan *plan = &node->scan.plan; Plan *plan = &node->scan.plan;
/* cost should be inserted by caller */ /* cost should be inserted by caller */
plan->state = (EState *) NULL;
plan->targetlist = qptlist; plan->targetlist = qptlist;
plan->qual = qpqual; plan->qual = qpqual;
plan->lefttree = NULL; plan->lefttree = NULL;
plan->righttree = NULL; plan->righttree = NULL;
node->scan.scanrelid = scanrelid; node->scan.scanrelid = scanrelid;
node->tideval = copyObject(tideval); /* XXX do we really need a node->tideval = tideval;
* copy? */
node->needRescan = false;
node->scan.scanstate = (CommonScanState *) NULL;
return node; return node;
} }
...@@ -1375,14 +1364,12 @@ make_subqueryscan(List *qptlist, ...@@ -1375,14 +1364,12 @@ make_subqueryscan(List *qptlist,
Plan *plan = &node->scan.plan; Plan *plan = &node->scan.plan;
copy_plan_costsize(plan, subplan); copy_plan_costsize(plan, subplan);
plan->state = (EState *) NULL;
plan->targetlist = qptlist; plan->targetlist = qptlist;
plan->qual = qpqual; plan->qual = qpqual;
plan->lefttree = NULL; plan->lefttree = NULL;
plan->righttree = NULL; plan->righttree = NULL;
node->scan.scanrelid = scanrelid; node->scan.scanrelid = scanrelid;
node->subplan = subplan; node->subplan = subplan;
node->scan.scanstate = (CommonScanState *) NULL;
return node; return node;
} }
...@@ -1396,13 +1383,11 @@ make_functionscan(List *qptlist, ...@@ -1396,13 +1383,11 @@ make_functionscan(List *qptlist,
Plan *plan = &node->scan.plan; Plan *plan = &node->scan.plan;
/* cost should be inserted by caller */ /* cost should be inserted by caller */
plan->state = (EState *) NULL;
plan->targetlist = qptlist; plan->targetlist = qptlist;
plan->qual = qpqual; plan->qual = qpqual;
plan->lefttree = NULL; plan->lefttree = NULL;
plan->righttree = NULL; plan->righttree = NULL;
node->scan.scanrelid = scanrelid; node->scan.scanrelid = scanrelid;
node->scan.scanstate = (CommonScanState *) NULL;
return node; return node;
} }
...@@ -1430,7 +1415,6 @@ make_append(List *appendplans, bool isTarget, List *tlist) ...@@ -1430,7 +1415,6 @@ make_append(List *appendplans, bool isTarget, List *tlist)
if (plan->plan_width < subplan->plan_width) if (plan->plan_width < subplan->plan_width)
plan->plan_width = subplan->plan_width; plan->plan_width = subplan->plan_width;
} }
plan->state = (EState *) NULL;
plan->targetlist = tlist; plan->targetlist = tlist;
plan->qual = NIL; plan->qual = NIL;
plan->lefttree = NULL; plan->lefttree = NULL;
...@@ -1453,7 +1437,6 @@ make_nestloop(List *tlist, ...@@ -1453,7 +1437,6 @@ make_nestloop(List *tlist,
Plan *plan = &node->join.plan; Plan *plan = &node->join.plan;
/* cost should be inserted by caller */ /* cost should be inserted by caller */
plan->state = (EState *) NULL;
plan->targetlist = tlist; plan->targetlist = tlist;
plan->qual = otherclauses; plan->qual = otherclauses;
plan->lefttree = lefttree; plan->lefttree = lefttree;
...@@ -1477,7 +1460,6 @@ make_hashjoin(List *tlist, ...@@ -1477,7 +1460,6 @@ make_hashjoin(List *tlist,
Plan *plan = &node->join.plan; Plan *plan = &node->join.plan;
/* cost should be inserted by caller */ /* cost should be inserted by caller */
plan->state = (EState *) NULL;
plan->targetlist = tlist; plan->targetlist = tlist;
plan->qual = otherclauses; plan->qual = otherclauses;
plan->lefttree = lefttree; plan->lefttree = lefttree;
...@@ -1502,7 +1484,6 @@ make_hash(List *tlist, List *hashkeys, Plan *lefttree) ...@@ -1502,7 +1484,6 @@ make_hash(List *tlist, List *hashkeys, Plan *lefttree)
* input plan; this only affects EXPLAIN display not decisions. * input plan; this only affects EXPLAIN display not decisions.
*/ */
plan->startup_cost = plan->total_cost; plan->startup_cost = plan->total_cost;
plan->state = (EState *) NULL;
plan->targetlist = tlist; plan->targetlist = tlist;
plan->qual = NULL; plan->qual = NULL;
plan->lefttree = lefttree; plan->lefttree = lefttree;
...@@ -1525,7 +1506,6 @@ make_mergejoin(List *tlist, ...@@ -1525,7 +1506,6 @@ make_mergejoin(List *tlist,
Plan *plan = &node->join.plan; Plan *plan = &node->join.plan;
/* cost should be inserted by caller */ /* cost should be inserted by caller */
plan->state = (EState *) NULL;
plan->targetlist = tlist; plan->targetlist = tlist;
plan->qual = otherclauses; plan->qual = otherclauses;
plan->lefttree = lefttree; plan->lefttree = lefttree;
...@@ -1557,7 +1537,6 @@ make_sort(Query *root, List *tlist, Plan *lefttree, int keycount) ...@@ -1557,7 +1537,6 @@ make_sort(Query *root, List *tlist, Plan *lefttree, int keycount)
lefttree->plan_width); lefttree->plan_width);
plan->startup_cost = sort_path.startup_cost; plan->startup_cost = sort_path.startup_cost;
plan->total_cost = sort_path.total_cost; plan->total_cost = sort_path.total_cost;
plan->state = (EState *) NULL;
plan->targetlist = tlist; plan->targetlist = tlist;
plan->qual = NIL; plan->qual = NIL;
plan->lefttree = lefttree; plan->lefttree = lefttree;
...@@ -1646,7 +1625,6 @@ make_material(List *tlist, Plan *lefttree) ...@@ -1646,7 +1625,6 @@ make_material(List *tlist, Plan *lefttree)
Plan *plan = &node->plan; Plan *plan = &node->plan;
/* cost should be inserted by caller */ /* cost should be inserted by caller */
plan->state = (EState *) NULL;
plan->targetlist = tlist; plan->targetlist = tlist;
plan->qual = NIL; plan->qual = NIL;
plan->lefttree = lefttree; plan->lefttree = lefttree;
...@@ -1690,7 +1668,6 @@ make_agg(Query *root, List *tlist, List *qual, ...@@ -1690,7 +1668,6 @@ make_agg(Query *root, List *tlist, List *qual,
else else
plan->plan_rows = numGroups; plan->plan_rows = numGroups;
plan->state = (EState *) NULL;
plan->qual = qual; plan->qual = qual;
plan->targetlist = tlist; plan->targetlist = tlist;
plan->lefttree = lefttree; plan->lefttree = lefttree;
...@@ -1726,7 +1703,6 @@ make_group(Query *root, ...@@ -1726,7 +1703,6 @@ make_group(Query *root,
/* One output tuple per estimated result group */ /* One output tuple per estimated result group */
plan->plan_rows = numGroups; plan->plan_rows = numGroups;
plan->state = (EState *) NULL;
plan->qual = NULL; plan->qual = NULL;
plan->targetlist = tlist; plan->targetlist = tlist;
plan->lefttree = lefttree; plan->lefttree = lefttree;
...@@ -1765,7 +1741,6 @@ make_unique(List *tlist, Plan *lefttree, List *distinctList) ...@@ -1765,7 +1741,6 @@ make_unique(List *tlist, Plan *lefttree, List *distinctList)
* if he has a better idea. * if he has a better idea.
*/ */
plan->state = (EState *) NULL;
plan->targetlist = tlist; plan->targetlist = tlist;
plan->qual = NIL; plan->qual = NIL;
plan->lefttree = lefttree; plan->lefttree = lefttree;
...@@ -1824,7 +1799,6 @@ make_setop(SetOpCmd cmd, List *tlist, Plan *lefttree, ...@@ -1824,7 +1799,6 @@ make_setop(SetOpCmd cmd, List *tlist, Plan *lefttree,
if (plan->plan_rows < 1) if (plan->plan_rows < 1)
plan->plan_rows = 1; plan->plan_rows = 1;
plan->state = (EState *) NULL;
plan->targetlist = tlist; plan->targetlist = tlist;
plan->qual = NIL; plan->qual = NIL;
plan->lefttree = lefttree; plan->lefttree = lefttree;
...@@ -1905,7 +1879,6 @@ make_limit(List *tlist, Plan *lefttree, ...@@ -1905,7 +1879,6 @@ make_limit(List *tlist, Plan *lefttree,
} }
} }
plan->state = (EState *) NULL;
plan->targetlist = tlist; plan->targetlist = tlist;
plan->qual = NIL; plan->qual = NIL;
plan->lefttree = lefttree; plan->lefttree = lefttree;
...@@ -1935,13 +1908,11 @@ make_result(List *tlist, ...@@ -1935,13 +1908,11 @@ make_result(List *tlist,
plan->plan_width = 0; /* XXX try to be smarter? */ plan->plan_width = 0; /* XXX try to be smarter? */
} }
plan->state = (EState *) NULL;
plan->targetlist = tlist; plan->targetlist = tlist;
plan->qual = NIL; plan->qual = NIL;
plan->lefttree = subplan; plan->lefttree = subplan;
plan->righttree = NULL; plan->righttree = NULL;
node->resconstantqual = resconstantqual; node->resconstantqual = resconstantqual;
node->resstate = NULL;
return node; return node;
} }
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.83 2002/11/30 21:25:04 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.84 2002/12/05 15:50:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -41,6 +41,7 @@ typedef struct ...@@ -41,6 +41,7 @@ typedef struct
} replace_vars_with_subplan_refs_context; } replace_vars_with_subplan_refs_context;
static void fix_expr_references(Plan *plan, Node *node); static void fix_expr_references(Plan *plan, Node *node);
static bool fix_expr_references_walker(Node *node, void *context);
static void set_join_references(Join *join, List *rtable); static void set_join_references(Join *join, List *rtable);
static void set_uppernode_references(Plan *plan, Index subvarno); static void set_uppernode_references(Plan *plan, Index subvarno);
static Node *join_references_mutator(Node *node, static Node *join_references_mutator(Node *node,
...@@ -66,8 +67,6 @@ static bool fix_opids_walker(Node *node, void *context); ...@@ -66,8 +67,6 @@ static bool fix_opids_walker(Node *node, void *context);
* for the convenience of the executor. We update Vars in upper plan nodes * for the convenience of the executor. We update Vars in upper plan nodes
* to refer to the outputs of their subplans, and we compute regproc OIDs * to refer to the outputs of their subplans, and we compute regproc OIDs
* for operators (ie, we look up the function that implements each op). * for operators (ie, we look up the function that implements each op).
* We must also build lists of all the subplan nodes present in each
* plan node's expression trees.
* *
* set_plan_references recursively traverses the whole plan tree. * set_plan_references recursively traverses the whole plan tree.
* *
...@@ -81,12 +80,6 @@ set_plan_references(Plan *plan, List *rtable) ...@@ -81,12 +80,6 @@ set_plan_references(Plan *plan, List *rtable)
if (plan == NULL) if (plan == NULL)
return; return;
/*
* We must rebuild the plan's list of subplan nodes, since we are
* copying/mutating its expression trees.
*/
plan->subPlan = NIL;
/* /*
* Plan-type-specific fixes * Plan-type-specific fixes
*/ */
...@@ -107,6 +100,8 @@ set_plan_references(Plan *plan, List *rtable) ...@@ -107,6 +100,8 @@ set_plan_references(Plan *plan, List *rtable)
case T_TidScan: case T_TidScan:
fix_expr_references(plan, (Node *) plan->targetlist); fix_expr_references(plan, (Node *) plan->targetlist);
fix_expr_references(plan, (Node *) plan->qual); fix_expr_references(plan, (Node *) plan->qual);
fix_expr_references(plan,
(Node *) ((TidScan *) plan)->tideval);
break; break;
case T_SubqueryScan: case T_SubqueryScan:
{ {
...@@ -175,9 +170,9 @@ set_plan_references(Plan *plan, List *rtable) ...@@ -175,9 +170,9 @@ set_plan_references(Plan *plan, List *rtable)
* unmodified input tuples). The optimizer is lazy about * unmodified input tuples). The optimizer is lazy about
* creating really valid targetlists for them. Best to just * creating really valid targetlists for them. Best to just
* leave the targetlist alone. In particular, we do not want * leave the targetlist alone. In particular, we do not want
* to pull a subplan list for them, since we will likely end * to process subplans for them, since we will likely end
* up with duplicate list entries for subplans that also * up reprocessing subplans that also appear in lower levels
* appear in lower levels of the plan tree! * of the plan tree!
*/ */
break; break;
case T_Agg: case T_Agg:
...@@ -206,7 +201,7 @@ set_plan_references(Plan *plan, List *rtable) ...@@ -206,7 +201,7 @@ set_plan_references(Plan *plan, List *rtable)
* Append, like Sort et al, doesn't actually evaluate its * Append, like Sort et al, doesn't actually evaluate its
* targetlist or quals, and we haven't bothered to give it its * targetlist or quals, and we haven't bothered to give it its
* own tlist copy. So, don't fix targetlist/qual. But do * own tlist copy. So, don't fix targetlist/qual. But do
* recurse into subplans. * recurse into child plans.
*/ */
foreach(pl, ((Append *) plan)->appendplans) foreach(pl, ((Append *) plan)->appendplans)
set_plan_references((Plan *) lfirst(pl), rtable); set_plan_references((Plan *) lfirst(pl), rtable);
...@@ -218,24 +213,19 @@ set_plan_references(Plan *plan, List *rtable) ...@@ -218,24 +213,19 @@ set_plan_references(Plan *plan, List *rtable)
} }
/* /*
* Now recurse into subplans, if any * Now recurse into child plans and initplans, if any
* *
* NOTE: it is essential that we recurse into subplans AFTER we set * NOTE: it is essential that we recurse into child plans AFTER we set
* subplan references in this plan's tlist and quals. If we did the * subplan references in this plan's tlist and quals. If we did the
* reference-adjustments bottom-up, then we would fail to match this * reference-adjustments bottom-up, then we would fail to match this
* plan's var nodes against the already-modified nodes of the * plan's var nodes against the already-modified nodes of the
* subplans. * children. Fortunately, that consideration doesn't apply to SubPlan
* nodes; else we'd need two passes over the expression trees.
*/ */
set_plan_references(plan->lefttree, rtable); set_plan_references(plan->lefttree, rtable);
set_plan_references(plan->righttree, rtable); set_plan_references(plan->righttree, rtable);
foreach(pl, plan->initPlan)
{
SubPlan *sp = (SubPlan *) lfirst(pl);
Assert(IsA(sp, SubPlan)); foreach(pl, plan->initPlan)
set_plan_references(sp->plan, sp->rtable);
}
foreach(pl, plan->subPlan)
{ {
SubPlan *sp = (SubPlan *) lfirst(pl); SubPlan *sp = (SubPlan *) lfirst(pl);
...@@ -249,13 +239,38 @@ set_plan_references(Plan *plan, List *rtable) ...@@ -249,13 +239,38 @@ set_plan_references(Plan *plan, List *rtable)
* Do final cleanup on expressions (targetlists or quals). * Do final cleanup on expressions (targetlists or quals).
* *
* This consists of looking up operator opcode info for Oper nodes * This consists of looking up operator opcode info for Oper nodes
* and adding subplans to the Plan node's list of contained subplans. * and recursively performing set_plan_references on SubPlans.
*
* The Plan argument is currently unused, but might be needed again someday.
*/ */
static void static void
fix_expr_references(Plan *plan, Node *node) fix_expr_references(Plan *plan, Node *node)
{ {
fix_opids(node); /* This tree walk requires no special setup, so away we go... */
plan->subPlan = nconc(plan->subPlan, pull_subplans(node)); fix_expr_references_walker(node, NULL);
}
static bool
fix_expr_references_walker(Node *node, void *context)
{
if (node == NULL)
return false;
if (IsA(node, Expr))
{
Expr *expr = (Expr *) node;
if (expr->opType == OP_EXPR ||
expr->opType == DISTINCT_EXPR)
replace_opid((Oper *) expr->oper);
else if (expr->opType == SUBPLAN_EXPR)
{
SubPlan *sp = (SubPlan *) expr->oper;
Assert(IsA(sp, SubPlan));
set_plan_references(sp->plan, sp->rtable);
}
}
return expression_tree_walker(node, fix_expr_references_walker, context);
} }
/* /*
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.58 2002/11/30 05:21:03 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.59 2002/12/05 15:50:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "catalog/pg_operator.h" #include "catalog/pg_operator.h"
#include "catalog/pg_type.h" #include "catalog/pg_type.h"
#include "nodes/makefuncs.h" #include "nodes/makefuncs.h"
#include "nodes/params.h"
#include "optimizer/clauses.h" #include "optimizer/clauses.h"
#include "optimizer/cost.h" #include "optimizer/cost.h"
#include "optimizer/planmain.h" #include "optimizer/planmain.h"
...@@ -297,7 +298,7 @@ make_subplan(SubLink *slink) ...@@ -297,7 +298,7 @@ make_subplan(SubLink *slink)
switch (nodeTag(plan)) switch (nodeTag(plan))
{ {
case T_SeqScan: case T_SeqScan:
if (plan->initPlan || plan->subPlan) if (plan->initPlan)
use_material = true; use_material = true;
else else
{ {
...@@ -453,20 +454,13 @@ convert_sublink_opers(SubLink *slink, List *targetlist, ...@@ -453,20 +454,13 @@ convert_sublink_opers(SubLink *slink, List *targetlist,
} }
/* /*
* finalize_primnode: build lists of subplans and params appearing * finalize_primnode: build lists of params appearing
* in the given expression tree. NOTE: items are added to lists passed in, * in the given expression tree. NOTE: items are added to list passed in,
* so caller must initialize lists to NIL before first call! * so caller must initialize list to NIL before first call!
*
* Note: the subplan list that is constructed here and assigned to the
* plan's subPlan field will be replaced with an up-to-date list in
* set_plan_references(). We could almost dispense with building this
* subplan list at all; I believe the only place that uses it is the
* check in make_subplan to see whether a subselect has any subselects.
*/ */
typedef struct finalize_primnode_results typedef struct finalize_primnode_results
{ {
List *subplans; /* List of subplans found in expr */
List *paramids; /* List of PARAM_EXEC paramids found */ List *paramids; /* List of PARAM_EXEC paramids found */
} finalize_primnode_results; } finalize_primnode_results;
...@@ -491,8 +485,6 @@ finalize_primnode(Node *node, finalize_primnode_results *results) ...@@ -491,8 +485,6 @@ finalize_primnode(Node *node, finalize_primnode_results *results)
SubPlan *subplan = (SubPlan *) ((Expr *) node)->oper; SubPlan *subplan = (SubPlan *) ((Expr *) node)->oper;
List *lst; List *lst;
/* Add subplan to subplans list */
results->subplans = lappend(results->subplans, subplan);
/* Check extParam list for params to add to paramids */ /* Check extParam list for params to add to paramids */
foreach(lst, subplan->plan->extParam) foreach(lst, subplan->plan->extParam)
{ {
...@@ -595,18 +587,16 @@ SS_finalize_plan(Plan *plan, List *rtable) ...@@ -595,18 +587,16 @@ SS_finalize_plan(Plan *plan, List *rtable)
if (plan == NULL) if (plan == NULL)
return NIL; return NIL;
results.subplans = NIL; /* initialize lists to NIL */ results.paramids = NIL; /* initialize list to NIL */
results.paramids = NIL;
/* /*
* When we call finalize_primnode, results.paramids lists are * When we call finalize_primnode, results.paramids lists are
* automatically merged together. But when recursing to self, we have * automatically merged together. But when recursing to self, we have
* to do it the hard way. We want the paramids list to include params * to do it the hard way. We want the paramids list to include params
* in subplans as well as at this level. (We don't care about finding * in subplans as well as at this level.
* subplans of subplans, though.)
*/ */
/* Find params and subplans in targetlist and qual */ /* Find params in targetlist and qual */
finalize_primnode((Node *) plan->targetlist, &results); finalize_primnode((Node *) plan->targetlist, &results);
finalize_primnode((Node *) plan->qual, &results); finalize_primnode((Node *) plan->qual, &results);
...@@ -624,8 +614,7 @@ SS_finalize_plan(Plan *plan, List *rtable) ...@@ -624,8 +614,7 @@ SS_finalize_plan(Plan *plan, List *rtable)
/* /*
* we need not look at indxqualorig, since it will have the * we need not look at indxqualorig, since it will have the
* same param references as indxqual, and we aren't really * same param references as indxqual.
* concerned yet about having a complete subplan list.
*/ */
break; break;
...@@ -704,7 +693,7 @@ SS_finalize_plan(Plan *plan, List *rtable) ...@@ -704,7 +693,7 @@ SS_finalize_plan(Plan *plan, List *rtable)
nodeTag(plan)); nodeTag(plan));
} }
/* Process left and right subplans, if any */ /* Process left and right child plans, if any */
results.paramids = set_unioni(results.paramids, results.paramids = set_unioni(results.paramids,
SS_finalize_plan(plan->lefttree, SS_finalize_plan(plan->lefttree,
rtable)); rtable));
...@@ -712,7 +701,7 @@ SS_finalize_plan(Plan *plan, List *rtable) ...@@ -712,7 +701,7 @@ SS_finalize_plan(Plan *plan, List *rtable)
SS_finalize_plan(plan->righttree, SS_finalize_plan(plan->righttree,
rtable)); rtable));
/* Now we have all the paramids and subplans */ /* Now we have all the paramids */
foreach(lst, results.paramids) foreach(lst, results.paramids)
{ {
...@@ -733,7 +722,6 @@ SS_finalize_plan(Plan *plan, List *rtable) ...@@ -733,7 +722,6 @@ SS_finalize_plan(Plan *plan, List *rtable)
plan->extParam = extParam; plan->extParam = extParam;
plan->locParam = locParam; plan->locParam = locParam;
plan->subPlan = results.subplans;
return results.paramids; return results.paramids;
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.82 2002/11/30 05:21:03 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.83 2002/12/05 15:50:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -385,9 +385,7 @@ create_tidscan_path(Query *root, RelOptInfo *rel, List *tideval) ...@@ -385,9 +385,7 @@ create_tidscan_path(Query *root, RelOptInfo *rel, List *tideval)
pathnode->path.pathtype = T_TidScan; pathnode->path.pathtype = T_TidScan;
pathnode->path.parent = rel; pathnode->path.parent = rel;
pathnode->path.pathkeys = NIL; pathnode->path.pathkeys = NIL;
pathnode->tideval = copyObject(tideval); /* is copy really pathnode->tideval = tideval;
* necessary? */
pathnode->unjoined_relids = NIL;
cost_tidscan(&pathnode->path, root, rel, tideval); cost_tidscan(&pathnode->path, root, rel, tideval);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.56 2002/11/18 01:17:39 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/tcop/pquery.c,v 1.57 2002/12/05 15:50:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -23,15 +23,16 @@ ...@@ -23,15 +23,16 @@
#include "utils/ps_status.h" #include "utils/ps_status.h"
/* ---------------------------------------------------------------- /*
* CreateQueryDesc * CreateQueryDesc
* ----------------------------------------------------------------
*/ */
QueryDesc * QueryDesc *
CreateQueryDesc(Query *parsetree, CreateQueryDesc(Query *parsetree,
Plan *plantree, Plan *plantree,
CommandDest dest, CommandDest dest,
const char *portalName) const char *portalName,
ParamListInfo params,
bool doInstrument)
{ {
QueryDesc *qd = (QueryDesc *) palloc(sizeof(QueryDesc)); QueryDesc *qd = (QueryDesc *) palloc(sizeof(QueryDesc));
...@@ -40,54 +41,15 @@ CreateQueryDesc(Query *parsetree, ...@@ -40,54 +41,15 @@ CreateQueryDesc(Query *parsetree,
qd->plantree = plantree; /* plan */ qd->plantree = plantree; /* plan */
qd->dest = dest; /* output dest */ qd->dest = dest; /* output dest */
qd->portalName = portalName; /* name, if dest is a portal */ qd->portalName = portalName; /* name, if dest is a portal */
qd->tupDesc = NULL; /* until set by ExecutorStart */ qd->params = params; /* parameter values passed into query */
qd->doInstrument = doInstrument; /* instrumentation wanted? */
return qd;
}
/* ----------------------------------------------------------------
* CreateExecutorState
*
* Note: this may someday take parameters -cim 9/18/89
* ----------------------------------------------------------------
*/
EState *
CreateExecutorState(void)
{
EState *state;
/*
* create a new executor state
*/
state = makeNode(EState);
/*
* initialize the Executor State structure
*/
state->es_direction = ForwardScanDirection;
state->es_range_table = NIL;
state->es_result_relations = NULL;
state->es_num_result_relations = 0;
state->es_result_relation_info = NULL;
state->es_junkFilter = NULL;
state->es_into_relation_descriptor = NULL;
state->es_param_list_info = NULL;
state->es_param_exec_vals = NULL;
state->es_tupleTable = NULL;
state->es_query_cxt = CurrentMemoryContext;
state->es_per_tuple_exprcontext = NULL; /* null these fields until set by ExecutorStart */
qd->tupDesc = NULL;
qd->estate = NULL;
qd->planstate = NULL;
/* return qd;
* return the executor state structure
*/
return state;
} }
/* ---------------- /* ----------------
...@@ -147,8 +109,6 @@ ProcessQuery(Query *parsetree, ...@@ -147,8 +109,6 @@ ProcessQuery(Query *parsetree,
Portal portal = NULL; Portal portal = NULL;
MemoryContext oldContext = NULL; MemoryContext oldContext = NULL;
QueryDesc *queryDesc; QueryDesc *queryDesc;
EState *state;
TupleDesc attinfo;
/* /*
* Check for special-case destinations * Check for special-case destinations
...@@ -193,7 +153,7 @@ ProcessQuery(Query *parsetree, ...@@ -193,7 +153,7 @@ ProcessQuery(Query *parsetree,
/* /*
* We stay in portal's memory context for now, so that query desc, * We stay in portal's memory context for now, so that query desc,
* EState, and plan startup info are also allocated in the portal * exec state, and plan startup info are also allocated in the portal
* context. * context.
*/ */
} }
...@@ -201,17 +161,12 @@ ProcessQuery(Query *parsetree, ...@@ -201,17 +161,12 @@ ProcessQuery(Query *parsetree,
/* /*
* Now we can create the QueryDesc object. * Now we can create the QueryDesc object.
*/ */
queryDesc = CreateQueryDesc(parsetree, plan, dest, intoName); queryDesc = CreateQueryDesc(parsetree, plan, dest, intoName, NULL, false);
/*
* create a default executor state.
*/
state = CreateExecutorState();
/* /*
* call ExecStart to prepare the plan for execution * call ExecStart to prepare the plan for execution
*/ */
attinfo = ExecutorStart(queryDesc, state); ExecutorStart(queryDesc);
/* /*
* If retrieve into portal, stop now; we do not run the plan until a * If retrieve into portal, stop now; we do not run the plan until a
...@@ -219,11 +174,8 @@ ProcessQuery(Query *parsetree, ...@@ -219,11 +174,8 @@ ProcessQuery(Query *parsetree,
*/ */
if (isRetrieveIntoPortal) if (isRetrieveIntoPortal)
{ {
PortalSetQuery(portal, /* Arrange to shut down the executor if portal is dropped */
queryDesc, PortalSetQuery(portal, queryDesc, PortalCleanup);
attinfo,
state,
PortalCleanup);
/* Now we can return to caller's memory context. */ /* Now we can return to caller's memory context. */
MemoryContextSwitchTo(oldContext); MemoryContextSwitchTo(oldContext);
...@@ -239,7 +191,7 @@ ProcessQuery(Query *parsetree, ...@@ -239,7 +191,7 @@ ProcessQuery(Query *parsetree,
* Now we get to the important call to ExecutorRun() where we actually * Now we get to the important call to ExecutorRun() where we actually
* run the plan.. * run the plan..
*/ */
ExecutorRun(queryDesc, state, ForwardScanDirection, 0L); ExecutorRun(queryDesc, ForwardScanDirection, 0L);
/* /*
* Build command completion status string, if caller wants one. * Build command completion status string, if caller wants one.
...@@ -254,20 +206,20 @@ ProcessQuery(Query *parsetree, ...@@ -254,20 +206,20 @@ ProcessQuery(Query *parsetree,
strcpy(completionTag, "SELECT"); strcpy(completionTag, "SELECT");
break; break;
case CMD_INSERT: case CMD_INSERT:
if (state->es_processed == 1) if (queryDesc->estate->es_processed == 1)
lastOid = state->es_lastoid; lastOid = queryDesc->estate->es_lastoid;
else else
lastOid = InvalidOid; lastOid = InvalidOid;
snprintf(completionTag, COMPLETION_TAG_BUFSIZE, snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
"INSERT %u %u", lastOid, state->es_processed); "INSERT %u %u", lastOid, queryDesc->estate->es_processed);
break; break;
case CMD_UPDATE: case CMD_UPDATE:
snprintf(completionTag, COMPLETION_TAG_BUFSIZE, snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
"UPDATE %u", state->es_processed); "UPDATE %u", queryDesc->estate->es_processed);
break; break;
case CMD_DELETE: case CMD_DELETE:
snprintf(completionTag, COMPLETION_TAG_BUFSIZE, snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
"DELETE %u", state->es_processed); "DELETE %u", queryDesc->estate->es_processed);
break; break;
default: default:
strcpy(completionTag, "???"); strcpy(completionTag, "???");
...@@ -278,5 +230,5 @@ ProcessQuery(Query *parsetree, ...@@ -278,5 +230,5 @@ ProcessQuery(Query *parsetree,
/* /*
* Now, we close down all the scans and free allocated resources. * Now, we close down all the scans and free allocated resources.
*/ */
ExecutorEnd(queryDesc, state); ExecutorEnd(queryDesc);
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.49 2002/06/20 20:29:40 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/utils/mmgr/portalmem.c,v 1.50 2002/12/05 15:50:35 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -149,26 +149,15 @@ GetPortalByName(char *name) ...@@ -149,26 +149,15 @@ GetPortalByName(char *name)
/* /*
* PortalSetQuery * PortalSetQuery
* Attaches a "query" to portal. * Attaches a "query" to portal.
*
* Exceptions:
* BadState if called when disabled.
* BadArg if portal is invalid.
* BadArg if queryDesc is "invalid."
* BadArg if state is "invalid."
*/ */
void void
PortalSetQuery(Portal portal, PortalSetQuery(Portal portal,
QueryDesc *queryDesc, QueryDesc *queryDesc,
TupleDesc attinfo,
EState *state,
void (*cleanup) (Portal portal)) void (*cleanup) (Portal portal))
{ {
AssertArg(PortalIsValid(portal)); AssertArg(PortalIsValid(portal));
AssertArg(IsA((Node *) state, EState));
portal->queryDesc = queryDesc; portal->queryDesc = queryDesc;
portal->attinfo = attinfo;
portal->state = state;
portal->atStart = true; /* Allow fetch forward only */ portal->atStart = true; /* Allow fetch forward only */
portal->atEnd = false; portal->atEnd = false;
portal->cleanup = cleanup; portal->cleanup = cleanup;
...@@ -212,8 +201,6 @@ CreatePortal(char *name) ...@@ -212,8 +201,6 @@ CreatePortal(char *name)
/* initialize portal query */ /* initialize portal query */
portal->queryDesc = NULL; portal->queryDesc = NULL;
portal->attinfo = NULL;
portal->state = NULL;
portal->atStart = true; /* disallow fetches until query is set */ portal->atStart = true; /* disallow fetches until query is set */
portal->atEnd = true; portal->atEnd = true;
portal->cleanup = NULL; portal->cleanup = NULL;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,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: execdesc.h,v 1.20 2002/09/04 20:31:42 momjian Exp $ * $Id: execdesc.h,v 1.21 2002/12/05 15:50:36 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -16,30 +16,38 @@ ...@@ -16,30 +16,38 @@
#define EXECDESC_H #define EXECDESC_H
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
#include "nodes/plannodes.h" #include "nodes/execnodes.h"
#include "tcop/dest.h" #include "tcop/dest.h"
/* ---------------- /* ----------------
* query descriptor: * query descriptor:
*
* a QueryDesc encapsulates everything that the executor * a QueryDesc encapsulates everything that the executor
* needs to execute the query * needs to execute the query
* --------------------- * ---------------------
*/ */
typedef struct QueryDesc typedef struct QueryDesc
{ {
/* These fields are provided by CreateQueryDesc */
CmdType operation; /* CMD_SELECT, CMD_UPDATE, etc. */ CmdType operation; /* CMD_SELECT, CMD_UPDATE, etc. */
Query *parsetree; Query *parsetree; /* rewritten parsetree */
Plan *plantree; Plan *plantree; /* planner's output */
CommandDest dest; /* the destination output of the execution */ CommandDest dest; /* the destination output of the execution */
const char *portalName; /* name of portal, or NULL */ const char *portalName; /* name of portal, or NULL */
ParamListInfo params; /* param values being passed in */
bool doInstrument; /* TRUE requests runtime instrumentation */
TupleDesc tupDesc; /* set by ExecutorStart */ /* These fields are set by ExecutorStart */
TupleDesc tupDesc; /* descriptor for result tuples */
EState *estate; /* executor's query-wide state */
PlanState *planstate; /* tree of per-plan-node state */
} QueryDesc; } QueryDesc;
/* in pquery.c */ /* in pquery.c */
extern QueryDesc *CreateQueryDesc(Query *parsetree, Plan *plantree, extern QueryDesc *CreateQueryDesc(Query *parsetree, Plan *plantree,
CommandDest dest, const char *portalName); CommandDest dest, const char *portalName,
ParamListInfo params,
bool doInstrument);
#endif /* EXECDESC_H */ #endif /* EXECDESC_H */
...@@ -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: executor.h,v 1.80 2002/12/01 20:27:32 tgl Exp $ * $Id: executor.h,v 1.81 2002/12/05 15:50:36 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "executor/execdesc.h" #include "executor/execdesc.h"
/* ---------------- /* ----------------
* TupIsNull * TupIsNull
* *
...@@ -30,9 +31,9 @@ ...@@ -30,9 +31,9 @@
/* /*
* prototypes from functions in execAmi.c * prototypes from functions in execAmi.c
*/ */
extern void ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent); extern void ExecReScan(PlanState *node, ExprContext *exprCtxt);
extern void ExecMarkPos(Plan *node); extern void ExecMarkPos(PlanState *node);
extern void ExecRestrPos(Plan *node); extern void ExecRestrPos(PlanState *node);
extern bool ExecSupportsMarkRestore(NodeTag plantype); extern bool ExecSupportsMarkRestore(NodeTag plantype);
/* /*
...@@ -49,10 +50,12 @@ extern HeapTuple ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot); ...@@ -49,10 +50,12 @@ extern HeapTuple ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot);
/* /*
* prototypes from functions in execMain.c * prototypes from functions in execMain.c
*/ */
extern TupleDesc ExecutorStart(QueryDesc *queryDesc, EState *estate); extern void ExecutorStart(QueryDesc *queryDesc);
extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc, EState *estate, extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc,
ScanDirection direction, long count); ScanDirection direction, long count);
extern void ExecutorEnd(QueryDesc *queryDesc, EState *estate); extern void ExecutorEnd(QueryDesc *queryDesc);
extern EState *CreateExecutorState(void);
extern void ExecCheckRTPerms(List *rangeTable, CmdType operation);
extern void ExecConstraints(const char *caller, ResultRelInfo *resultRelInfo, extern void ExecConstraints(const char *caller, ResultRelInfo *resultRelInfo,
TupleTableSlot *slot, EState *estate); TupleTableSlot *slot, EState *estate);
extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti, extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti,
...@@ -61,11 +64,11 @@ extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti, ...@@ -61,11 +64,11 @@ extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti,
/* /*
* prototypes from functions in execProcnode.c * prototypes from functions in execProcnode.c
*/ */
extern bool ExecInitNode(Plan *node, EState *estate, Plan *parent); extern PlanState *ExecInitNode(Plan *node, EState *estate);
extern TupleTableSlot *ExecProcNode(Plan *node, Plan *parent); extern TupleTableSlot *ExecProcNode(PlanState *node);
extern int ExecCountSlotsNode(Plan *node); extern int ExecCountSlotsNode(Plan *node);
extern void ExecEndNode(Plan *node, Plan *parent); extern void ExecEndNode(PlanState *node);
extern TupleDesc ExecGetTupType(Plan *node); extern TupleDesc ExecGetTupType(PlanState *node);
/* /*
* prototypes from functions in execQual.c * prototypes from functions in execQual.c
...@@ -89,6 +92,7 @@ extern Datum ExecEvalExpr(Node *expression, ExprContext *econtext, ...@@ -89,6 +92,7 @@ extern Datum ExecEvalExpr(Node *expression, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
extern Datum ExecEvalExprSwitchContext(Node *expression, ExprContext *econtext, extern Datum ExecEvalExprSwitchContext(Node *expression, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone); bool *isNull, ExprDoneCond *isDone);
extern Node *ExecInitExpr(Node *node, PlanState *parent);
extern bool ExecQual(List *qual, ExprContext *econtext, bool resultForNull); extern bool ExecQual(List *qual, ExprContext *econtext, bool resultForNull);
extern int ExecTargetListLength(List *targetlist); extern int ExecTargetListLength(List *targetlist);
extern int ExecCleanTargetListLength(List *targetlist); extern int ExecCleanTargetListLength(List *targetlist);
...@@ -98,9 +102,9 @@ extern TupleTableSlot *ExecProject(ProjectionInfo *projInfo, ...@@ -98,9 +102,9 @@ extern TupleTableSlot *ExecProject(ProjectionInfo *projInfo,
/* /*
* prototypes from functions in execScan.c * prototypes from functions in execScan.c
*/ */
typedef TupleTableSlot *(*ExecScanAccessMtd) (Scan *node); typedef TupleTableSlot *(*ExecScanAccessMtd) (ScanState *node);
extern TupleTableSlot *ExecScan(Scan *node, ExecScanAccessMtd accessMtd); extern TupleTableSlot *ExecScan(ScanState *node, ExecScanAccessMtd accessMtd);
/* /*
* prototypes from functions in execTuples.c * prototypes from functions in execTuples.c
...@@ -117,14 +121,13 @@ extern TupleTableSlot *ExecClearTuple(TupleTableSlot *slot); ...@@ -117,14 +121,13 @@ extern TupleTableSlot *ExecClearTuple(TupleTableSlot *slot);
extern void ExecSetSlotDescriptor(TupleTableSlot *slot, extern void ExecSetSlotDescriptor(TupleTableSlot *slot,
TupleDesc tupdesc, bool shouldFree); TupleDesc tupdesc, bool shouldFree);
extern void ExecSetSlotDescriptorIsNew(TupleTableSlot *slot, bool isNew); extern void ExecSetSlotDescriptorIsNew(TupleTableSlot *slot, bool isNew);
extern void ExecInitResultTupleSlot(EState *estate, CommonState *commonstate); extern void ExecInitResultTupleSlot(EState *estate, PlanState *planstate);
extern void ExecInitScanTupleSlot(EState *estate, extern void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate);
CommonScanState *commonscanstate);
extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate); extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate);
extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate, extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate,
TupleDesc tupType); TupleDesc tupType);
extern TupleDesc ExecTypeFromTL(List *targetList, bool hasoid); extern TupleDesc ExecTypeFromTL(List *targetList, bool hasoid);
extern void SetChangedParamList(Plan *node, List *newchg); extern void SetChangedParamList(PlanState *node, List *newchg);
typedef struct TupOutputState typedef struct TupOutputState
{ {
...@@ -155,21 +158,19 @@ extern void end_tup_output(TupOutputState *tstate); ...@@ -155,21 +158,19 @@ extern void end_tup_output(TupOutputState *tstate);
* prototypes from functions in execUtils.c * prototypes from functions in execUtils.c
*/ */
extern void ResetTupleCount(void); extern void ResetTupleCount(void);
extern void ExecAssignExprContext(EState *estate, CommonState *commonstate); extern void ExecAssignExprContext(EState *estate, PlanState *planstate);
extern void ExecAssignResultType(CommonState *commonstate, extern void ExecAssignResultType(PlanState *planstate,
TupleDesc tupDesc, bool shouldFree); TupleDesc tupDesc, bool shouldFree);
extern void ExecAssignResultTypeFromOuterPlan(Plan *node, extern void ExecAssignResultTypeFromOuterPlan(PlanState *planstate);
CommonState *commonstate); extern void ExecAssignResultTypeFromTL(PlanState *planstate);
extern void ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate); extern TupleDesc ExecGetResultType(PlanState *planstate);
extern TupleDesc ExecGetResultType(CommonState *commonstate); extern void ExecAssignProjectionInfo(PlanState *planstate);
extern void ExecAssignProjectionInfo(Plan *node, CommonState *commonstate); extern void ExecFreeProjectionInfo(PlanState *planstate);
extern void ExecFreeProjectionInfo(CommonState *commonstate); extern void ExecFreeExprContext(PlanState *planstate);
extern void ExecFreeExprContext(CommonState *commonstate); extern TupleDesc ExecGetScanType(ScanState *scanstate);
extern TupleDesc ExecGetScanType(CommonScanState *csstate); extern void ExecAssignScanType(ScanState *scanstate,
extern void ExecAssignScanType(CommonScanState *csstate,
TupleDesc tupDesc, bool shouldFree); TupleDesc tupDesc, bool shouldFree);
extern void ExecAssignScanTypeFromOuterPlan(Plan *node, extern void ExecAssignScanTypeFromOuterPlan(ScanState *scanstate);
CommonScanState *csstate);
extern ExprContext *MakeExprContext(TupleTableSlot *slot, extern ExprContext *MakeExprContext(TupleTableSlot *slot,
MemoryContext queryContext); MemoryContext queryContext);
......
...@@ -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: nodeAgg.h,v 1.17 2002/06/20 20:29:49 momjian Exp $ * $Id: nodeAgg.h,v 1.18 2002/12/05 15:50:36 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -15,13 +15,13 @@ ...@@ -15,13 +15,13 @@
#define NODEAGG_H #define NODEAGG_H
#include "fmgr.h" #include "fmgr.h"
#include "nodes/plannodes.h" #include "nodes/execnodes.h"
extern TupleTableSlot *ExecAgg(Agg *node);
extern bool ExecInitAgg(Agg *node, EState *estate, Plan *parent);
extern int ExecCountSlotsAgg(Agg *node); extern int ExecCountSlotsAgg(Agg *node);
extern void ExecEndAgg(Agg *node); extern AggState *ExecInitAgg(Agg *node, EState *estate);
extern void ExecReScanAgg(Agg *node, ExprContext *exprCtxt, Plan *parent); extern TupleTableSlot *ExecAgg(AggState *node);
extern void ExecEndAgg(AggState *node);
extern void ExecReScanAgg(AggState *node, ExprContext *exprCtxt);
extern Datum aggregate_dummy(PG_FUNCTION_ARGS); extern Datum aggregate_dummy(PG_FUNCTION_ARGS);
......
...@@ -7,19 +7,19 @@ ...@@ -7,19 +7,19 @@
* 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: nodeAppend.h,v 1.17 2002/06/20 20:29:49 momjian Exp $ * $Id: nodeAppend.h,v 1.18 2002/12/05 15:50:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef NODEAPPEND_H #ifndef NODEAPPEND_H
#define NODEAPPEND_H #define NODEAPPEND_H
#include "nodes/plannodes.h" #include "nodes/execnodes.h"
extern bool ExecInitAppend(Append *node, EState *estate, Plan *parent);
extern int ExecCountSlotsAppend(Append *node); extern int ExecCountSlotsAppend(Append *node);
extern TupleTableSlot *ExecProcAppend(Append *node); extern AppendState *ExecInitAppend(Append *node, EState *estate);
extern void ExecEndAppend(Append *node); extern TupleTableSlot *ExecProcAppend(AppendState *node);
extern void ExecReScanAppend(Append *node, ExprContext *exprCtxt, Plan *parent); extern void ExecEndAppend(AppendState *node);
extern void ExecReScanAppend(AppendState *node, ExprContext *exprCtxt);
#endif /* NODEAPPEND_H */ #endif /* NODEAPPEND_H */
...@@ -7,21 +7,21 @@ ...@@ -7,21 +7,21 @@
* 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: nodeFunctionscan.h,v 1.2 2002/06/20 20:29:49 momjian Exp $ * $Id: nodeFunctionscan.h,v 1.3 2002/12/05 15:50:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef NODEFUNCTIONSCAN_H #ifndef NODEFUNCTIONSCAN_H
#define NODEFUNCTIONSCAN_H #define NODEFUNCTIONSCAN_H
#include "nodes/plannodes.h" #include "nodes/execnodes.h"
extern TupleTableSlot *ExecFunctionScan(FunctionScan *node);
extern void ExecEndFunctionScan(FunctionScan *node);
extern bool ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent);
extern int ExecCountSlotsFunctionScan(FunctionScan *node); extern int ExecCountSlotsFunctionScan(FunctionScan *node);
extern void ExecFunctionMarkPos(FunctionScan *node); extern FunctionScanState *ExecInitFunctionScan(FunctionScan *node, EState *estate);
extern void ExecFunctionRestrPos(FunctionScan *node); extern TupleTableSlot *ExecFunctionScan(FunctionScanState *node);
extern void ExecFunctionReScan(FunctionScan *node, ExprContext *exprCtxt, Plan *parent); extern void ExecEndFunctionScan(FunctionScanState *node);
extern void ExecFunctionMarkPos(FunctionScanState *node);
extern void ExecFunctionRestrPos(FunctionScanState *node);
extern void ExecFunctionReScan(FunctionScanState *node, ExprContext *exprCtxt);
#endif /* NODEFUNCTIONSCAN_H */ #endif /* NODEFUNCTIONSCAN_H */
...@@ -7,20 +7,20 @@ ...@@ -7,20 +7,20 @@
* 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: nodeGroup.h,v 1.22 2002/06/20 20:29:49 momjian Exp $ * $Id: nodeGroup.h,v 1.23 2002/12/05 15:50:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef NODEGROUP_H #ifndef NODEGROUP_H
#define NODEGROUP_H #define NODEGROUP_H
#include "nodes/plannodes.h" #include "nodes/execnodes.h"
extern TupleTableSlot *ExecGroup(Group *node);
extern bool ExecInitGroup(Group *node, EState *estate, Plan *parent);
extern int ExecCountSlotsGroup(Group *node); extern int ExecCountSlotsGroup(Group *node);
extern void ExecEndGroup(Group *node); extern GroupState *ExecInitGroup(Group *node, EState *estate);
extern void ExecReScanGroup(Group *node, ExprContext *exprCtxt, Plan *parent); extern TupleTableSlot *ExecGroup(GroupState *node);
extern void ExecEndGroup(GroupState *node);
extern void ExecReScanGroup(GroupState *node, ExprContext *exprCtxt);
extern bool execTuplesMatch(HeapTuple tuple1, extern bool execTuplesMatch(HeapTuple tuple1,
HeapTuple tuple2, HeapTuple tuple2,
......
...@@ -7,19 +7,21 @@ ...@@ -7,19 +7,21 @@
* 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: nodeHash.h,v 1.26 2002/11/30 00:08:20 tgl Exp $ * $Id: nodeHash.h,v 1.27 2002/12/05 15:50:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef NODEHASH_H #ifndef NODEHASH_H
#define NODEHASH_H #define NODEHASH_H
#include "nodes/plannodes.h" #include "nodes/execnodes.h"
extern TupleTableSlot *ExecHash(Hash *node);
extern bool ExecInitHash(Hash *node, EState *estate, Plan *parent);
extern int ExecCountSlotsHash(Hash *node); extern int ExecCountSlotsHash(Hash *node);
extern void ExecEndHash(Hash *node); extern HashState *ExecInitHash(Hash *node, EState *estate);
extern TupleTableSlot *ExecHash(HashState *node);
extern void ExecEndHash(HashState *node);
extern void ExecReScanHash(HashState *node, ExprContext *exprCtxt);
extern HashJoinTable ExecHashTableCreate(Hash *node); extern HashJoinTable ExecHashTableCreate(Hash *node);
extern void ExecHashTableDestroy(HashJoinTable hashtable); extern void ExecHashTableDestroy(HashJoinTable hashtable);
extern void ExecHashTableInsert(HashJoinTable hashtable, extern void ExecHashTableInsert(HashJoinTable hashtable,
...@@ -31,7 +33,6 @@ extern int ExecHashGetBucket(HashJoinTable hashtable, ...@@ -31,7 +33,6 @@ extern int ExecHashGetBucket(HashJoinTable hashtable,
extern HeapTuple ExecScanHashBucket(HashJoinState *hjstate, List *hjclauses, extern HeapTuple ExecScanHashBucket(HashJoinState *hjstate, List *hjclauses,
ExprContext *econtext); ExprContext *econtext);
extern void ExecHashTableReset(HashJoinTable hashtable, long ntuples); extern void ExecHashTableReset(HashJoinTable hashtable, long ntuples);
extern void ExecReScanHash(Hash *node, ExprContext *exprCtxt, Plan *parent);
extern void ExecChooseHashTableSize(double ntuples, int tupwidth, extern void ExecChooseHashTableSize(double ntuples, int tupwidth,
int *virtualbuckets, int *virtualbuckets,
int *physicalbuckets, int *physicalbuckets,
......
...@@ -7,20 +7,21 @@ ...@@ -7,20 +7,21 @@
* 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: nodeHashjoin.h,v 1.23 2002/06/20 20:29:49 momjian Exp $ * $Id: nodeHashjoin.h,v 1.24 2002/12/05 15:50:37 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef NODEHASHJOIN_H #ifndef NODEHASHJOIN_H
#define NODEHASHJOIN_H #define NODEHASHJOIN_H
#include "nodes/plannodes.h" #include "nodes/execnodes.h"
extern TupleTableSlot *ExecHashJoin(HashJoin *node);
extern bool ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent);
extern int ExecCountSlotsHashJoin(HashJoin *node); extern int ExecCountSlotsHashJoin(HashJoin *node);
extern void ExecEndHashJoin(HashJoin *node); extern HashJoinState *ExecInitHashJoin(HashJoin *node, EState *estate);
extern TupleTableSlot *ExecHashJoin(HashJoinState *node);
extern void ExecEndHashJoin(HashJoinState *node);
extern void ExecReScanHashJoin(HashJoinState *node, ExprContext *exprCtxt);
extern void ExecHashJoinSaveTuple(HeapTuple heapTuple, BufFile *file); extern void ExecHashJoinSaveTuple(HeapTuple heapTuple, BufFile *file);
extern void ExecReScanHashJoin(HashJoin *node, ExprContext *exprCtxt, Plan *parent);
#endif /* NODEHASHJOIN_H */ #endif /* NODEHASHJOIN_H */
...@@ -7,22 +7,23 @@ ...@@ -7,22 +7,23 @@
* 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: nodeIndexscan.h,v 1.16 2002/06/20 20:29:49 momjian Exp $ * $Id: nodeIndexscan.h,v 1.17 2002/12/05 15:50:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef NODEINDEXSCAN_H #ifndef NODEINDEXSCAN_H
#define NODEINDEXSCAN_H #define NODEINDEXSCAN_H
#include "nodes/plannodes.h" #include "nodes/execnodes.h"
extern TupleTableSlot *ExecIndexScan(IndexScan *node);
extern void ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent);
extern void ExecEndIndexScan(IndexScan *node);
extern void ExecIndexMarkPos(IndexScan *node);
extern void ExecIndexRestrPos(IndexScan *node);
extern void ExecUpdateIndexScanKeys(IndexScan *node, ExprContext *econtext);
extern bool ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent);
extern int ExecCountSlotsIndexScan(IndexScan *node); extern int ExecCountSlotsIndexScan(IndexScan *node);
extern IndexScanState *ExecInitIndexScan(IndexScan *node, EState *estate);
extern TupleTableSlot *ExecIndexScan(IndexScanState *node);
extern void ExecEndIndexScan(IndexScanState *node);
extern void ExecIndexMarkPos(IndexScanState *node);
extern void ExecIndexRestrPos(IndexScanState *node);
extern void ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt);
extern void ExecUpdateIndexScanKeys(IndexScanState *node, ExprContext *econtext);
#endif /* NODEINDEXSCAN_H */ #endif /* NODEINDEXSCAN_H */
...@@ -7,19 +7,19 @@ ...@@ -7,19 +7,19 @@
* 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: nodeLimit.h,v 1.6 2002/06/20 20:29:49 momjian Exp $ * $Id: nodeLimit.h,v 1.7 2002/12/05 15:50:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef NODELIMIT_H #ifndef NODELIMIT_H
#define NODELIMIT_H #define NODELIMIT_H
#include "nodes/plannodes.h" #include "nodes/execnodes.h"
extern TupleTableSlot *ExecLimit(Limit *node);
extern bool ExecInitLimit(Limit *node, EState *estate, Plan *parent);
extern int ExecCountSlotsLimit(Limit *node); extern int ExecCountSlotsLimit(Limit *node);
extern void ExecEndLimit(Limit *node); extern LimitState *ExecInitLimit(Limit *node, EState *estate);
extern void ExecReScanLimit(Limit *node, ExprContext *exprCtxt, Plan *parent); extern TupleTableSlot *ExecLimit(LimitState *node);
extern void ExecEndLimit(LimitState *node);
extern void ExecReScanLimit(LimitState *node, ExprContext *exprCtxt);
#endif /* NODELIMIT_H */ #endif /* NODELIMIT_H */
...@@ -7,21 +7,21 @@ ...@@ -7,21 +7,21 @@
* 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: nodeMaterial.h,v 1.18 2002/06/20 20:29:49 momjian Exp $ * $Id: nodeMaterial.h,v 1.19 2002/12/05 15:50:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef NODEMATERIAL_H #ifndef NODEMATERIAL_H
#define NODEMATERIAL_H #define NODEMATERIAL_H
#include "nodes/plannodes.h" #include "nodes/execnodes.h"
extern TupleTableSlot *ExecMaterial(Material *node);
extern bool ExecInitMaterial(Material *node, EState *estate, Plan *parent);
extern int ExecCountSlotsMaterial(Material *node); extern int ExecCountSlotsMaterial(Material *node);
extern void ExecEndMaterial(Material *node); extern MaterialState *ExecInitMaterial(Material *node, EState *estate);
extern void ExecMaterialMarkPos(Material *node); extern TupleTableSlot *ExecMaterial(MaterialState *node);
extern void ExecMaterialRestrPos(Material *node); extern void ExecEndMaterial(MaterialState *node);
extern void ExecMaterialReScan(Material *node, ExprContext *exprCtxt, Plan *parent); extern void ExecMaterialMarkPos(MaterialState *node);
extern void ExecMaterialRestrPos(MaterialState *node);
extern void ExecMaterialReScan(MaterialState *node, ExprContext *exprCtxt);
#endif /* NODEMATERIAL_H */ #endif /* NODEMATERIAL_H */
...@@ -7,19 +7,19 @@ ...@@ -7,19 +7,19 @@
* 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: nodeMergejoin.h,v 1.17 2002/06/20 20:29:49 momjian Exp $ * $Id: nodeMergejoin.h,v 1.18 2002/12/05 15:50:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef NODEMERGEJOIN_H #ifndef NODEMERGEJOIN_H
#define NODEMERGEJOIN_H #define NODEMERGEJOIN_H
#include "nodes/plannodes.h" #include "nodes/execnodes.h"
extern TupleTableSlot *ExecMergeJoin(MergeJoin *node);
extern bool ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent);
extern int ExecCountSlotsMergeJoin(MergeJoin *node); extern int ExecCountSlotsMergeJoin(MergeJoin *node);
extern void ExecEndMergeJoin(MergeJoin *node); extern MergeJoinState *ExecInitMergeJoin(MergeJoin *node, EState *estate);
extern void ExecReScanMergeJoin(MergeJoin *node, ExprContext *exprCtxt, Plan *parent); extern TupleTableSlot *ExecMergeJoin(MergeJoinState *node);
extern void ExecEndMergeJoin(MergeJoinState *node);
extern void ExecReScanMergeJoin(MergeJoinState *node, ExprContext *exprCtxt);
#endif /* NODEMERGEJOIN_H; */ #endif /* NODEMERGEJOIN_H */
...@@ -7,20 +7,19 @@ ...@@ -7,20 +7,19 @@
* 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: nodeNestloop.h,v 1.18 2002/06/20 20:29:49 momjian Exp $ * $Id: nodeNestloop.h,v 1.19 2002/12/05 15:50:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef NODENESTLOOP_H #ifndef NODENESTLOOP_H
#define NODENESTLOOP_H #define NODENESTLOOP_H
#include "nodes/plannodes.h" #include "nodes/execnodes.h"
extern TupleTableSlot *ExecNestLoop(NestLoop *node);
extern bool ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent);
extern int ExecCountSlotsNestLoop(NestLoop *node); extern int ExecCountSlotsNestLoop(NestLoop *node);
extern void ExecEndNestLoop(NestLoop *node); extern NestLoopState *ExecInitNestLoop(NestLoop *node, EState *estate);
extern void ExecReScanNestLoop(NestLoop *node, ExprContext *exprCtxt, extern TupleTableSlot *ExecNestLoop(NestLoopState *node);
Plan *parent); extern void ExecEndNestLoop(NestLoopState *node);
extern void ExecReScanNestLoop(NestLoopState *node, ExprContext *exprCtxt);
#endif /* NODENESTLOOP_H */ #endif /* NODENESTLOOP_H */
...@@ -7,19 +7,19 @@ ...@@ -7,19 +7,19 @@
* 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: nodeResult.h,v 1.15 2002/06/20 20:29:49 momjian Exp $ * $Id: nodeResult.h,v 1.16 2002/12/05 15:50:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef NODERESULT_H #ifndef NODERESULT_H
#define NODERESULT_H #define NODERESULT_H
#include "nodes/plannodes.h" #include "nodes/execnodes.h"
extern TupleTableSlot *ExecResult(Result *node);
extern bool ExecInitResult(Result *node, EState *estate, Plan *parent);
extern int ExecCountSlotsResult(Result *node); extern int ExecCountSlotsResult(Result *node);
extern void ExecEndResult(Result *node); extern ResultState *ExecInitResult(Result *node, EState *estate);
extern void ExecReScanResult(Result *node, ExprContext *exprCtxt, Plan *parent); extern TupleTableSlot *ExecResult(ResultState *node);
extern void ExecEndResult(ResultState *node);
extern void ExecReScanResult(ResultState *node, ExprContext *exprCtxt);
#endif /* NODERESULT_H */ #endif /* NODERESULT_H */
...@@ -7,21 +7,21 @@ ...@@ -7,21 +7,21 @@
* 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: nodeSeqscan.h,v 1.15 2002/06/20 20:29:49 momjian Exp $ * $Id: nodeSeqscan.h,v 1.16 2002/12/05 15:50:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef NODESEQSCAN_H #ifndef NODESEQSCAN_H
#define NODESEQSCAN_H #define NODESEQSCAN_H
#include "nodes/plannodes.h" #include "nodes/execnodes.h"
extern TupleTableSlot *ExecSeqScan(SeqScan *node);
extern bool ExecInitSeqScan(SeqScan *node, EState *estate, Plan *parent);
extern int ExecCountSlotsSeqScan(SeqScan *node); extern int ExecCountSlotsSeqScan(SeqScan *node);
extern void ExecEndSeqScan(SeqScan *node); extern SeqScanState *ExecInitSeqScan(SeqScan *node, EState *estate);
extern void ExecSeqReScan(SeqScan *node, ExprContext *exprCtxt, Plan *parent); extern TupleTableSlot *ExecSeqScan(SeqScanState *node);
extern void ExecSeqMarkPos(SeqScan *node); extern void ExecEndSeqScan(SeqScanState *node);
extern void ExecSeqRestrPos(SeqScan *node); extern void ExecSeqMarkPos(SeqScanState *node);
extern void ExecSeqRestrPos(SeqScanState *node);
extern void ExecSeqReScan(SeqScanState *node, ExprContext *exprCtxt);
#endif /* NODESEQSCAN_H */ #endif /* NODESEQSCAN_H */
...@@ -7,19 +7,19 @@ ...@@ -7,19 +7,19 @@
* 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: nodeSetOp.h,v 1.6 2002/06/20 20:29:49 momjian Exp $ * $Id: nodeSetOp.h,v 1.7 2002/12/05 15:50:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef NODESETOP_H #ifndef NODESETOP_H
#define NODESETOP_H #define NODESETOP_H
#include "nodes/plannodes.h" #include "nodes/execnodes.h"
extern TupleTableSlot *ExecSetOp(SetOp *node);
extern bool ExecInitSetOp(SetOp *node, EState *estate, Plan *parent);
extern int ExecCountSlotsSetOp(SetOp *node); extern int ExecCountSlotsSetOp(SetOp *node);
extern void ExecEndSetOp(SetOp *node); extern SetOpState *ExecInitSetOp(SetOp *node, EState *estate);
extern void ExecReScanSetOp(SetOp *node, ExprContext *exprCtxt, Plan *parent); extern TupleTableSlot *ExecSetOp(SetOpState *node);
extern void ExecEndSetOp(SetOpState *node);
extern void ExecReScanSetOp(SetOpState *node, ExprContext *exprCtxt);
#endif /* NODESETOP_H */ #endif /* NODESETOP_H */
...@@ -7,21 +7,21 @@ ...@@ -7,21 +7,21 @@
* 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: nodeSort.h,v 1.15 2002/06/20 20:29:49 momjian Exp $ * $Id: nodeSort.h,v 1.16 2002/12/05 15:50:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef NODESORT_H #ifndef NODESORT_H
#define NODESORT_H #define NODESORT_H
#include "nodes/plannodes.h" #include "nodes/execnodes.h"
extern TupleTableSlot *ExecSort(Sort *node);
extern bool ExecInitSort(Sort *node, EState *estate, Plan *parent);
extern int ExecCountSlotsSort(Sort *node); extern int ExecCountSlotsSort(Sort *node);
extern void ExecEndSort(Sort *node); extern SortState *ExecInitSort(Sort *node, EState *estate);
extern void ExecSortMarkPos(Sort *node); extern TupleTableSlot *ExecSort(SortState *node);
extern void ExecSortRestrPos(Sort *node); extern void ExecEndSort(SortState *node);
extern void ExecReScanSort(Sort *node, ExprContext *exprCtxt, Plan *parent); extern void ExecSortMarkPos(SortState *node);
extern void ExecSortRestrPos(SortState *node);
extern void ExecReScanSort(SortState *node, ExprContext *exprCtxt);
#endif /* NODESORT_H */ #endif /* NODESORT_H */
...@@ -2,18 +2,26 @@ ...@@ -2,18 +2,26 @@
* *
* nodeSubplan.h * nodeSubplan.h
* *
*
*
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: nodeSubplan.h,v 1.12 2002/12/05 15:50:38 tgl Exp $
*
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef NODESUBPLAN_H #ifndef NODESUBPLAN_H
#define NODESUBPLAN_H #define NODESUBPLAN_H
#include "nodes/plannodes.h" #include "nodes/execnodes.h"
extern Datum ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, extern SubPlanState *ExecInitSubPlan(SubPlan *node, EState *estate);
extern Datum ExecSubPlan(SubPlanState *node, List *pvar, ExprContext *econtext,
bool *isNull); bool *isNull);
extern bool ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent); extern void ExecEndSubPlan(SubPlanState *node);
extern void ExecReScanSetParamPlan(SubPlan *node, Plan *parent); extern void ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent);
extern void ExecSetParamPlan(SubPlan *node, ExprContext *econtext);
extern void ExecEndSubPlan(SubPlan *node); extern void ExecSetParamPlan(SubPlanState *node, ExprContext *econtext);
#endif /* NODESUBPLAN_H */ #endif /* NODESUBPLAN_H */
...@@ -7,19 +7,19 @@ ...@@ -7,19 +7,19 @@
* 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: nodeSubqueryscan.h,v 1.6 2002/06/20 20:29:49 momjian Exp $ * $Id: nodeSubqueryscan.h,v 1.7 2002/12/05 15:50:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef NODESUBQUERYSCAN_H #ifndef NODESUBQUERYSCAN_H
#define NODESUBQUERYSCAN_H #define NODESUBQUERYSCAN_H
#include "nodes/plannodes.h" #include "nodes/execnodes.h"
extern TupleTableSlot *ExecSubqueryScan(SubqueryScan *node);
extern void ExecEndSubqueryScan(SubqueryScan *node);
extern bool ExecInitSubqueryScan(SubqueryScan *node, EState *estate, Plan *parent);
extern int ExecCountSlotsSubqueryScan(SubqueryScan *node); extern int ExecCountSlotsSubqueryScan(SubqueryScan *node);
extern void ExecSubqueryReScan(SubqueryScan *node, ExprContext *exprCtxt, Plan *parent); extern SubqueryScanState *ExecInitSubqueryScan(SubqueryScan *node, EState *estate);
extern TupleTableSlot *ExecSubqueryScan(SubqueryScanState *node);
extern void ExecEndSubqueryScan(SubqueryScanState *node);
extern void ExecSubqueryReScan(SubqueryScanState *node, ExprContext *exprCtxt);
#endif /* NODESUBQUERYSCAN_H */ #endif /* NODESUBQUERYSCAN_H */
...@@ -7,22 +7,21 @@ ...@@ -7,22 +7,21 @@
* 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: nodeTidscan.h,v 1.10 2002/11/30 05:21:03 tgl Exp $ * $Id: nodeTidscan.h,v 1.11 2002/12/05 15:50:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef NODETIDSCAN_H #ifndef NODETIDSCAN_H
#define NODETIDSCAN_H #define NODETIDSCAN_H
#include "nodes/plannodes.h" #include "nodes/execnodes.h"
extern TupleTableSlot *ExecTidScan(TidScan *node);
extern void ExecTidReScan(TidScan *node, ExprContext *exprCtxt, Plan *parent);
extern void ExecEndTidScan(TidScan *node);
extern void ExecTidMarkPos(TidScan *node);
extern void ExecTidRestrPos(TidScan *node);
extern bool ExecInitTidScan(TidScan *node, EState *estate, Plan *parent);
extern int ExecCountSlotsTidScan(TidScan *node); extern int ExecCountSlotsTidScan(TidScan *node);
extern void ExecTidReScan(TidScan *node, ExprContext *exprCtxt, Plan *parent); extern TidScanState *ExecInitTidScan(TidScan *node, EState *estate);
extern TupleTableSlot *ExecTidScan(TidScanState *node);
extern void ExecEndTidScan(TidScanState *node);
extern void ExecTidMarkPos(TidScanState *node);
extern void ExecTidRestrPos(TidScanState *node);
extern void ExecTidReScan(TidScanState *node, ExprContext *exprCtxt);
#endif /* NODETIDSCAN_H */ #endif /* NODETIDSCAN_H */
...@@ -7,19 +7,19 @@ ...@@ -7,19 +7,19 @@
* 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: nodeUnique.h,v 1.15 2002/06/20 20:29:49 momjian Exp $ * $Id: nodeUnique.h,v 1.16 2002/12/05 15:50:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef NODEUNIQUE_H #ifndef NODEUNIQUE_H
#define NODEUNIQUE_H #define NODEUNIQUE_H
#include "nodes/plannodes.h" #include "nodes/execnodes.h"
extern TupleTableSlot *ExecUnique(Unique *node);
extern bool ExecInitUnique(Unique *node, EState *estate, Plan *parent);
extern int ExecCountSlotsUnique(Unique *node); extern int ExecCountSlotsUnique(Unique *node);
extern void ExecEndUnique(Unique *node); extern UniqueState *ExecInitUnique(Unique *node, EState *estate);
extern void ExecReScanUnique(Unique *node, ExprContext *exprCtxt, Plan *parent); extern TupleTableSlot *ExecUnique(UniqueState *node);
extern void ExecEndUnique(UniqueState *node);
extern void ExecReScanUnique(UniqueState *node, ExprContext *exprCtxt);
#endif /* NODEUNIQUE_H */ #endif /* NODEUNIQUE_H */
...@@ -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: execnodes.h,v 1.81 2002/11/30 00:08:20 tgl Exp $ * $Id: execnodes.h,v 1.82 2002/12/05 15:50:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -15,12 +15,11 @@ ...@@ -15,12 +15,11 @@
#define EXECNODES_H #define EXECNODES_H
#include "access/relscan.h" #include "access/relscan.h"
#include "access/sdir.h"
#include "executor/hashjoin.h" #include "executor/hashjoin.h"
#include "executor/tuptable.h" #include "executor/tuptable.h"
#include "fmgr.h" #include "fmgr.h"
#include "nodes/params.h" #include "nodes/params.h"
#include "nodes/primnodes.h" #include "nodes/plannodes.h"
#include "utils/tuplestore.h" #include "utils/tuplestore.h"
...@@ -316,6 +315,8 @@ typedef struct EState ...@@ -316,6 +315,8 @@ typedef struct EState
List *es_rowMark; /* not good place, but there is no other */ List *es_rowMark; /* not good place, but there is no other */
MemoryContext es_query_cxt; /* per-query context in which EState lives */ MemoryContext es_query_cxt; /* per-query context in which EState lives */
bool es_instrument; /* true requests runtime instrumentation */
/* /*
* this ExprContext is for per-output-tuple operations, such as * this ExprContext is for per-output-tuple operations, such as
* constraint checks and index-value computations. It will be reset * constraint checks and index-value computations. It will be reset
...@@ -332,98 +333,101 @@ typedef struct EState ...@@ -332,98 +333,101 @@ typedef struct EState
bool es_useEvalPlan; bool es_useEvalPlan;
} EState; } EState;
/* ----------------
* Executor Type information needed by plannodes.h
*
*| Note: the bogus classes CommonState and CommonScanState exist only
*| because our inheritance system only allows single inheritance
*| and we have to have unique slot names. Hence two or more
*| classes which want to have a common slot must ALL inherit
*| the slot from some other class. (This is a big hack to
*| allow our classes to share slot names..)
*|
*| Example:
*| the class Result and the class NestLoop nodes both want
*| a slot called "OuterTuple" so they both have to inherit
*| it from some other class. In this case they inherit
*| it from CommonState. "CommonState" and "CommonScanState" are
*| the best names I could come up with for this sort of
*| stuff.
*|
*| As a result, many classes have extra slots which they
*| don't use. These slots are denoted (unused) in the
*| comment preceding the class definition. If you
*| comes up with a better idea of a way of doing things
*| along these lines, then feel free to make your idea
*| known to me.. -cim 10/15/89
* ----------------
*/
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* Common Executor State Information * Executor State Information
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
/* ---------------- /* ----------------
* CommonState information * PlanState node
*
* Superclass for all executor node-state object types.
* *
* OuterTupleSlot pointer to slot containing current "outer" tuple * We never actually instantiate any PlanState nodes; this is just the common
* ResultTupleSlot pointer to slot in tuple table for projected tuple * abstract superclass for all PlanState-type nodes.
* ExprContext node's expression-evaluation context
* ProjInfo info this node uses to form tuple projections
* TupFromTlist state flag used by some node types (why kept here?)
* ---------------- * ----------------
*/ */
typedef struct CommonState typedef struct PlanState
{ {
NodeTag type; /* its first field is NodeTag */ NodeTag type;
TupleTableSlot *cs_OuterTupleSlot;
TupleTableSlot *cs_ResultTupleSlot;
ExprContext *cs_ExprContext;
ProjectionInfo *cs_ProjInfo;
bool cs_TupFromTlist;
} CommonState;
Plan *plan; /* associated Plan node */
/* ---------------------------------------------------------------- EState *state; /* at execution time, state's of
* Control Node State Information * individual nodes point to one EState
* ---------------------------------------------------------------- * for the whole top-level plan */
struct Instrumentation *instrument; /* Optional runtime stats for this
* plan node */
/*
* Common structural data for all Plan types. These links to subsidiary
* state trees parallel links in the associated plan tree (except for
* the subPlan list, which does not exist in the plan tree).
*/
List *targetlist; /* target list to be computed at this node */
List *qual; /* implicitly-ANDed qual conditions */
struct PlanState *lefttree; /* input plan tree(s) */
struct PlanState *righttree;
List *initPlan; /* Init SubPlanState nodes (un-correlated
* expr subselects) */
List *subPlan; /* SubPlanState nodes in my expressions */
/*
* State for management of parameter-change-driven rescanning
*/
List *chgParam; /* integer list of IDs of changed Params */
/*
* Other run-time state needed by most if not all node types.
*/ */
TupleTableSlot *ps_OuterTupleSlot; /* slot for current "outer" tuple */
TupleTableSlot *ps_ResultTupleSlot; /* slot for my result tuples */
ExprContext *ps_ExprContext; /* node's expression-evaluation context */
ProjectionInfo *ps_ProjInfo; /* info for doing tuple projection */
bool ps_TupFromTlist; /* state flag for processing set-valued
* functions in targetlist */
} PlanState;
/* ----------------
* these are are defined to avoid confusion problems with "left"
* and "right" and "inner" and "outer". The convention is that
* the "left" plan is the "outer" plan and the "right" plan is
* the inner plan, but these make the code more readable.
* ----------------
*/
#define innerPlanState(node) (((PlanState *)(node))->righttree)
#define outerPlanState(node) (((PlanState *)(node))->lefttree)
/* ---------------- /* ----------------
* ResultState information * ResultState information
*
* done flag which tells us to quit when we
* have already returned a constant tuple.
* ---------------- * ----------------
*/ */
typedef struct ResultState typedef struct ResultState
{ {
CommonState cstate; /* its first field is NodeTag */ PlanState ps; /* its first field is NodeTag */
bool rs_done; Node *resconstantqual;
bool rs_checkqual; bool rs_done; /* are we done? */
bool rs_checkqual; /* do we need to check the qual? */
} ResultState; } ResultState;
/* ---------------- /* ----------------
* AppendState information * AppendState information
* *
* nplans how many plans are in the list
* whichplan which plan is being executed (0 .. n-1) * whichplan which plan is being executed (0 .. n-1)
* firstplan first plan to execute (usually 0) * firstplan first plan to execute (usually 0)
* lastplan last plan to execute (usually n-1) * lastplan last plan to execute (usually n-1)
* nplans how many plans are in the list
* initialized array of ExecInitNode() results
* ---------------- * ----------------
*/ */
typedef struct AppendState typedef struct AppendState
{ {
CommonState cstate; /* its first field is NodeTag */ PlanState ps; /* its first field is NodeTag */
PlanState **appendplans; /* array of PlanStates for my inputs */
int as_nplans;
int as_whichplan; int as_whichplan;
int as_firstplan; int as_firstplan;
int as_lastplan; int as_lastplan;
int as_nplans;
bool *as_initialized;
} AppendState; } AppendState;
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -432,9 +436,9 @@ typedef struct AppendState ...@@ -432,9 +436,9 @@ typedef struct AppendState
*/ */
/* ---------------- /* ----------------
* CommonScanState information * ScanState information
* *
* CommonScanState extends CommonState for node types that represent * ScanState extends PlanState for node types that represent
* scans of an underlying relation. It can also be used for nodes * scans of an underlying relation. It can also be used for nodes
* that scan the output of an underlying plan node --- in that case, * that scan the output of an underlying plan node --- in that case,
* only ScanTupleSlot is actually useful, and it refers to the tuple * only ScanTupleSlot is actually useful, and it refers to the tuple
...@@ -445,27 +449,23 @@ typedef struct AppendState ...@@ -445,27 +449,23 @@ typedef struct AppendState
* ScanTupleSlot pointer to slot in tuple table holding scan tuple * ScanTupleSlot pointer to slot in tuple table holding scan tuple
* ---------------- * ----------------
*/ */
typedef struct CommonScanState typedef struct ScanState
{ {
CommonState cstate; /* its first field is NodeTag */ PlanState ps; /* its first field is NodeTag */
Relation css_currentRelation; Relation ss_currentRelation;
HeapScanDesc css_currentScanDesc; HeapScanDesc ss_currentScanDesc;
TupleTableSlot *css_ScanTupleSlot; TupleTableSlot *ss_ScanTupleSlot;
} CommonScanState; } ScanState;
/* /*
* SeqScan uses a bare CommonScanState as its state item, since it needs * SeqScan uses a bare ScanState as its state node, since it needs
* no additional fields. * no additional fields.
*/ */
typedef ScanState SeqScanState;
/* ---------------- /* ----------------
* IndexScanState information * IndexScanState information
* *
* Note that an IndexScan node *also* has a CommonScanState state item.
* IndexScanState stores the info needed specifically for indexing.
* There's probably no good reason why this is a separate node type
* rather than an extension of CommonScanState.
*
* NumIndices number of indices in this scan * NumIndices number of indices in this scan
* IndexPtr current index in use * IndexPtr current index in use
* ScanKeys Skey structures to scan index rels * ScanKeys Skey structures to scan index rels
...@@ -479,7 +479,9 @@ typedef struct CommonScanState ...@@ -479,7 +479,9 @@ typedef struct CommonScanState
*/ */
typedef struct IndexScanState typedef struct IndexScanState
{ {
NodeTag type; ScanState ss; /* its first field is NodeTag */
List *indxqual;
List *indxqualorig;
int iss_NumIndices; int iss_NumIndices;
int iss_IndexPtr; int iss_IndexPtr;
int iss_MarkIndexPtr; int iss_MarkIndexPtr;
...@@ -495,10 +497,6 @@ typedef struct IndexScanState ...@@ -495,10 +497,6 @@ typedef struct IndexScanState
/* ---------------- /* ----------------
* TidScanState information * TidScanState information
* *
* Note that a TidScan node *also* has a CommonScanState state item.
* There's probably no good reason why this is a separate node type
* rather than an extension of CommonScanState.
*
* NumTids number of tids in this scan * NumTids number of tids in this scan
* TidPtr current tid in use * TidPtr current tid in use
* TidList evaluated item pointers * TidList evaluated item pointers
...@@ -506,7 +504,7 @@ typedef struct IndexScanState ...@@ -506,7 +504,7 @@ typedef struct IndexScanState
*/ */
typedef struct TidScanState typedef struct TidScanState
{ {
NodeTag type; ScanState ss; /* its first field is NodeTag */
int tss_NumTids; int tss_NumTids;
int tss_TidPtr; int tss_TidPtr;
int tss_MarkTidPtr; int tss_MarkTidPtr;
...@@ -526,7 +524,8 @@ typedef struct TidScanState ...@@ -526,7 +524,8 @@ typedef struct TidScanState
*/ */
typedef struct SubqueryScanState typedef struct SubqueryScanState
{ {
CommonScanState csstate; /* its first field is NodeTag */ ScanState ss; /* its first field is NodeTag */
PlanState *subplan;
EState *sss_SubEState; EState *sss_SubEState;
} SubqueryScanState; } SubqueryScanState;
...@@ -538,12 +537,12 @@ typedef struct SubqueryScanState ...@@ -538,12 +537,12 @@ typedef struct SubqueryScanState
* *
* tupdesc expected return tuple description * tupdesc expected return tuple description
* tuplestorestate private state of tuplestore.c * tuplestorestate private state of tuplestore.c
* funcexpr function expression being evaluated * funcexpr state for function expression being evaluated
* ---------------- * ----------------
*/ */
typedef struct FunctionScanState typedef struct FunctionScanState
{ {
CommonScanState csstate; /* its first field is NodeTag */ ScanState ss; /* its first field is NodeTag */
TupleDesc tupdesc; TupleDesc tupdesc;
Tuplestorestate *tuplestorestate; Tuplestorestate *tuplestorestate;
Node *funcexpr; Node *funcexpr;
...@@ -557,11 +556,15 @@ typedef struct FunctionScanState ...@@ -557,11 +556,15 @@ typedef struct FunctionScanState
/* ---------------- /* ----------------
* JoinState information * JoinState information
* *
* Superclass for state items of join nodes. * Superclass for state nodes of join plans.
* Currently this is the same as CommonState.
* ---------------- * ----------------
*/ */
typedef CommonState JoinState; typedef struct JoinState
{
PlanState ps;
JoinType jointype;
List *joinqual; /* JOIN quals (in addition to ps.qual) */
} JoinState;
/* ---------------- /* ----------------
* NestLoopState information * NestLoopState information
...@@ -573,7 +576,7 @@ typedef CommonState JoinState; ...@@ -573,7 +576,7 @@ typedef CommonState JoinState;
*/ */
typedef struct NestLoopState typedef struct NestLoopState
{ {
JoinState jstate; /* its first field is NodeTag */ JoinState js; /* its first field is NodeTag */
bool nl_NeedNewOuter; bool nl_NeedNewOuter;
bool nl_MatchedOuter; bool nl_MatchedOuter;
TupleTableSlot *nl_NullInnerTupleSlot; TupleTableSlot *nl_NullInnerTupleSlot;
...@@ -596,7 +599,8 @@ typedef struct NestLoopState ...@@ -596,7 +599,8 @@ typedef struct NestLoopState
*/ */
typedef struct MergeJoinState typedef struct MergeJoinState
{ {
JoinState jstate; /* its first field is NodeTag */ JoinState js; /* its first field is NodeTag */
List *mergeclauses;
List *mj_OuterSkipQual; List *mj_OuterSkipQual;
List *mj_InnerSkipQual; List *mj_InnerSkipQual;
int mj_JoinState; int mj_JoinState;
...@@ -630,7 +634,8 @@ typedef struct MergeJoinState ...@@ -630,7 +634,8 @@ typedef struct MergeJoinState
*/ */
typedef struct HashJoinState typedef struct HashJoinState
{ {
JoinState jstate; /* its first field is NodeTag */ JoinState js; /* its first field is NodeTag */
List *hashclauses;
HashJoinTable hj_HashTable; HashJoinTable hj_HashTable;
int hj_CurBucketNo; int hj_CurBucketNo;
HashJoinTuple hj_CurTuple; HashJoinTuple hj_CurTuple;
...@@ -656,23 +661,46 @@ typedef struct HashJoinState ...@@ -656,23 +661,46 @@ typedef struct HashJoinState
* materialize nodes are used to materialize the results * materialize nodes are used to materialize the results
* of a subplan into a temporary file. * of a subplan into a temporary file.
* *
* csstate.css_ScanTupleSlot refers to output of underlying plan. * ss.ss_ScanTupleSlot refers to output of underlying plan.
* *
* tuplestorestate private state of tuplestore.c * tuplestorestate private state of tuplestore.c
* ---------------- * ----------------
*/ */
typedef struct MaterialState typedef struct MaterialState
{ {
CommonScanState csstate; /* its first field is NodeTag */ ScanState ss; /* its first field is NodeTag */
void *tuplestorestate; void *tuplestorestate;
} MaterialState; } MaterialState;
/* ----------------
* SortState information
* ----------------
*/
typedef struct SortState
{
ScanState ss; /* its first field is NodeTag */
bool sort_Done; /* sort completed yet? */
void *tuplesortstate; /* private state of tuplesort.c */
} SortState;
/* ---------------------
* GroupState information
* -------------------------
*/
typedef struct GroupState
{
ScanState ss; /* its first field is NodeTag */
FmgrInfo *eqfunctions; /* per-field lookup data for equality fns */
HeapTuple grp_firstTuple; /* copy of first tuple of current group */
bool grp_done; /* indicates completion of Group scan */
} GroupState;
/* --------------------- /* ---------------------
* AggregateState information * AggState information
* *
* csstate.css_ScanTupleSlot refers to output of underlying plan. * ss.ss_ScanTupleSlot refers to output of underlying plan.
* *
* Note: csstate.cstate.cs_ExprContext contains ecxt_aggvalues and * Note: ss.ps.ps_ExprContext contains ecxt_aggvalues and
* ecxt_aggnulls arrays, which hold the computed agg values for the current * ecxt_aggnulls arrays, which hold the computed agg values for the current
* input group during evaluation of an Agg node's output tuple(s). We * input group during evaluation of an Agg node's output tuple(s). We
* create a second ExprContext, tmpcontext, in which to evaluate input * create a second ExprContext, tmpcontext, in which to evaluate input
...@@ -687,7 +715,7 @@ typedef struct AggHashTableData *AggHashTable; ...@@ -687,7 +715,7 @@ typedef struct AggHashTableData *AggHashTable;
typedef struct AggState typedef struct AggState
{ {
CommonScanState csstate; /* its first field is NodeTag */ ScanState ss; /* its first field is NodeTag */
List *aggs; /* all Aggref nodes in targetlist & quals */ List *aggs; /* all Aggref nodes in targetlist & quals */
int numaggs; /* length of list (could be zero!) */ int numaggs; /* length of list (could be zero!) */
FmgrInfo *eqfunctions; /* per-grouping-field equality fns */ FmgrInfo *eqfunctions; /* per-grouping-field equality fns */
...@@ -705,32 +733,6 @@ typedef struct AggState ...@@ -705,32 +733,6 @@ typedef struct AggState
int next_hash_bucket; /* next chain */ int next_hash_bucket; /* next chain */
} AggState; } AggState;
/* ---------------------
* GroupState information
* -------------------------
*/
typedef struct GroupState
{
CommonScanState csstate; /* its first field is NodeTag */
FmgrInfo *eqfunctions; /* per-field lookup data for equality fns */
HeapTuple grp_firstTuple; /* copy of first tuple of current group */
bool grp_done; /* indicates completion of Group scan */
} GroupState;
/* ----------------
* SortState information
*
* sort_Done indicates whether sort has been performed yet
* tuplesortstate private state of tuplesort.c
* ----------------
*/
typedef struct SortState
{
CommonScanState csstate; /* its first field is NodeTag */
bool sort_Done;
void *tuplesortstate;
} SortState;
/* ---------------- /* ----------------
* UniqueState information * UniqueState information
* *
...@@ -744,12 +746,22 @@ typedef struct SortState ...@@ -744,12 +746,22 @@ typedef struct SortState
*/ */
typedef struct UniqueState typedef struct UniqueState
{ {
CommonState cstate; /* its first field is NodeTag */ PlanState ps; /* its first field is NodeTag */
FmgrInfo *eqfunctions; /* per-field lookup data for equality fns */ FmgrInfo *eqfunctions; /* per-field lookup data for equality fns */
HeapTuple priorTuple; /* most recently returned tuple, or NULL */ HeapTuple priorTuple; /* most recently returned tuple, or NULL */
MemoryContext tempContext; /* short-term context for comparisons */ MemoryContext tempContext; /* short-term context for comparisons */
} UniqueState; } UniqueState;
/* ----------------
* HashState information
* ----------------
*/
typedef struct HashState
{
PlanState ps; /* its first field is NodeTag */
HashJoinTable hashtable; /* hash table for the hashjoin */
} HashState;
/* ---------------- /* ----------------
* SetOpState information * SetOpState information
* *
...@@ -761,7 +773,7 @@ typedef struct UniqueState ...@@ -761,7 +773,7 @@ typedef struct UniqueState
*/ */
typedef struct SetOpState typedef struct SetOpState
{ {
CommonState cstate; /* its first field is NodeTag */ PlanState ps; /* its first field is NodeTag */
FmgrInfo *eqfunctions; /* per-field lookup data for equality fns */ FmgrInfo *eqfunctions; /* per-field lookup data for equality fns */
bool subplan_done; /* has subplan returned EOF? */ bool subplan_done; /* has subplan returned EOF? */
long numLeft; /* number of left-input dups of cur group */ long numLeft; /* number of left-input dups of cur group */
...@@ -794,7 +806,9 @@ typedef enum ...@@ -794,7 +806,9 @@ typedef enum
typedef struct LimitState typedef struct LimitState
{ {
CommonState cstate; /* its first field is NodeTag */ PlanState ps; /* its first field is NodeTag */
Node *limitOffset; /* OFFSET parameter, or NULL if none */
Node *limitCount; /* COUNT parameter, or NULL if none */
long offset; /* current OFFSET value */ long offset; /* current OFFSET value */
long count; /* current COUNT, if any */ long count; /* current COUNT, if any */
bool noCount; /* if true, ignore count */ bool noCount; /* if true, ignore count */
...@@ -803,46 +817,16 @@ typedef struct LimitState ...@@ -803,46 +817,16 @@ typedef struct LimitState
TupleTableSlot *subSlot; /* tuple last obtained from subplan */ TupleTableSlot *subSlot; /* tuple last obtained from subplan */
} LimitState; } LimitState;
/* ---------------------
/* ---------------- * SubPlanState information
* HashState information * ---------------------
*
* hashtable hash table for the hashjoin
* ----------------
*/ */
typedef struct HashState typedef struct SubPlanState
{ {
CommonState cstate; /* its first field is NodeTag */ PlanState ps; /* its first field is NodeTag */
HashJoinTable hashtable; PlanState *planstate; /* subselect plan's state tree */
} HashState; bool needShutdown; /* TRUE = need to shutdown subplan */
HeapTuple curTuple; /* copy of most recent tuple from subplan */
#ifdef NOT_USED } SubPlanState;
/* -----------------------
* TeeState information
* leftPlace : next item in the queue unseen by the left parent
* rightPlace : next item in the queue unseen by the right parent
* lastPlace : last item in the queue
* bufferRelname : name of the relation used as the buffer queue
* bufferRel : the relation used as the buffer queue
* mcxt : for now, tee's have their own memory context
* may be cleaned up later if portals are cleaned up
*
* initially, a Tee starts with [left/right]Place variables set to -1.
* on cleanup, queue is free'd when both leftPlace and rightPlace = -1
* -------------------------
*/
typedef struct TeeState
{
CommonState cstate; /* its first field is NodeTag */
int tee_leftPlace,
tee_rightPlace,
tee_lastPlace;
char *tee_bufferRelname;
Relation tee_bufferRel;
MemoryContext tee_mcxt;
HeapScanDesc tee_leftScanDesc,
tee_rightScanDesc;
} TeeState;
#endif
#endif /* EXECNODES_H */ #endif /* EXECNODES_H */
...@@ -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: nodes.h,v 1.125 2002/11/30 05:21:03 tgl Exp $ * $Id: nodes.h,v 1.126 2002/12/05 15:50:38 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -18,43 +18,84 @@ ...@@ -18,43 +18,84 @@
* The first field of every node is NodeTag. Each node created (with makeNode) * The first field of every node is NodeTag. Each node created (with makeNode)
* will have one of the following tags as the value of its first field. * will have one of the following tags as the value of its first field.
* *
* Note that the number of the node tags are not contiguous. We left holes * Note that the numbers of the node tags are not contiguous. We left holes
* here so that we can add more tags without changing the existing enum's. * here so that we can add more tags without changing the existing enum's.
* (Since node tag numbers never exist outside backend memory, there's no
* real harm in renumbering, it just costs a full rebuild ...)
*/ */
typedef enum NodeTag typedef enum NodeTag
{ {
T_Invalid = 0, T_Invalid = 0,
/*
* TAGS FOR EXECUTOR NODES (execnodes.h)
*/
T_IndexInfo = 10,
T_ResultRelInfo,
T_TupleTableSlot,
T_ExprContext,
T_ProjectionInfo,
T_JunkFilter,
T_EState,
/* /*
* TAGS FOR PLAN NODES (plannodes.h) * TAGS FOR PLAN NODES (plannodes.h)
*/ */
T_Plan = 10, T_Plan = 100,
T_Result, T_Result,
T_Append, T_Append,
T_Scan, T_Scan,
T_SeqScan, T_SeqScan,
T_IndexScan, T_IndexScan,
T_TidScan,
T_SubqueryScan,
T_FunctionScan,
T_Join, T_Join,
T_NestLoop, T_NestLoop,
T_MergeJoin, T_MergeJoin,
T_HashJoin, T_HashJoin,
T_Limit,
T_Material, T_Material,
T_Sort, T_Sort,
T_Group,
T_Agg, T_Agg,
T_Unique, T_Unique,
T_Hash, T_Hash,
T_SetOp, T_SetOp,
T_Group, T_Limit,
T_SubPlan, T_SubPlan,
T_TidScan,
T_SubqueryScan, /*
T_FunctionScan, * TAGS FOR PLAN STATE NODES (execnodes.h)
*
* These should correspond one-to-one with Plan node types.
*/
T_PlanState = 200,
T_ResultState,
T_AppendState,
T_ScanState,
T_SeqScanState,
T_IndexScanState,
T_TidScanState,
T_SubqueryScanState,
T_FunctionScanState,
T_JoinState,
T_NestLoopState,
T_MergeJoinState,
T_HashJoinState,
T_MaterialState,
T_SortState,
T_GroupState,
T_AggState,
T_UniqueState,
T_HashState,
T_SetOpState,
T_LimitState,
T_SubPlanState,
/* /*
* TAGS FOR PRIMITIVE NODES (primnodes.h) * TAGS FOR PRIMITIVE NODES (primnodes.h)
*/ */
T_Resdom = 100, T_Resdom = 300,
T_Fjoin, T_Fjoin,
T_Expr, T_Expr,
T_Var, T_Var,
...@@ -74,7 +115,7 @@ typedef enum NodeTag ...@@ -74,7 +115,7 @@ typedef enum NodeTag
/* /*
* TAGS FOR PLANNER NODES (relation.h) * TAGS FOR PLANNER NODES (relation.h)
*/ */
T_RelOptInfo = 200, T_RelOptInfo = 400,
T_IndexOptInfo, T_IndexOptInfo,
T_Path, T_Path,
T_IndexPath, T_IndexPath,
...@@ -90,48 +131,16 @@ typedef enum NodeTag ...@@ -90,48 +131,16 @@ typedef enum NodeTag
T_JoinInfo, T_JoinInfo,
T_InnerIndexscanInfo, T_InnerIndexscanInfo,
/*
* TAGS FOR EXECUTOR NODES (execnodes.h)
*/
T_IndexInfo = 300,
T_ResultRelInfo,
T_TupleTableSlot,
T_ExprContext,
T_ProjectionInfo,
T_JunkFilter,
T_EState,
T_CommonState,
T_ResultState,
T_AppendState,
T_CommonScanState,
T_ScanState,
T_IndexScanState,
T_JoinState,
T_NestLoopState,
T_MergeJoinState,
T_HashJoinState,
T_MaterialState,
T_AggState,
T_GroupState,
T_SortState,
T_UniqueState,
T_HashState,
T_TidScanState,
T_SubqueryScanState,
T_SetOpState,
T_LimitState,
T_FunctionScanState,
/* /*
* TAGS FOR MEMORY NODES (memnodes.h) * TAGS FOR MEMORY NODES (memnodes.h)
*/ */
T_MemoryContext = 400, T_MemoryContext = 500,
T_AllocSetContext, T_AllocSetContext,
/* /*
* TAGS FOR VALUE NODES (pg_list.h) * TAGS FOR VALUE NODES (pg_list.h)
*/ */
T_Value = 500, T_Value = 600,
T_List, T_List,
T_Integer, T_Integer,
T_Float, T_Float,
...@@ -142,7 +151,7 @@ typedef enum NodeTag ...@@ -142,7 +151,7 @@ typedef enum NodeTag
/* /*
* TAGS FOR PARSE TREE NODES (parsenodes.h) * TAGS FOR PARSE TREE NODES (parsenodes.h)
*/ */
T_Query = 600, T_Query = 700,
T_InsertStmt, T_InsertStmt,
T_DeleteStmt, T_DeleteStmt,
T_UpdateStmt, T_UpdateStmt,
...@@ -208,7 +217,7 @@ typedef enum NodeTag ...@@ -208,7 +217,7 @@ typedef enum NodeTag
T_ExecuteStmt, T_ExecuteStmt,
T_DeallocateStmt, T_DeallocateStmt,
T_A_Expr = 700, T_A_Expr = 800,
T_ColumnRef, T_ColumnRef,
T_ParamRef, T_ParamRef,
T_A_Const, T_A_Const,
...@@ -248,7 +257,7 @@ typedef enum NodeTag ...@@ -248,7 +257,7 @@ typedef enum NodeTag
/* /*
* TAGS FOR FUNCTION-CALL CONTEXT AND RESULTINFO NODES (see fmgr.h) * TAGS FOR FUNCTION-CALL CONTEXT AND RESULTINFO NODES (see fmgr.h)
*/ */
T_TriggerData = 800, /* in commands/trigger.h */ T_TriggerData = 900, /* in commands/trigger.h */
T_ReturnSetInfo /* in nodes/execnodes.h */ T_ReturnSetInfo /* in nodes/execnodes.h */
} NodeTag; } NodeTag;
......
...@@ -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: params.h,v 1.18 2002/11/25 21:29:42 tgl Exp $ * $Id: params.h,v 1.19 2002/12/05 15:50:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -88,7 +88,7 @@ typedef ParamListInfoData *ParamListInfo; ...@@ -88,7 +88,7 @@ typedef ParamListInfoData *ParamListInfo;
* array of ParamExecData records, which is referenced through * array of ParamExecData records, which is referenced through
* es_param_exec_vals or ecxt_param_exec_vals. * es_param_exec_vals or ecxt_param_exec_vals.
* *
* If execPlan is not NULL, it points to a SubPlan node that needs to * If execPlan is not NULL, it points to a SubPlanState node that needs to
* be executed to produce the value. (This is done so that we can have * be executed to produce the value. (This is done so that we can have
* lazy evaluation of InitPlans: they aren't executed until/unless a * lazy evaluation of InitPlans: they aren't executed until/unless a
* result value is needed.) Otherwise the value is assumed to be valid * result value is needed.) Otherwise the value is assumed to be valid
...@@ -98,7 +98,7 @@ typedef ParamListInfoData *ParamListInfo; ...@@ -98,7 +98,7 @@ typedef ParamListInfoData *ParamListInfo;
typedef struct ParamExecData typedef struct ParamExecData
{ {
void *execPlan; /* should be "SubPlan *" */ void *execPlan; /* should be "SubPlanState *" */
Datum value; Datum value;
bool isnull; bool isnull;
} ParamExecData; } ParamExecData;
......
...@@ -7,52 +7,15 @@ ...@@ -7,52 +7,15 @@
* 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: plannodes.h,v 1.61 2002/11/30 00:08:22 tgl Exp $ * $Id: plannodes.h,v 1.62 2002/12/05 15:50:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef PLANNODES_H #ifndef PLANNODES_H
#define PLANNODES_H #define PLANNODES_H
#include "nodes/execnodes.h" #include "access/sdir.h"
#include "nodes/primnodes.h"
/* ----------------------------------------------------------------
* Executor State types are used in the plannode structures
* so we have to include their definitions too.
*
* Node Type node information used by executor
*
* control nodes
*
* Result ResultState resstate;
* Append AppendState appendstate;
*
* scan nodes
*
* Scan *** CommonScanState scanstate;
* IndexScan IndexScanState indxstate;
* SubqueryScan SubqueryScanState subquerystate;
* FunctionScan FunctionScanState functionstate;
*
* (*** nodes which inherit Scan also inherit scanstate)
*
* join nodes
*
* NestLoop NestLoopState nlstate;
* MergeJoin MergeJoinState mergestate;
* HashJoin HashJoinState hashjoinstate;
*
* materialize nodes
*
* Material MaterialState matstate;
* Sort SortState sortstate;
* Unique UniqueState uniquestate;
* SetOp SetOpState setopstate;
* Limit LimitState limitstate;
* Hash HashState hashstate;
*
* ----------------------------------------------------------------
*/
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
...@@ -62,45 +25,47 @@ ...@@ -62,45 +25,47 @@
/* ---------------- /* ----------------
* Plan node * Plan node
*
* All plan nodes "derive" from the Plan structure by having the
* Plan structure as the first field. This ensures that everything works
* when nodes are cast to Plan's. (node pointers are frequently cast to Plan*
* when passed around generically in the executor)
*
* We never actually instantiate any Plan nodes; this is just the common
* abstract superclass for all Plan-type nodes.
* ---------------- * ----------------
*/ */
typedef struct Plan typedef struct Plan
{ {
NodeTag type; NodeTag type;
/* estimated execution costs for plan (see costsize.c for more info) */ /*
* estimated execution costs for plan (see costsize.c for more info)
*/
Cost startup_cost; /* cost expended before fetching any Cost startup_cost; /* cost expended before fetching any
* tuples */ * tuples */
Cost total_cost; /* total cost (assuming all tuples Cost total_cost; /* total cost (assuming all tuples
* fetched) */ * fetched) */
/* /*
* planner's estimate of result size (note: LIMIT, if any, is not * planner's estimate of result size of this plan step
* considered in setting plan_rows)
*/ */
double plan_rows; /* number of rows plan is expected to emit */ double plan_rows; /* number of rows plan is expected to emit */
int plan_width; /* average row width in bytes */ int plan_width; /* average row width in bytes */
/* /*
* execution state data. Having Plan point to this, rather than the * Common structural data for all Plan types.
* other way round, is 100% bogus.
*/ */
EState *state; /* at execution time, state's of List *targetlist; /* target list to be computed at this node */
* individual nodes point to one EState List *qual; /* implicitly-ANDed qual conditions */
* for the whole top-level plan */ struct Plan *lefttree; /* input plan tree(s) */
struct Plan *righttree;
struct Instrumentation *instrument; /* Optional runtime stats for this List *initPlan; /* Init Plan nodes (un-correlated expr
* plan node */ * subselects) */
/* /*
* Common structural data for all Plan types. XXX chgParam is runtime * Information for management of parameter-change-driven rescanning
* data and should be in the EState, not here.
*/ */
List *targetlist;
List *qual; /* implicitly-ANDed qual conditions */
struct Plan *lefttree;
struct Plan *righttree;
List *extParam; /* indices of _all_ _external_ PARAM_EXEC List *extParam; /* indices of _all_ _external_ PARAM_EXEC
* for this plan in global * for this plan in global
* es_param_exec_vals. Params from * es_param_exec_vals. Params from
...@@ -108,10 +73,6 @@ typedef struct Plan ...@@ -108,10 +73,6 @@ typedef struct Plan
* included, but their execParam-s are * included, but their execParam-s are
* here!!! */ * here!!! */
List *locParam; /* someones from setParam-s */ List *locParam; /* someones from setParam-s */
List *chgParam; /* list of changed ones from the above */
List *initPlan; /* Init Plan nodes (un-correlated expr
* subselects) */
List *subPlan; /* Other SubPlan nodes */
/* /*
* We really need in some TopPlan node to store range table and * We really need in some TopPlan node to store range table and
...@@ -134,20 +95,6 @@ typedef struct Plan ...@@ -134,20 +95,6 @@ typedef struct Plan
#define outerPlan(node) (((Plan *)(node))->lefttree) #define outerPlan(node) (((Plan *)(node))->lefttree)
/*
* ===============
* Top-level nodes
* ===============
*/
/*
* all plan nodes "derive" from the Plan structure by having the
* Plan structure as the first field. This ensures that everything works
* when nodes are cast to Plan's. (node pointers are frequently cast to Plan*
* when passed around generically in the executor)
*/
/* ---------------- /* ----------------
* Result node - * Result node -
* If no outer plan, evaluate a variable-free targetlist. * If no outer plan, evaluate a variable-free targetlist.
...@@ -163,7 +110,6 @@ typedef struct Result ...@@ -163,7 +110,6 @@ typedef struct Result
{ {
Plan plan; Plan plan;
Node *resconstantqual; Node *resconstantqual;
ResultState *resstate;
} Result; } Result;
/* ---------------- /* ----------------
...@@ -182,7 +128,6 @@ typedef struct Append ...@@ -182,7 +128,6 @@ typedef struct Append
Plan plan; Plan plan;
List *appendplans; List *appendplans;
bool isTarget; bool isTarget;
AppendState *appendstate;
} Append; } Append;
/* /*
...@@ -194,7 +139,6 @@ typedef struct Scan ...@@ -194,7 +139,6 @@ typedef struct Scan
{ {
Plan plan; Plan plan;
Index scanrelid; /* relid is index into the range table */ Index scanrelid; /* relid is index into the range table */
CommonScanState *scanstate;
} Scan; } Scan;
/* ---------------- /* ----------------
...@@ -214,7 +158,6 @@ typedef struct IndexScan ...@@ -214,7 +158,6 @@ typedef struct IndexScan
List *indxqual; List *indxqual;
List *indxqualorig; List *indxqualorig;
ScanDirection indxorderdir; ScanDirection indxorderdir;
IndexScanState *indxstate;
} IndexScan; } IndexScan;
/* ---------------- /* ----------------
...@@ -224,9 +167,7 @@ typedef struct IndexScan ...@@ -224,9 +167,7 @@ typedef struct IndexScan
typedef struct TidScan typedef struct TidScan
{ {
Scan scan; Scan scan;
bool needRescan;
List *tideval; List *tideval;
TidScanState *tidstate;
} TidScan; } TidScan;
/* ---------------- /* ----------------
...@@ -257,7 +198,6 @@ typedef struct FunctionScan ...@@ -257,7 +198,6 @@ typedef struct FunctionScan
{ {
Scan scan; Scan scan;
/* no other fields needed at present */ /* no other fields needed at present */
/* scan.scanstate actually points at a FunctionScanState node */
} FunctionScan; } FunctionScan;
/* /*
...@@ -296,7 +236,6 @@ typedef struct Join ...@@ -296,7 +236,6 @@ typedef struct Join
typedef struct NestLoop typedef struct NestLoop
{ {
Join join; Join join;
NestLoopState *nlstate;
} NestLoop; } NestLoop;
/* ---------------- /* ----------------
...@@ -307,7 +246,6 @@ typedef struct MergeJoin ...@@ -307,7 +246,6 @@ typedef struct MergeJoin
{ {
Join join; Join join;
List *mergeclauses; List *mergeclauses;
MergeJoinState *mergestate;
} MergeJoin; } MergeJoin;
/* ---------------- /* ----------------
...@@ -318,9 +256,40 @@ typedef struct HashJoin ...@@ -318,9 +256,40 @@ typedef struct HashJoin
{ {
Join join; Join join;
List *hashclauses; List *hashclauses;
HashJoinState *hashjoinstate;
} HashJoin; } HashJoin;
/* ----------------
* materialization node
* ----------------
*/
typedef struct Material
{
Plan plan;
} Material;
/* ----------------
* sort node
* ----------------
*/
typedef struct Sort
{
Plan plan;
int keycount;
} Sort;
/* ---------------
* group node -
* Used for queries with GROUP BY (but no aggregates) specified.
* The input must be presorted according to the grouping columns.
* ---------------
*/
typedef struct Group
{
Plan plan;
int numCols; /* number of grouping columns */
AttrNumber *grpColIdx; /* their indexes in the target list */
} Group;
/* --------------- /* ---------------
* aggregate node * aggregate node
* *
...@@ -349,44 +318,8 @@ typedef struct Agg ...@@ -349,44 +318,8 @@ typedef struct Agg
int numCols; /* number of grouping columns */ int numCols; /* number of grouping columns */
AttrNumber *grpColIdx; /* their indexes in the target list */ AttrNumber *grpColIdx; /* their indexes in the target list */
long numGroups; /* estimated number of groups in input */ long numGroups; /* estimated number of groups in input */
AggState *aggstate;
} Agg; } Agg;
/* ---------------
* group node -
* Used for queries with GROUP BY (but no aggregates) specified.
* The input must be presorted according to the grouping columns.
* ---------------
*/
typedef struct Group
{
Plan plan;
int numCols; /* number of grouping columns */
AttrNumber *grpColIdx; /* their indexes in the target list */
GroupState *grpstate;
} Group;
/* ----------------
* materialization node
* ----------------
*/
typedef struct Material
{
Plan plan;
MaterialState *matstate;
} Material;
/* ----------------
* sort node
* ----------------
*/
typedef struct Sort
{
Plan plan;
int keycount;
SortState *sortstate;
} Sort;
/* ---------------- /* ----------------
* unique node * unique node
* ---------------- * ----------------
...@@ -397,9 +330,18 @@ typedef struct Unique ...@@ -397,9 +330,18 @@ typedef struct Unique
int numCols; /* number of columns to check for int numCols; /* number of columns to check for
* uniqueness */ * uniqueness */
AttrNumber *uniqColIdx; /* indexes into the target list */ AttrNumber *uniqColIdx; /* indexes into the target list */
UniqueState *uniquestate;
} Unique; } Unique;
/* ----------------
* hash build node
* ----------------
*/
typedef struct Hash
{
Plan plan;
List *hashkeys;
} Hash;
/* ---------------- /* ----------------
* setop node * setop node
* ---------------- * ----------------
...@@ -420,7 +362,6 @@ typedef struct SetOp ...@@ -420,7 +362,6 @@ typedef struct SetOp
* duplicate-ness */ * duplicate-ness */
AttrNumber *dupColIdx; /* indexes into the target list */ AttrNumber *dupColIdx; /* indexes into the target list */
AttrNumber flagColIdx; AttrNumber flagColIdx;
SetOpState *setopstate;
} SetOp; } SetOp;
/* ---------------- /* ----------------
...@@ -432,44 +373,13 @@ typedef struct Limit ...@@ -432,44 +373,13 @@ typedef struct Limit
Plan plan; Plan plan;
Node *limitOffset; /* OFFSET parameter, or NULL if none */ Node *limitOffset; /* OFFSET parameter, or NULL if none */
Node *limitCount; /* COUNT parameter, or NULL if none */ Node *limitCount; /* COUNT parameter, or NULL if none */
LimitState *limitstate;
} Limit; } Limit;
/* ----------------
* hash build node
* ----------------
*/
typedef struct Hash
{
Plan plan;
List *hashkeys;
HashState *hashstate;
} Hash;
#ifdef NOT_USED
/* -------------------
* Tee node information
*
* leftParent : the left parent of this node
* rightParent: the right parent of this node
* -------------------
*/
typedef struct Tee
{
Plan plan;
Plan *leftParent;
Plan *rightParent;
TeeState *teestate;
char *teeTableName; /* the name of the table to materialize
* the tee into */
List *rtentries; /* the range table for the plan below the
* Tee may be different than the parent
* plans */
} Tee;
#endif
/* --------------------- /* ---------------------
* SubPlan node * SubPlan node
*
* XXX Perhaps does not belong in this file? It's not really a Plan node.
* Should we make it inherit from Plan anyway?
* --------------------- * ---------------------
*/ */
typedef struct SubPlan typedef struct SubPlan
...@@ -489,12 +399,7 @@ typedef struct SubPlan ...@@ -489,12 +399,7 @@ typedef struct SubPlan
* about what to do with subselect's * about what to do with subselect's
* results */ * results */
/* struct SubPlanState *pstate; /* XXX TEMPORARY HACK */
* Remaining fields are working state for executor; not used in
* planning
*/
bool needShutdown; /* TRUE = need to shutdown subplan */
HeapTuple curTuple; /* copy of most recent tuple from subplan */
} SubPlan; } SubPlan;
#endif /* PLANNODES_H */ #endif /* PLANNODES_H */
...@@ -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: print.h,v 1.19 2002/09/04 20:31:44 momjian Exp $ * $Id: print.h,v 1.20 2002/12/05 15:50:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -15,10 +15,10 @@ ...@@ -15,10 +15,10 @@
#define PRINT_H #define PRINT_H
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
#include "nodes/plannodes.h" #include "nodes/execnodes.h"
#define nodeDisplay pprint #define nodeDisplay(x) pprint(x)
extern void print(void *obj); extern void print(void *obj);
extern void pprint(void *obj); extern void pprint(void *obj);
......
...@@ -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;
/* /*
......
...@@ -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: pquery.h,v 1.22 2002/09/04 20:31:45 momjian Exp $ * $Id: pquery.h,v 1.23 2002/12/05 15:50:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -21,8 +21,6 @@ ...@@ -21,8 +21,6 @@
extern void ProcessQuery(Query *parsetree, Plan *plan, CommandDest dest, extern void ProcessQuery(Query *parsetree, Plan *plan, CommandDest dest,
char *completionTag); char *completionTag);
extern EState *CreateExecutorState(void);
extern Portal PreparePortal(char *portalName); extern Portal PreparePortal(char *portalName);
#endif /* PQUERY_H */ #endif /* PQUERY_H */
...@@ -3,19 +3,16 @@ ...@@ -3,19 +3,16 @@
* portal.h * portal.h
* POSTGRES portal definitions. * POSTGRES portal definitions.
* *
* A portal is an abstraction which represents the execution state of
* a running query (specifically, a CURSOR).
* *
* 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: portal.h,v 1.35 2002/09/04 20:31:45 momjian Exp $ * $Id: portal.h,v 1.36 2002/12/05 15:50:39 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
/*
* Note:
* A portal is an abstraction which represents the execution state of
* a running query (specifically, a CURSOR).
*/
#ifndef PORTAL_H #ifndef PORTAL_H
#define PORTAL_H #define PORTAL_H
...@@ -30,8 +27,6 @@ typedef struct PortalData ...@@ -30,8 +27,6 @@ typedef struct PortalData
char *name; /* Portal's name */ char *name; /* Portal's name */
MemoryContext heap; /* subsidiary memory */ MemoryContext heap; /* subsidiary memory */
QueryDesc *queryDesc; /* Info about query associated with portal */ QueryDesc *queryDesc; /* Info about query associated with portal */
TupleDesc attinfo;
EState *state; /* Execution state of query */
bool atStart; /* T => fetch backwards is not allowed */ bool atStart; /* T => fetch backwards is not allowed */
bool atEnd; /* T => fetch forwards is not allowed */ bool atEnd; /* T => fetch forwards is not allowed */
void (*cleanup) (Portal); /* Cleanup routine (optional) */ void (*cleanup) (Portal); /* Cleanup routine (optional) */
...@@ -47,8 +42,6 @@ typedef struct PortalData ...@@ -47,8 +42,6 @@ typedef struct PortalData
* Access macros for Portal ... use these in preference to field access. * Access macros for Portal ... use these in preference to field access.
*/ */
#define PortalGetQueryDesc(portal) ((portal)->queryDesc) #define PortalGetQueryDesc(portal) ((portal)->queryDesc)
#define PortalGetTupleDesc(portal) ((portal)->attinfo)
#define PortalGetState(portal) ((portal)->state)
#define PortalGetHeapMemory(portal) ((portal)->heap) #define PortalGetHeapMemory(portal) ((portal)->heap)
/* /*
...@@ -64,7 +57,6 @@ extern Portal CreatePortal(char *name); ...@@ -64,7 +57,6 @@ extern Portal CreatePortal(char *name);
extern void PortalDrop(Portal portal); extern void PortalDrop(Portal portal);
extern Portal GetPortalByName(char *name); extern Portal GetPortalByName(char *name);
extern void PortalSetQuery(Portal portal, QueryDesc *queryDesc, extern void PortalSetQuery(Portal portal, QueryDesc *queryDesc,
TupleDesc attinfo, EState *state,
void (*cleanup) (Portal portal)); void (*cleanup) (Portal portal));
#endif /* PORTAL_H */ #endif /* PORTAL_H */
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* procedural language * procedural language
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.71 2002/11/30 21:25:08 tgl Exp $ * $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.72 2002/12/05 15:50:39 tgl Exp $
* *
* This software is copyrighted by Jan Wieck - Hamburg. * This software is copyrighted by Jan Wieck - Hamburg.
* *
...@@ -3583,7 +3583,6 @@ exec_simple_check_plan(PLpgSQL_expr * expr) ...@@ -3583,7 +3583,6 @@ exec_simple_check_plan(PLpgSQL_expr * expr)
if (plan->lefttree != NULL || if (plan->lefttree != NULL ||
plan->righttree != NULL || plan->righttree != NULL ||
plan->initPlan != NULL || plan->initPlan != NULL ||
plan->subPlan != NULL ||
plan->qual != NULL || plan->qual != NULL ||
((Result *) plan)->resconstantqual != NULL) ((Result *) plan)->resconstantqual != NULL)
return; return;
......
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