From 1fd0c59e25063e664f8a5cee6f723470c5979544 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 5 Dec 2002 15:50:39 +0000 Subject: [PATCH] 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. --- src/backend/commands/explain.c | 189 ++++++++----- src/backend/commands/portalcmds.c | 14 +- src/backend/commands/prepare.c | 25 +- src/backend/executor/README | 23 +- src/backend/executor/execAmi.c | 157 +++++------ src/backend/executor/execMain.c | 263 ++++++++---------- src/backend/executor/execProcnode.c | 450 +++++++++++++++--------------- src/backend/executor/execQual.c | 168 +++++++++++- src/backend/executor/execScan.c | 24 +- src/backend/executor/execTuples.c | 10 +- src/backend/executor/execUtils.c | 79 +++--- src/backend/executor/functions.c | 147 +++++----- src/backend/executor/nodeAgg.c | 270 +++++++++--------- src/backend/executor/nodeAppend.c | 126 ++++----- src/backend/executor/nodeFunctionscan.c | 140 ++++------ src/backend/executor/nodeGroup.c | 129 ++++----- src/backend/executor/nodeHash.c | 83 +++--- src/backend/executor/nodeHashjoin.c | 227 ++++++++-------- src/backend/executor/nodeIndexscan.c | 232 +++++++--------- src/backend/executor/nodeLimit.c | 164 ++++++----- src/backend/executor/nodeMaterial.c | 104 +++---- src/backend/executor/nodeMergejoin.c | 383 +++++++++++++------------- src/backend/executor/nodeNestloop.c | 153 +++++------ src/backend/executor/nodeResult.c | 122 ++++----- src/backend/executor/nodeSeqscan.c | 147 +++++----- src/backend/executor/nodeSetOp.c | 150 +++++----- src/backend/executor/nodeSort.c | 126 ++++----- src/backend/executor/nodeSubplan.c | 131 +++++---- src/backend/executor/nodeSubqueryscan.c | 109 ++++---- src/backend/executor/nodeTidscan.c | 189 ++++++------- src/backend/executor/nodeUnique.c | 102 +++---- src/backend/executor/spi.c | 110 ++++---- src/backend/nodes/copyfuncs.c | 466 +++----------------------------- src/backend/nodes/equalfuncs.c | 209 +------------- src/backend/nodes/outfuncs.c | 14 +- src/backend/optimizer/plan/createplan.c | 33 +-- src/backend/optimizer/plan/setrefs.c | 67 +++-- src/backend/optimizer/plan/subselect.c | 36 +-- src/backend/optimizer/util/pathnode.c | 6 +- src/backend/tcop/pquery.c | 98 ++----- src/backend/utils/mmgr/portalmem.c | 15 +- src/include/executor/execdesc.h | 22 +- src/include/executor/executor.h | 61 +++-- src/include/executor/nodeAgg.h | 12 +- src/include/executor/nodeAppend.h | 12 +- src/include/executor/nodeFunctionscan.h | 16 +- src/include/executor/nodeGroup.h | 12 +- src/include/executor/nodeHash.h | 13 +- src/include/executor/nodeHashjoin.h | 13 +- src/include/executor/nodeIndexscan.h | 19 +- src/include/executor/nodeLimit.h | 12 +- src/include/executor/nodeMaterial.h | 16 +- src/include/executor/nodeMergejoin.h | 14 +- src/include/executor/nodeNestloop.h | 13 +- src/include/executor/nodeResult.h | 12 +- src/include/executor/nodeSeqscan.h | 16 +- src/include/executor/nodeSetOp.h | 12 +- src/include/executor/nodeSort.h | 16 +- src/include/executor/nodeSubplan.h | 20 +- src/include/executor/nodeSubqueryscan.h | 12 +- src/include/executor/nodeTidscan.h | 17 +- src/include/executor/nodeUnique.h | 12 +- src/include/nodes/execnodes.h | 310 ++++++++++----------- src/include/nodes/nodes.h | 103 +++---- src/include/nodes/params.h | 6 +- src/include/nodes/plannodes.h | 233 +++++----------- src/include/nodes/print.h | 6 +- src/include/nodes/relation.h | 5 +- src/include/tcop/pquery.h | 4 +- src/include/utils/portal.h | 16 +- src/pl/plpgsql/src/pl_exec.c | 3 +- 71 files changed, 3001 insertions(+), 3727 deletions(-) diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 0e6ca88fd4..e2d1a6eeab 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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,17 +34,19 @@ typedef struct ExplainState { /* options */ bool printCost; /* print cost */ - bool printNodes; /* do nodeToString() instead */ - bool printAnalyze; /* print actual times */ + bool printNodes; /* do nodeToString() too */ + bool printAnalyze; /* print actual times */ /* other states */ List *rtable; /* range table */ } ExplainState; -static StringInfo Explain_PlanToString(Plan *plan, ExplainState *es); static void ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate); -static void explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, - int indent, ExplainState *es); +static double elapsed_time(struct timeval *starttime); +static void explain_outNode(StringInfo str, + Plan *plan, PlanState *planstate, + Plan *outer_plan, + int indent, ExplainState *es); static void show_scan_qual(List *qual, bool is_or_qual, const char *qlabel, int scanrelid, Plan *outer_plan, StringInfo str, int indent, ExplainState *es); @@ -116,8 +118,11 @@ static void ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate) { Plan *plan; + QueryDesc *queryDesc; ExplainState *es; + StringInfo str; double totaltime = 0; + struct timeval starttime; /* planner will not cope with utility statements */ if (query->commandType == CMD_UTILITY) @@ -136,41 +141,34 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate) if (plan == NULL) 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 */ if (stmt->analyze) { - struct timeval starttime; - struct timeval endtime; - - /* - * Set up the instrumentation for the top node. This will cascade - * during plan initialisation - */ - plan->instrument = InstrAlloc(); + /* run the plan */ + ExecutorRun(queryDesc, ForwardScanDirection, 0L); - gettimeofday(&starttime, NULL); - ProcessQuery(query, plan, None, NULL); - CommandCounterIncrement(); - gettimeofday(&endtime, NULL); + /* We can't clean up 'till we're done printing the stats... */ - endtime.tv_sec -= starttime.tv_sec; - 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; + totaltime += elapsed_time(&starttime); } es = (ExplainState *) palloc0(sizeof(ExplainState)); es->printCost = true; /* default */ - - if (stmt->verbose) - es->printNodes = true; - + es->printNodes = stmt->verbose; + es->printAnalyze = stmt->analyze; es->rtable = query->rtable; if (es->printNodes) @@ -193,33 +191,73 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate) } } + str = makeStringInfo(); + if (es->printCost) { - StringInfo str; + explain_outNode(str, plan, queryDesc->planstate, + NULL, 0, es); + } - str = Explain_PlanToString(plan, es); + /* + * Close down the query and free resources. Include time for this + * in the total runtime. + */ + gettimeofday(&starttime, NULL); + + ExecutorEnd(queryDesc); + CommandCounterIncrement(); + + totaltime += elapsed_time(&starttime); + + if (es->printCost) + { if (stmt->analyze) appendStringInfo(str, "Total runtime: %.2f msec\n", 1000.0 * totaltime); do_text_output_multiline(tstate, str->data); - pfree(str->data); - pfree(str); } + pfree(str->data); + pfree(str); 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 - * 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 * side of a join with the current node. This is only interesting for * deciphering runtime keys of an inner indexscan. */ 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) { List *l; @@ -410,18 +448,23 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, plan->startup_cost, plan->total_cost, 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)", - 1000.0 * plan->instrument->startup / nloops, - 1000.0 * plan->instrument->total / nloops, - plan->instrument->ntuples / nloops, - plan->instrument->nloops); - es->printAnalyze = true; + 1000.0 * planstate->instrument->startup / nloops, + 1000.0 * planstate->instrument->total / nloops, + planstate->instrument->ntuples / nloops, + planstate->instrument->nloops); } - else if( es->printAnalyze ) + else if (es->printAnalyze) { appendStringInfo(str, " (never executed)"); } @@ -538,6 +581,7 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, if (plan->initPlan) { List *saved_rtable = es->rtable; + List *pslist = planstate->initPlan; List *lst; for (i = 0; i < indent; i++) @@ -545,12 +589,18 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, appendStringInfo(str, " InitPlan\n"); 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++) appendStringInfo(str, " "); appendStringInfo(str, " -> "); - explain_outNode(str, ((SubPlan *) lfirst(lst))->plan, NULL, + explain_outNode(str, subplan->plan, + subplanstate->planstate, + NULL, indent + 4, es); + pslist = lnext(pslist); } es->rtable = saved_rtable; } @@ -561,7 +611,10 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, for (i = 0; i < indent; i++) 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 */ @@ -570,15 +623,20 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, for (i = 0; i < indent; i++) appendStringInfo(str, " "); appendStringInfo(str, " -> "); - explain_outNode(str, innerPlan(plan), outerPlan(plan), + explain_outNode(str, innerPlan(plan), + innerPlanState(planstate), + outerPlan(plan), indent + 3, es); } if (IsA(plan, Append)) { Append *appendplan = (Append *) plan; + AppendState *appendstate = (AppendState *) planstate; List *lst; + int j; + j = 0; foreach(lst, appendplan->appendplans) { Plan *subnode = (Plan *) lfirst(lst); @@ -587,13 +645,18 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, 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)) { SubqueryScan *subqueryscan = (SubqueryScan *) plan; + SubqueryScanState *subquerystate = (SubqueryScanState *) planstate; Plan *subnode = subqueryscan->subplan; RangeTblEntry *rte = rt_fetch(subqueryscan->scan.scanrelid, es->rtable); @@ -606,13 +669,16 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, 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; } /* subPlan-s */ - if (plan->subPlan) + if (planstate->subPlan) { List *saved_rtable = es->rtable; List *lst; @@ -620,29 +686,24 @@ explain_outNode(StringInfo str, Plan *plan, Plan *outer_plan, for (i = 0; i < indent; i++) appendStringInfo(str, " "); 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++) appendStringInfo(str, " "); appendStringInfo(str, " -> "); - explain_outNode(str, ((SubPlan *) lfirst(lst))->plan, NULL, + explain_outNode(str, sp->plan, + sps->planstate, + NULL, indent + 4, es); } 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 */ diff --git a/src/backend/commands/portalcmds.c b/src/backend/commands/portalcmds.c index 812cb05dac..c8607fcf32 100644 --- a/src/backend/commands/portalcmds.c +++ b/src/backend/commands/portalcmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.4 2002/11/13 00:44:08 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.5 2002/12/05 15:50:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -23,6 +23,10 @@ /* * PortalCleanup + * + * Clean up a portal when it's dropped. Since this mainly exists to run + * ExecutorEnd(), it should not be set as the cleanup hook until we have + * called ExecutorStart() on the portal's query. */ void PortalCleanup(Portal portal) @@ -43,7 +47,7 @@ PortalCleanup(Portal portal) /* * tell the executor to shutdown the query */ - ExecutorEnd(PortalGetQueryDesc(portal), PortalGetState(portal)); + ExecutorEnd(PortalGetQueryDesc(portal)); /* * switch back to previous context @@ -116,7 +120,7 @@ PerformPortalFetch(char *name, oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal)); queryDesc = PortalGetQueryDesc(portal); - estate = PortalGetState(portal); + estate = queryDesc->estate; /* * If the requested destination is not the same as the query's @@ -158,7 +162,7 @@ PerformPortalFetch(char *name, else direction = ForwardScanDirection; - ExecutorRun(queryDesc, estate, direction, (long) count); + ExecutorRun(queryDesc, direction, (long) count); if (estate->es_processed > 0) portal->atStart = false; /* OK to back up now */ @@ -172,7 +176,7 @@ PerformPortalFetch(char *name, else direction = BackwardScanDirection; - ExecutorRun(queryDesc, estate, direction, (long) count); + ExecutorRun(queryDesc, direction, (long) count); if (estate->es_processed > 0) portal->atEnd = false; /* OK to go forward now */ diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c index 391ef0bc9c..9a570c8f68 100644 --- a/src/backend/commands/prepare.c +++ b/src/backend/commands/prepare.c @@ -6,7 +6,7 @@ * Copyright (c) 2002, PostgreSQL Global Development Group * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/prepare.c,v 1.8 2002/11/15 00:47:22 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/prepare.c,v 1.9 2002/12/05 15:50:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -49,7 +49,7 @@ static void InitQueryHashTable(void); static void StoreQuery(const char *stmt_name, List *query_list, List *plan_list, List *argtype_list); static QueryHashEntry *FetchQuery(const char *plan_name); -static void RunQuery(QueryDesc *qdesc, EState *state); +static void RunQuery(QueryDesc *qdesc); /* @@ -151,15 +151,12 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest) else { QueryDesc *qdesc; - EState *state; if (log_executor_stats) ResetUsage(); - qdesc = CreateQueryDesc(query, plan, outputDest, NULL); - state = CreateExecutorState(); - - state->es_param_list_info = paramLI; + qdesc = CreateQueryDesc(query, plan, outputDest, NULL, + paramLI, false); if (stmt->into) { @@ -170,7 +167,7 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest) qdesc->dest = None; } - RunQuery(qdesc, state); + RunQuery(qdesc); if (log_executor_stats) ShowUsage("EXECUTOR STATISTICS"); @@ -334,15 +331,11 @@ FetchQueryParams(const char *plan_name) * Actually execute a prepared query. */ static void -RunQuery(QueryDesc *qdesc, EState *state) +RunQuery(QueryDesc *qdesc) { - TupleDesc tupdesc; - - tupdesc = ExecutorStart(qdesc, state); - - ExecutorRun(qdesc, state, state->es_direction, 0L); - - ExecutorEnd(qdesc, state); + ExecutorStart(qdesc); + ExecutorRun(qdesc, ForwardScanDirection, 0L); + ExecutorEnd(qdesc); } /* diff --git a/src/backend/executor/README b/src/backend/executor/README index 0a56c3fa6a..d9b0ea1275 100644 --- a/src/backend/executor/README +++ b/src/backend/executor/README @@ -1,4 +1,4 @@ -$Header: /cvsroot/pgsql/src/backend/executor/README,v 1.1 2001/05/15 00:35:50 tgl Exp $ +$Header: /cvsroot/pgsql/src/backend/executor/README,v 1.2 2002/12/05 15:50:30 tgl Exp $ The Postgres Executor --------------------- @@ -39,6 +39,27 @@ delivered by the plan tree. XXX a great deal more documentation needs to be written here... +Plan Trees and State Trees +-------------------------- + +The plan tree delivered by the planner contains a tree of Plan nodes (struct +types derived from struct Plan). Each Plan node may have expression trees +associated with it, to represent its target list, qualification conditions, +etc. During executor startup we build a parallel tree of identical structure +containing executor state nodes --- every plan and expression node type has +a corresponding executor state node type. Each node in the state tree has a +pointer to its corresponding node in the plan tree, plus executor state data +as needed to implement that node type. This arrangement allows the plan +tree to be completely read-only as far as the executor is concerned: all data +that is modified during execution is in the state tree. Read-only plan trees +make life much simpler for plan caching and reuse. + +Altogether there are four classes of nodes used in these trees: Plan nodes, +their corresponding PlanState nodes, Expr nodes, and their corresponding +ExprState nodes. (Actually, there are also List nodes, which are used as +"glue" in all four kinds of tree.) + + EvalPlanQual (READ COMMITTED update checking) --------------------------------------------- diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c index 1d7bf67f60..4ac4781ec7 100644 --- a/src/backend/executor/execAmi.c +++ b/src/backend/executor/execAmi.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: execAmi.c,v 1.65 2002/11/30 05:21:01 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.66 2002/12/05 15:50:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,12 +19,12 @@ #include "executor/instrument.h" #include "executor/nodeAgg.h" #include "executor/nodeAppend.h" +#include "executor/nodeFunctionscan.h" #include "executor/nodeGroup.h" #include "executor/nodeGroup.h" #include "executor/nodeHash.h" #include "executor/nodeHashjoin.h" #include "executor/nodeIndexscan.h" -#include "executor/nodeTidscan.h" #include "executor/nodeLimit.h" #include "executor/nodeMaterial.h" #include "executor/nodeMergejoin.h" @@ -35,45 +35,45 @@ #include "executor/nodeSort.h" #include "executor/nodeSubplan.h" #include "executor/nodeSubqueryscan.h" -#include "executor/nodeFunctionscan.h" +#include "executor/nodeTidscan.h" #include "executor/nodeUnique.h" /* ---------------------------------------------------------------- * ExecReScan * - * XXX this should be extended to cope with all the node types.. - * * takes the new expression context as an argument, so that * index scans needn't have their scan keys updated separately * - marcel 09/20/94 * ---------------------------------------------------------------- */ void -ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent) +ExecReScan(PlanState *node, ExprContext *exprCtxt) { + /* If collecting timing stats, update them */ if (node->instrument) InstrEndLoop(node->instrument); - if (node->chgParam != NULL) /* Wow! */ + /* If we have changed parameters, propagate that info */ + if (node->chgParam != NIL) { List *lst; foreach(lst, node->initPlan) { - Plan *splan = ((SubPlan *) lfirst(lst))->plan; + PlanState *splan = ((SubPlanState *) lfirst(lst))->planstate; - if (splan->extParam != NULL) /* don't care about child + if (splan->plan->extParam != NIL) /* don't care about child * locParam */ SetChangedParamList(splan, node->chgParam); - if (splan->chgParam != NULL) - ExecReScanSetParamPlan((SubPlan *) lfirst(lst), node); + if (splan->chgParam != NIL) + ExecReScanSetParamPlan((SubPlanState *) lfirst(lst), node); } foreach(lst, node->subPlan) { - Plan *splan = ((SubPlan *) lfirst(lst))->plan; + PlanState *splan = ((SubPlanState *) lfirst(lst))->planstate; - if (splan->extParam != NULL) + if (splan->plan->extParam != NIL) SetChangedParamList(splan, node->chgParam); } /* Well. Now set chgParam for left/right trees. */ @@ -85,76 +85,76 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent) switch (nodeTag(node)) { - case T_SeqScan: - ExecSeqReScan((SeqScan *) node, exprCtxt, parent); + case T_ResultState: + ExecReScanResult((ResultState *) node, exprCtxt); break; - case T_IndexScan: - ExecIndexReScan((IndexScan *) node, exprCtxt, parent); + case T_AppendState: + ExecReScanAppend((AppendState *) node, exprCtxt); break; - case T_TidScan: - ExecTidReScan((TidScan *) node, exprCtxt, parent); + case T_SeqScanState: + ExecSeqReScan((SeqScanState *) node, exprCtxt); break; - case T_SubqueryScan: - ExecSubqueryReScan((SubqueryScan *) node, exprCtxt, parent); + case T_IndexScanState: + ExecIndexReScan((IndexScanState *) node, exprCtxt); break; - case T_FunctionScan: - ExecFunctionReScan((FunctionScan *) node, exprCtxt, parent); + case T_TidScanState: + ExecTidReScan((TidScanState *) node, exprCtxt); break; - case T_Material: - ExecMaterialReScan((Material *) node, exprCtxt, parent); + case T_SubqueryScanState: + ExecSubqueryReScan((SubqueryScanState *) node, exprCtxt); break; - case T_NestLoop: - ExecReScanNestLoop((NestLoop *) node, exprCtxt, parent); + case T_FunctionScanState: + ExecFunctionReScan((FunctionScanState *) node, exprCtxt); break; - case T_HashJoin: - ExecReScanHashJoin((HashJoin *) node, exprCtxt, parent); + case T_NestLoopState: + ExecReScanNestLoop((NestLoopState *) node, exprCtxt); break; - case T_Hash: - ExecReScanHash((Hash *) node, exprCtxt, parent); + case T_MergeJoinState: + ExecReScanMergeJoin((MergeJoinState *) node, exprCtxt); break; - case T_Agg: - ExecReScanAgg((Agg *) node, exprCtxt, parent); + case T_HashJoinState: + ExecReScanHashJoin((HashJoinState *) node, exprCtxt); break; - case T_Group: - ExecReScanGroup((Group *) node, exprCtxt, parent); + case T_MaterialState: + ExecMaterialReScan((MaterialState *) node, exprCtxt); break; - case T_Result: - ExecReScanResult((Result *) node, exprCtxt, parent); + case T_SortState: + ExecReScanSort((SortState *) node, exprCtxt); break; - case T_Unique: - ExecReScanUnique((Unique *) node, exprCtxt, parent); + case T_GroupState: + ExecReScanGroup((GroupState *) node, exprCtxt); break; - case T_SetOp: - ExecReScanSetOp((SetOp *) node, exprCtxt, parent); + case T_AggState: + ExecReScanAgg((AggState *) node, exprCtxt); break; - case T_Limit: - ExecReScanLimit((Limit *) node, exprCtxt, parent); + case T_UniqueState: + ExecReScanUnique((UniqueState *) node, exprCtxt); break; - case T_Sort: - ExecReScanSort((Sort *) node, exprCtxt, parent); + case T_HashState: + ExecReScanHash((HashState *) node, exprCtxt); break; - case T_MergeJoin: - ExecReScanMergeJoin((MergeJoin *) node, exprCtxt, parent); + case T_SetOpState: + ExecReScanSetOp((SetOpState *) node, exprCtxt); break; - case T_Append: - ExecReScanAppend((Append *) node, exprCtxt, parent); + case T_LimitState: + ExecReScanLimit((LimitState *) node, exprCtxt); break; default: @@ -163,10 +163,10 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent) return; } - if (node->chgParam != NULL) + if (node->chgParam != NIL) { freeList(node->chgParam); - node->chgParam = NULL; + node->chgParam = NIL; } } @@ -176,37 +176,37 @@ ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent) * Marks the current scan position. */ void -ExecMarkPos(Plan *node) +ExecMarkPos(PlanState *node) { switch (nodeTag(node)) { - case T_SeqScan: - ExecSeqMarkPos((SeqScan *) node); + case T_SeqScanState: + ExecSeqMarkPos((SeqScanState *) node); break; - case T_IndexScan: - ExecIndexMarkPos((IndexScan *) node); + case T_IndexScanState: + ExecIndexMarkPos((IndexScanState *) node); break; - case T_TidScan: - ExecTidMarkPos((TidScan *) node); + case T_TidScanState: + ExecTidMarkPos((TidScanState *) node); break; - case T_FunctionScan: - ExecFunctionMarkPos((FunctionScan *) node); + case T_FunctionScanState: + ExecFunctionMarkPos((FunctionScanState *) node); break; - case T_Material: - ExecMaterialMarkPos((Material *) node); + case T_MaterialState: + ExecMaterialMarkPos((MaterialState *) node); break; - case T_Sort: - ExecSortMarkPos((Sort *) node); + case T_SortState: + ExecSortMarkPos((SortState *) node); break; default: /* don't make hard error unless caller asks to restore... */ - elog(LOG, "ExecMarkPos: node type %d not supported", + elog(DEBUG1, "ExecMarkPos: node type %d not supported", nodeTag(node)); break; } @@ -218,32 +218,32 @@ ExecMarkPos(Plan *node) * restores the scan position previously saved with ExecMarkPos() */ void -ExecRestrPos(Plan *node) +ExecRestrPos(PlanState *node) { switch (nodeTag(node)) { - case T_SeqScan: - ExecSeqRestrPos((SeqScan *) node); + case T_SeqScanState: + ExecSeqRestrPos((SeqScanState *) node); break; - case T_IndexScan: - ExecIndexRestrPos((IndexScan *) node); + case T_IndexScanState: + ExecIndexRestrPos((IndexScanState *) node); break; - case T_TidScan: - ExecTidRestrPos((TidScan *) node); + case T_TidScanState: + ExecTidRestrPos((TidScanState *) node); break; - case T_FunctionScan: - ExecFunctionRestrPos((FunctionScan *) node); + case T_FunctionScanState: + ExecFunctionRestrPos((FunctionScanState *) node); break; - case T_Material: - ExecMaterialRestrPos((Material *) node); + case T_MaterialState: + ExecMaterialRestrPos((MaterialState *) node); break; - case T_Sort: - ExecSortRestrPos((Sort *) node); + case T_SortState: + ExecSortRestrPos((SortState *) node); break; default: @@ -258,6 +258,7 @@ ExecRestrPos(Plan *node) * * XXX Ideally, all plan node types would support mark/restore, and this * wouldn't be needed. For now, this had better match the routines above. + * But note the test is on Plan nodetype, not PlanState nodetype. */ bool ExecSupportsMarkRestore(NodeTag plantype) diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 9202666689..15d47df669 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -12,10 +12,9 @@ * ExecutorRun() and ExecutorEnd() * * These three procedures are the external interfaces to the executor. - * In each case, the query descriptor and the execution state is required - * as arguments + * In each case, the query descriptor is required as an argument. * - * ExecutorStart() must be called at the beginning of any execution of any + * ExecutorStart() must be called at the beginning of execution of any * query plan and ExecutorEnd() should always be called at the end of * execution of a plan. * @@ -27,7 +26,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.189 2002/12/05 04:04:42 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.190 2002/12/05 15:50:30 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -48,16 +47,13 @@ /* decls for local routines only used within this module */ -static TupleDesc InitPlan(CmdType operation, - Query *parseTree, - Plan *plan, - EState *estate); +static void InitPlan(QueryDesc *queryDesc); static void initResultRelInfo(ResultRelInfo *resultRelInfo, Index resultRelationIndex, List *rangeTable, CmdType operation); -static void EndPlan(Plan *plan, EState *estate); -static TupleTableSlot *ExecutePlan(EState *estate, Plan *plan, +static void EndPlan(PlanState *planstate, EState *estate); +static TupleTableSlot *ExecutePlan(EState *estate, PlanState *planstate, CmdType operation, long numberTuples, ScanDirection direction, @@ -73,11 +69,6 @@ static void ExecUpdate(TupleTableSlot *slot, ItemPointer tupleid, EState *estate); static TupleTableSlot *EvalPlanQualNext(EState *estate); static void EndEvalPlanQual(EState *estate); -static void ExecCheckQueryPerms(CmdType operation, Query *parseTree, - Plan *plan); -static void ExecCheckPlanPerms(Plan *plan, List *rangeTable, - CmdType operation); -static void ExecCheckRTPerms(List *rangeTable, CmdType operation); static void ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation); /* end of local decls */ @@ -89,26 +80,40 @@ static void ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation); * This routine must be called at the beginning of any execution of any * query plan * - * returns a TupleDesc which describes the attributes of the tuples to - * be returned by the query. (Same value is saved in queryDesc) + * Takes a QueryDesc previously created by CreateQueryDesc (it's not real + * clear why we bother to separate the two functions, but...). The tupDesc + * field of the QueryDesc is filled in to describe the tuples that will be + * returned, and the internal fields (estate and planstate) are set up. * + * XXX this will change soon: * NB: the CurrentMemoryContext when this is called must be the context * to be used as the per-query context for the query plan. ExecutorRun() * and ExecutorEnd() must be called in this same memory context. * ---------------------------------------------------------------- */ -TupleDesc -ExecutorStart(QueryDesc *queryDesc, EState *estate) +void +ExecutorStart(QueryDesc *queryDesc) { - TupleDesc result; + EState *estate; - /* sanity checks */ + /* sanity checks: queryDesc must not be started already */ Assert(queryDesc != NULL); + Assert(queryDesc->estate == NULL); + + /* + * Build EState, fill with parameters from queryDesc + */ + estate = CreateExecutorState(); + queryDesc->estate = estate; + + estate->es_param_list_info = queryDesc->params; if (queryDesc->plantree->nParamExec > 0) estate->es_param_exec_vals = (ParamExecData *) palloc0(queryDesc->plantree->nParamExec * sizeof(ParamExecData)); + estate->es_instrument = queryDesc->doInstrument; + /* * Make our own private copy of the current query snapshot data. * @@ -119,16 +124,9 @@ ExecutorStart(QueryDesc *queryDesc, EState *estate) estate->es_snapshot = CopyQuerySnapshot(); /* - * Initialize the plan + * Initialize the plan state tree */ - result = InitPlan(queryDesc->operation, - queryDesc->parsetree, - queryDesc->plantree, - estate); - - queryDesc->tupDesc = result; - - return result; + InitPlan(queryDesc); } /* ---------------------------------------------------------------- @@ -150,11 +148,11 @@ ExecutorStart(QueryDesc *queryDesc, EState *estate) * ---------------------------------------------------------------- */ TupleTableSlot * -ExecutorRun(QueryDesc *queryDesc, EState *estate, +ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, long count) { CmdType operation; - Plan *plan; + EState *estate; CommandDest dest; DestReceiver *destfunc; TupleTableSlot *result; @@ -169,7 +167,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, * feature. */ operation = queryDesc->operation; - plan = queryDesc->plantree; + estate = queryDesc->estate; dest = queryDesc->dest; /* @@ -189,7 +187,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, result = NULL; else result = ExecutePlan(estate, - plan, + queryDesc->planstate, operation, count, direction, @@ -211,12 +209,16 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, * ---------------------------------------------------------------- */ void -ExecutorEnd(QueryDesc *queryDesc, EState *estate) +ExecutorEnd(QueryDesc *queryDesc) { + EState *estate; + /* sanity checks */ Assert(queryDesc != NULL); - EndPlan(queryDesc->plantree, estate); + estate = queryDesc->estate; + + EndPlan(queryDesc->planstate, estate); if (estate->es_snapshot != NULL) { @@ -235,97 +237,55 @@ ExecutorEnd(QueryDesc *queryDesc, EState *estate) /* - * ExecCheckQueryPerms - * Check access permissions for all relations referenced in a query. + * CreateExecutorState */ -static void -ExecCheckQueryPerms(CmdType operation, Query *parseTree, Plan *plan) +EState * +CreateExecutorState(void) { + EState *state; + /* - * Check RTEs in the query's primary rangetable. + * create a new executor state */ - ExecCheckRTPerms(parseTree->rtable, operation); + state = makeNode(EState); /* - * Search for subplans and APPEND nodes to check their rangetables. + * initialize the Executor State structure */ - ExecCheckPlanPerms(plan, parseTree->rtable, operation); -} - -/* - * ExecCheckPlanPerms - * Recursively scan the plan tree to check access permissions in - * subplans. - */ -static void -ExecCheckPlanPerms(Plan *plan, List *rangeTable, CmdType operation) -{ - List *subp; + state->es_direction = ForwardScanDirection; + state->es_range_table = NIL; - if (plan == NULL) - return; - - /* Check subplans, which we assume are plain SELECT queries */ - - foreach(subp, plan->initPlan) - { - SubPlan *subplan = (SubPlan *) lfirst(subp); - - ExecCheckRTPerms(subplan->rtable, CMD_SELECT); - ExecCheckPlanPerms(subplan->plan, subplan->rtable, CMD_SELECT); - } - foreach(subp, plan->subPlan) - { - SubPlan *subplan = (SubPlan *) lfirst(subp); + state->es_result_relations = NULL; + state->es_num_result_relations = 0; + state->es_result_relation_info = NULL; - ExecCheckRTPerms(subplan->rtable, CMD_SELECT); - ExecCheckPlanPerms(subplan->plan, subplan->rtable, CMD_SELECT); - } + state->es_junkFilter = NULL; - /* Check lower plan nodes */ + state->es_into_relation_descriptor = NULL; - ExecCheckPlanPerms(plan->lefttree, rangeTable, operation); - ExecCheckPlanPerms(plan->righttree, rangeTable, operation); + state->es_param_list_info = NULL; + state->es_param_exec_vals = NULL; - /* Do node-type-specific checks */ + state->es_tupleTable = NULL; - switch (nodeTag(plan)) - { - case T_SubqueryScan: - { - SubqueryScan *scan = (SubqueryScan *) plan; - RangeTblEntry *rte; + state->es_query_cxt = CurrentMemoryContext; - /* Recursively check the subquery */ - rte = rt_fetch(scan->scan.scanrelid, rangeTable); - Assert(rte->rtekind == RTE_SUBQUERY); - ExecCheckQueryPerms(operation, rte->subquery, scan->subplan); - break; - } - case T_Append: - { - Append *app = (Append *) plan; - List *appendplans; + state->es_instrument = false; - foreach(appendplans, app->appendplans) - { - ExecCheckPlanPerms((Plan *) lfirst(appendplans), - rangeTable, - operation); - } - break; - } + state->es_per_tuple_exprcontext = NULL; - default: - break; - } + /* + * return the executor state structure + */ + return state; } + /* * ExecCheckRTPerms * Check access permissions for all relations listed in a range table. */ -static void +void ExecCheckRTPerms(List *rangeTable, CmdType operation) { List *lp; @@ -350,11 +310,18 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation) AclResult aclcheck_result; /* - * Only plain-relation RTEs need to be checked here. Subquery RTEs - * will be checked when ExecCheckPlanPerms finds the SubqueryScan - * node, and function RTEs are checked by init_fcache when the - * function is prepared for execution. Join and special RTEs need no - * checks. + * If it's a subquery, recursively examine its rangetable. + */ + if (rte->rtekind == RTE_SUBQUERY) + { + ExecCheckRTPerms(rte->subquery->rtable, operation); + return; + } + + /* + * Otherwise, only plain-relation RTEs need to be checked here. + * Function RTEs are checked by init_fcache when the function is prepared + * for execution. Join and special RTEs need no checks. */ if (rte->rtekind != RTE_RELATION) return; @@ -367,7 +334,7 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation) * * Note: GetUserId() is presently fast enough that there's no harm in * calling it separately for each RTE. If that stops being true, we - * could call it once in ExecCheckQueryPerms and pass the userid down + * could call it once in ExecCheckRTPerms and pass the userid down * from there. But for now, no need for the extra clutter. */ userid = rte->checkAsUser ? rte->checkAsUser : GetUserId(); @@ -428,7 +395,8 @@ typedef struct execRowMark typedef struct evalPlanQual { - Plan *plan; + Plan *plan; /* XXX temporary */ + PlanState *planstate; Index rti; EState estate; struct evalPlanQual *free; @@ -441,17 +409,24 @@ typedef struct evalPlanQual * and start up the rule manager * ---------------------------------------------------------------- */ -static TupleDesc -InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) +static void +InitPlan(QueryDesc *queryDesc) { + CmdType operation = queryDesc->operation; + Query *parseTree = queryDesc->parsetree; + Plan *plan = queryDesc->plantree; + EState *estate = queryDesc->estate; + PlanState *planstate; List *rangeTable; Relation intoRelationDesc; TupleDesc tupType; /* - * Do permissions checks. + * Do permissions checks. It's sufficient to examine the query's + * top rangetable here --- subplan RTEs will be checked during + * ExecInitSubPlan(). */ - ExecCheckQueryPerms(operation, parseTree, plan); + ExecCheckRTPerms(parseTree->rtable, operation); /* * get information from query descriptor @@ -575,14 +550,14 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) * query tree. This opens files, allocates storage and leaves us * ready to start processing tuples. */ - ExecInitNode(plan, estate, NULL); + planstate = ExecInitNode(plan, estate); /* * Get the tuple descriptor describing the type of tuples to return. * (this is especially important if we are creating a relation with * "SELECT INTO") */ - tupType = ExecGetTupType(plan); /* tuple descriptor */ + tupType = ExecGetTupType(planstate); /* * Initialize the junk filter if needed. SELECT and INSERT queries @@ -627,26 +602,29 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) */ if (parseTree->resultRelations != NIL) { - List *subplans; + PlanState **appendplans; + int as_nplans; ResultRelInfo *resultRelInfo; + int i; /* Top plan had better be an Append here. */ Assert(IsA(plan, Append)); Assert(((Append *) plan)->isTarget); - subplans = ((Append *) plan)->appendplans; - Assert(length(subplans) == estate->es_num_result_relations); + Assert(IsA(planstate, AppendState)); + appendplans = ((AppendState *) planstate)->appendplans; + as_nplans = ((AppendState *) planstate)->as_nplans; + Assert(as_nplans == estate->es_num_result_relations); resultRelInfo = estate->es_result_relations; - while (subplans != NIL) + for (i = 0; i < as_nplans; i++) { - Plan *subplan = (Plan *) lfirst(subplans); + PlanState *subplan = appendplans[i]; JunkFilter *j; - j = ExecInitJunkFilter(subplan->targetlist, + j = ExecInitJunkFilter(subplan->plan->targetlist, ExecGetTupType(subplan), ExecAllocTableSlot(estate->es_tupleTable)); resultRelInfo->ri_junkFilter = j; resultRelInfo++; - subplans = lnext(subplans); } /* @@ -661,7 +639,7 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) /* Normal case with just one JunkFilter */ JunkFilter *j; - j = ExecInitJunkFilter(plan->targetlist, + j = ExecInitJunkFilter(planstate->plan->targetlist, tupType, ExecAllocTableSlot(estate->es_tupleTable)); estate->es_junkFilter = j; @@ -755,7 +733,8 @@ InitPlan(CmdType operation, Query *parseTree, Plan *plan, EState *estate) estate->es_into_relation_descriptor = intoRelationDesc; - return tupType; + queryDesc->tupDesc = tupType; + queryDesc->planstate = planstate; } /* @@ -816,11 +795,11 @@ initResultRelInfo(ResultRelInfo *resultRelInfo, /* ---------------------------------------------------------------- * EndPlan * - * Cleans up the query plan -- closes files and free up storages + * Cleans up the query plan -- closes files and frees up storage * ---------------------------------------------------------------- */ static void -EndPlan(Plan *plan, EState *estate) +EndPlan(PlanState *planstate, EState *estate) { ResultRelInfo *resultRelInfo; int i; @@ -835,7 +814,7 @@ EndPlan(Plan *plan, EState *estate) /* * shut down the node-type-specific query processing */ - ExecEndNode(plan, NULL); + ExecEndNode(planstate); /* * destroy the executor "tuple" table. @@ -902,7 +881,7 @@ EndPlan(Plan *plan, EState *estate) */ static TupleTableSlot * ExecutePlan(EState *estate, - Plan *plan, + PlanState *planstate, CmdType operation, long numberTuples, ScanDirection direction, @@ -964,10 +943,10 @@ lnext: ; { slot = EvalPlanQualNext(estate); if (TupIsNull(slot)) - slot = ExecProcNode(plan, NULL); + slot = ExecProcNode(planstate); } else - slot = ExecProcNode(plan, NULL); + slot = ExecProcNode(planstate); /* * if the tuple is null, then we assume there is nothing more to @@ -1765,7 +1744,7 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid) oldepq = (evalPlanQual *) epqstate->es_evalPlanQual; Assert(oldepq->rti != 0); /* stop execution */ - ExecEndNode(epq->plan, NULL); + ExecEndNode(epq->planstate); ExecDropTupleTable(epqstate->es_tupleTable, true); epqstate->es_tupleTable = NULL; heap_freetuple(epqstate->es_evTuple[epq->rti - 1]); @@ -1793,10 +1772,8 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid) /* * Each stack level has its own copy of the plan tree. This - * is wasteful, but necessary as long as plan nodes point to - * exec state nodes rather than vice versa. Note that - * copyfuncs.c doesn't attempt to copy the exec state nodes, - * which is a good thing in this situation. + * is wasteful, but necessary until plan trees are fully + * read-only. */ newepq->plan = copyObject(estate->es_origPlan); @@ -1858,7 +1835,7 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid) if (endNode) { /* stop execution */ - ExecEndNode(epq->plan, NULL); + ExecEndNode(epq->planstate); ExecDropTupleTable(epqstate->es_tupleTable, true); epqstate->es_tupleTable = NULL; } @@ -1886,7 +1863,7 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid) epqstate->es_tupleTable = ExecCreateTupleTable(estate->es_tupleTable->size); - ExecInitNode(epq->plan, epqstate, NULL); + epq->planstate = ExecInitNode(epq->plan, epqstate); return EvalPlanQualNext(estate); } @@ -1902,7 +1879,7 @@ EvalPlanQualNext(EState *estate) Assert(epq->rti != 0); lpqnext:; - slot = ExecProcNode(epq->plan, NULL); + slot = ExecProcNode(epq->planstate); /* * No more tuples for this PQ. Continue previous one. @@ -1910,7 +1887,7 @@ lpqnext:; if (TupIsNull(slot)) { /* stop execution */ - ExecEndNode(epq->plan, NULL); + ExecEndNode(epq->planstate); ExecDropTupleTable(epqstate->es_tupleTable, true); epqstate->es_tupleTable = NULL; heap_freetuple(epqstate->es_evTuple[epq->rti - 1]); @@ -1951,7 +1928,7 @@ EndEvalPlanQual(EState *estate) for (;;) { /* stop execution */ - ExecEndNode(epq->plan, NULL); + ExecEndNode(epq->planstate); ExecDropTupleTable(epqstate->es_tupleTable, true); epqstate->es_tupleTable = NULL; if (epqstate->es_evTuple[epq->rti - 1] != NULL) diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c index 2054a6cf05..2db4a146bc 100644 --- a/src/backend/executor/execProcnode.c +++ b/src/backend/executor/execProcnode.c @@ -5,23 +5,23 @@ * "get a tuple", and "cleanup" routines for the given node type. * If the node has children, then it will presumably call ExecInitNode, * ExecProcNode, or ExecEndNode on its subnodes and do the appropriate - * processing.. + * processing. * * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.30 2002/06/20 20:29:27 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.31 2002/12/05 15:50:31 tgl Exp $ * *------------------------------------------------------------------------- */ /* * INTERFACE ROUTINES + * ExecCountSlotsNode - count tuple slots needed by plan tree * ExecInitNode - initialize a plan node and its subplans * ExecProcNode - get a tuple by executing the plan node * ExecEndNode - shut down a plan node and its subplans - * ExecCountSlotsNode - count tuple slots needed by plan tree * ExecGetTupType - get result tuple type of a plan node * * NOTES @@ -53,10 +53,12 @@ * * ExecInitNode() notices that it is looking at a nest loop and * as the code below demonstrates, it calls ExecInitNestLoop(). * Eventually this calls ExecInitNode() on the right and left subplans - * and so forth until the entire plan is initialized. + * and so forth until the entire plan is initialized. The result + * of ExecInitNode() is a plan state tree built with the same structure + * as the underlying plan tree. * - * * Then when ExecRun() is called, it calls ExecutePlan() which - * calls ExecProcNode() repeatedly on the top node of the plan. + * * Then when ExecRun() is called, it calls ExecutePlan() which calls + * ExecProcNode() repeatedly on the top node of the plan state tree. * Each time this happens, ExecProcNode() will end up calling * ExecNestLoop(), which calls ExecProcNode() on its subplans. * Each of these subplans is a sequential scan so ExecSeqScan() is @@ -73,7 +75,6 @@ * ExecInitNode(), ExecProcNode() and ExecEndNode() dispatch * their work to the appopriate node support routines which may * in turn call these routines themselves on their subplans. - * */ #include "postgres.h" @@ -81,11 +82,11 @@ #include "executor/instrument.h" #include "executor/nodeAgg.h" #include "executor/nodeAppend.h" +#include "executor/nodeFunctionscan.h" #include "executor/nodeGroup.h" #include "executor/nodeHash.h" #include "executor/nodeHashjoin.h" #include "executor/nodeIndexscan.h" -#include "executor/nodeTidscan.h" #include "executor/nodeLimit.h" #include "executor/nodeMaterial.h" #include "executor/nodeMergejoin.h" @@ -96,7 +97,7 @@ #include "executor/nodeSort.h" #include "executor/nodeSubplan.h" #include "executor/nodeSubqueryscan.h" -#include "executor/nodeFunctionscan.h" +#include "executor/nodeTidscan.h" #include "executor/nodeUnique.h" #include "miscadmin.h" #include "tcop/tcopprot.h" @@ -109,32 +110,23 @@ * * Initial States: * 'node' is the plan produced by the query planner + * 'estate' is the shared execution state for the query tree * - * returns TRUE/FALSE on whether the plan was successfully initialized + * Returns a PlanState node corresponding to the given Plan node. * ------------------------------------------------------------------------ */ -bool -ExecInitNode(Plan *node, EState *estate, Plan *parent) +PlanState * +ExecInitNode(Plan *node, EState *estate) { - bool result; + PlanState *result; + List *subps; List *subp; /* * do nothing when we get to the end of a leaf on tree. */ if (node == NULL) - return FALSE; - - /* Set up instrumentation for this node if the parent has it */ - if (!node->instrument && parent && parent->instrument) - node->instrument = InstrAlloc(); - - foreach(subp, node->initPlan) - { - result = ExecInitSubPlan((SubPlan *) lfirst(subp), estate, node); - if (result == FALSE) - return FALSE; - } + return NULL; switch (nodeTag(node)) { @@ -142,104 +134,124 @@ ExecInitNode(Plan *node, EState *estate, Plan *parent) * control nodes */ case T_Result: - result = ExecInitResult((Result *) node, estate, parent); + result = (PlanState *) ExecInitResult((Result *) node, estate); break; case T_Append: - result = ExecInitAppend((Append *) node, estate, parent); + result = (PlanState *) ExecInitAppend((Append *) node, estate); break; /* * scan nodes */ case T_SeqScan: - result = ExecInitSeqScan((SeqScan *) node, estate, parent); + result = (PlanState *) ExecInitSeqScan((SeqScan *) node, estate); break; case T_IndexScan: - result = ExecInitIndexScan((IndexScan *) node, estate, parent); + result = (PlanState *) ExecInitIndexScan((IndexScan *) node, estate); break; case T_TidScan: - result = ExecInitTidScan((TidScan *) node, estate, parent); + result = (PlanState *) ExecInitTidScan((TidScan *) node, estate); break; case T_SubqueryScan: - result = ExecInitSubqueryScan((SubqueryScan *) node, estate, - parent); + result = (PlanState *) ExecInitSubqueryScan((SubqueryScan *) node, estate); break; case T_FunctionScan: - result = ExecInitFunctionScan((FunctionScan *) node, estate, - parent); + result = (PlanState *) ExecInitFunctionScan((FunctionScan *) node, estate); break; /* * join nodes */ case T_NestLoop: - result = ExecInitNestLoop((NestLoop *) node, estate, parent); + result = (PlanState *) ExecInitNestLoop((NestLoop *) node, estate); break; case T_MergeJoin: - result = ExecInitMergeJoin((MergeJoin *) node, estate, parent); - break; - - case T_Hash: - result = ExecInitHash((Hash *) node, estate, parent); + result = (PlanState *) ExecInitMergeJoin((MergeJoin *) node, estate); break; case T_HashJoin: - result = ExecInitHashJoin((HashJoin *) node, estate, parent); + result = (PlanState *) ExecInitHashJoin((HashJoin *) node, estate); break; /* * materialization nodes */ case T_Material: - result = ExecInitMaterial((Material *) node, estate, parent); + result = (PlanState *) ExecInitMaterial((Material *) node, estate); break; case T_Sort: - result = ExecInitSort((Sort *) node, estate, parent); + result = (PlanState *) ExecInitSort((Sort *) node, estate); break; - case T_Unique: - result = ExecInitUnique((Unique *) node, estate, parent); + case T_Group: + result = (PlanState *) ExecInitGroup((Group *) node, estate); break; - case T_SetOp: - result = ExecInitSetOp((SetOp *) node, estate, parent); + case T_Agg: + result = (PlanState *) ExecInitAgg((Agg *) node, estate); break; - case T_Limit: - result = ExecInitLimit((Limit *) node, estate, parent); + case T_Unique: + result = (PlanState *) ExecInitUnique((Unique *) node, estate); break; - case T_Group: - result = ExecInitGroup((Group *) node, estate, parent); + case T_Hash: + result = (PlanState *) ExecInitHash((Hash *) node, estate); break; - case T_Agg: - result = ExecInitAgg((Agg *) node, estate, parent); + case T_SetOp: + result = (PlanState *) ExecInitSetOp((SetOp *) node, estate); + break; + + case T_Limit: + result = (PlanState *) ExecInitLimit((Limit *) node, estate); break; default: elog(ERROR, "ExecInitNode: node type %d unsupported", (int) nodeTag(node)); - result = FALSE; + result = NULL; /* keep compiler quiet */ break; } - if (result != FALSE) + /* + * Initialize any initPlans present in this node. The planner put + * them in a separate list for us. + */ + subps = NIL; + foreach(subp, node->initPlan) { - foreach(subp, node->subPlan) - { - result = ExecInitSubPlan((SubPlan *) lfirst(subp), estate, node); - if (result == FALSE) - return FALSE; - } + SubPlan *subplan = (SubPlan *) lfirst(subp); + + Assert(IsA(subplan, SubPlan)); + subps = lappend(subps, ExecInitSubPlan(subplan, estate)); } + result->initPlan = subps; + + /* + * Initialize any subPlans present in this node. These were found + * by ExecInitExpr during initialization of the PlanState. + */ + subps = NIL; + foreach(subp, result->subPlan) + { + SubPlan *subplan = (SubPlan *) lfirst(subp); + + Assert(IsA(subplan, SubPlan)); + subps = lappend(subps, ExecInitSubPlan(subplan, estate)); + } + result->subPlan = subps; + + /* Set up instrumentation for this node if requested */ + if (estate->es_instrument) + result->instrument = InstrAlloc(); return result; } @@ -248,12 +260,11 @@ ExecInitNode(Plan *node, EState *estate, Plan *parent) /* ---------------------------------------------------------------- * ExecProcNode * - * Initial States: - * the query tree must be initialized once by calling ExecInit. + * Execute the given node to return a(nother) tuple. * ---------------------------------------------------------------- */ TupleTableSlot * -ExecProcNode(Plan *node, Plan *parent) +ExecProcNode(PlanState *node) { TupleTableSlot *result; @@ -265,8 +276,8 @@ ExecProcNode(Plan *node, Plan *parent) if (node == NULL) return NULL; - if (node->chgParam != NULL) /* something changed */ - ExecReScan(node, NULL, parent); /* let ReScan handle this */ + if (node->chgParam != NIL) /* something changed */ + ExecReScan(node, NULL); /* let ReScan handle this */ if (node->instrument) InstrStartNode(node->instrument); @@ -276,85 +287,85 @@ ExecProcNode(Plan *node, Plan *parent) /* * control nodes */ - case T_Result: - result = ExecResult((Result *) node); + case T_ResultState: + result = ExecResult((ResultState *) node); break; - case T_Append: - result = ExecProcAppend((Append *) node); + case T_AppendState: + result = ExecProcAppend((AppendState *) node); break; /* * scan nodes */ - case T_SeqScan: - result = ExecSeqScan((SeqScan *) node); + case T_SeqScanState: + result = ExecSeqScan((SeqScanState *) node); break; - case T_IndexScan: - result = ExecIndexScan((IndexScan *) node); + case T_IndexScanState: + result = ExecIndexScan((IndexScanState *) node); break; - case T_TidScan: - result = ExecTidScan((TidScan *) node); + case T_TidScanState: + result = ExecTidScan((TidScanState *) node); break; - case T_SubqueryScan: - result = ExecSubqueryScan((SubqueryScan *) node); + case T_SubqueryScanState: + result = ExecSubqueryScan((SubqueryScanState *) node); break; - case T_FunctionScan: - result = ExecFunctionScan((FunctionScan *) node); + case T_FunctionScanState: + result = ExecFunctionScan((FunctionScanState *) node); break; /* * join nodes */ - case T_NestLoop: - result = ExecNestLoop((NestLoop *) node); + case T_NestLoopState: + result = ExecNestLoop((NestLoopState *) node); break; - case T_MergeJoin: - result = ExecMergeJoin((MergeJoin *) node); + case T_MergeJoinState: + result = ExecMergeJoin((MergeJoinState *) node); break; - case T_Hash: - result = ExecHash((Hash *) node); - break; - - case T_HashJoin: - result = ExecHashJoin((HashJoin *) node); + case T_HashJoinState: + result = ExecHashJoin((HashJoinState *) node); break; /* * materialization nodes */ - case T_Material: - result = ExecMaterial((Material *) node); + case T_MaterialState: + result = ExecMaterial((MaterialState *) node); break; - case T_Sort: - result = ExecSort((Sort *) node); + case T_SortState: + result = ExecSort((SortState *) node); break; - case T_Unique: - result = ExecUnique((Unique *) node); + case T_GroupState: + result = ExecGroup((GroupState *) node); break; - case T_SetOp: - result = ExecSetOp((SetOp *) node); + case T_AggState: + result = ExecAgg((AggState *) node); break; - case T_Limit: - result = ExecLimit((Limit *) node); + case T_UniqueState: + result = ExecUnique((UniqueState *) node); break; - case T_Group: - result = ExecGroup((Group *) node); + case T_HashState: + result = ExecHash((HashState *) node); break; - case T_Agg: - result = ExecAgg((Agg *) node); + case T_SetOpState: + result = ExecSetOp((SetOpState *) node); + break; + + case T_LimitState: + result = ExecLimit((LimitState *) node); break; default: @@ -370,10 +381,16 @@ ExecProcNode(Plan *node, Plan *parent) return result; } +/* + * ExecCountSlotsNode - count up the number of tuple table slots needed + * + * Note that this scans a Plan tree, not a PlanState tree, because we + * haven't built the PlanState tree yet ... + */ int ExecCountSlotsNode(Plan *node) { - if (node == (Plan *) NULL) + if (node == NULL) return 0; switch (nodeTag(node)) @@ -414,9 +431,6 @@ ExecCountSlotsNode(Plan *node) case T_MergeJoin: return ExecCountSlotsMergeJoin((MergeJoin *) node); - case T_Hash: - return ExecCountSlotsHash((Hash *) node); - case T_HashJoin: return ExecCountSlotsHashJoin((HashJoin *) node); @@ -429,26 +443,30 @@ ExecCountSlotsNode(Plan *node) case T_Sort: return ExecCountSlotsSort((Sort *) node); + case T_Group: + return ExecCountSlotsGroup((Group *) node); + + case T_Agg: + return ExecCountSlotsAgg((Agg *) node); + case T_Unique: return ExecCountSlotsUnique((Unique *) node); + case T_Hash: + return ExecCountSlotsHash((Hash *) node); + case T_SetOp: return ExecCountSlotsSetOp((SetOp *) node); case T_Limit: return ExecCountSlotsLimit((Limit *) node); - case T_Group: - return ExecCountSlotsGroup((Group *) node); - - case T_Agg: - return ExecCountSlotsAgg((Agg *) node); - default: elog(ERROR, "ExecCountSlotsNode: node type %d unsupported", (int) nodeTag(node)); break; } + return 0; } @@ -464,7 +482,7 @@ ExecCountSlotsNode(Plan *node) * ---------------------------------------------------------------- */ void -ExecEndNode(Plan *node, Plan *parent) +ExecEndNode(PlanState *node) { List *subp; @@ -474,14 +492,19 @@ ExecEndNode(Plan *node, Plan *parent) if (node == NULL) return; + if (node->instrument) + InstrEndLoop(node->instrument); + + /* Clean up initPlans and subPlans */ foreach(subp, node->initPlan) - ExecEndSubPlan((SubPlan *) lfirst(subp)); + ExecEndSubPlan((SubPlanState *) lfirst(subp)); foreach(subp, node->subPlan) - ExecEndSubPlan((SubPlan *) lfirst(subp)); - if (node->chgParam != NULL) + ExecEndSubPlan((SubPlanState *) lfirst(subp)); + + if (node->chgParam != NIL) { freeList(node->chgParam); - node->chgParam = NULL; + node->chgParam = NIL; } switch (nodeTag(node)) @@ -489,85 +512,85 @@ ExecEndNode(Plan *node, Plan *parent) /* * control nodes */ - case T_Result: - ExecEndResult((Result *) node); + case T_ResultState: + ExecEndResult((ResultState *) node); break; - case T_Append: - ExecEndAppend((Append *) node); + case T_AppendState: + ExecEndAppend((AppendState *) node); break; /* * scan nodes */ - case T_SeqScan: - ExecEndSeqScan((SeqScan *) node); + case T_SeqScanState: + ExecEndSeqScan((SeqScanState *) node); break; - case T_IndexScan: - ExecEndIndexScan((IndexScan *) node); + case T_IndexScanState: + ExecEndIndexScan((IndexScanState *) node); break; - case T_TidScan: - ExecEndTidScan((TidScan *) node); + case T_TidScanState: + ExecEndTidScan((TidScanState *) node); break; - case T_SubqueryScan: - ExecEndSubqueryScan((SubqueryScan *) node); + case T_SubqueryScanState: + ExecEndSubqueryScan((SubqueryScanState *) node); break; - case T_FunctionScan: - ExecEndFunctionScan((FunctionScan *) node); + case T_FunctionScanState: + ExecEndFunctionScan((FunctionScanState *) node); break; /* * join nodes */ - case T_NestLoop: - ExecEndNestLoop((NestLoop *) node); - break; - - case T_MergeJoin: - ExecEndMergeJoin((MergeJoin *) node); + case T_NestLoopState: + ExecEndNestLoop((NestLoopState *) node); break; - case T_Hash: - ExecEndHash((Hash *) node); + case T_MergeJoinState: + ExecEndMergeJoin((MergeJoinState *) node); break; - case T_HashJoin: - ExecEndHashJoin((HashJoin *) node); + case T_HashJoinState: + ExecEndHashJoin((HashJoinState *) node); break; /* * materialization nodes */ - case T_Material: - ExecEndMaterial((Material *) node); + case T_MaterialState: + ExecEndMaterial((MaterialState *) node); break; - case T_Sort: - ExecEndSort((Sort *) node); + case T_SortState: + ExecEndSort((SortState *) node); break; - case T_Unique: - ExecEndUnique((Unique *) node); + case T_GroupState: + ExecEndGroup((GroupState *) node); break; - case T_SetOp: - ExecEndSetOp((SetOp *) node); + case T_AggState: + ExecEndAgg((AggState *) node); break; - case T_Limit: - ExecEndLimit((Limit *) node); + case T_UniqueState: + ExecEndUnique((UniqueState *) node); break; - case T_Group: - ExecEndGroup((Group *) node); + case T_HashState: + ExecEndHash((HashState *) node); break; - case T_Agg: - ExecEndAgg((Agg *) node); + case T_SetOpState: + ExecEndSetOp((SetOpState *) node); + break; + + case T_LimitState: + ExecEndLimit((LimitState *) node); break; default: @@ -575,9 +598,6 @@ ExecEndNode(Plan *node, Plan *parent) (int) nodeTag(node)); break; } - - if (node->instrument) - InstrEndLoop(node->instrument); } @@ -592,7 +612,7 @@ ExecEndNode(Plan *node, Plan *parent) * ---------------------------------------------------------------- */ TupleDesc -ExecGetTupType(Plan *node) +ExecGetTupType(PlanState *node) { TupleTableSlot *slot; @@ -601,147 +621,147 @@ ExecGetTupType(Plan *node) switch (nodeTag(node)) { - case T_Result: + case T_ResultState: { - ResultState *resstate = ((Result *) node)->resstate; + ResultState *resstate = (ResultState *) node; - slot = resstate->cstate.cs_ResultTupleSlot; + slot = resstate->ps.ps_ResultTupleSlot; } break; - case T_SeqScan: + case T_AppendState: { - CommonScanState *scanstate = ((SeqScan *) node)->scanstate; + AppendState *appendstate = (AppendState *) node; - slot = scanstate->cstate.cs_ResultTupleSlot; + slot = appendstate->ps.ps_ResultTupleSlot; } break; - case T_NestLoop: + case T_SeqScanState: { - NestLoopState *nlstate = ((NestLoop *) node)->nlstate; + SeqScanState *scanstate = (SeqScanState *) node; - slot = nlstate->jstate.cs_ResultTupleSlot; + slot = scanstate->ps.ps_ResultTupleSlot; } break; - case T_Append: + case T_IndexScanState: { - AppendState *appendstate = ((Append *) node)->appendstate; + IndexScanState *scanstate = (IndexScanState *) node; - slot = appendstate->cstate.cs_ResultTupleSlot; + slot = scanstate->ss.ps.ps_ResultTupleSlot; } break; - case T_IndexScan: + case T_TidScanState: { - CommonScanState *scanstate = ((IndexScan *) node)->scan.scanstate; + TidScanState *scanstate = (TidScanState *) node; - slot = scanstate->cstate.cs_ResultTupleSlot; + slot = scanstate->ss.ps.ps_ResultTupleSlot; } break; - case T_TidScan: + case T_SubqueryScanState: { - CommonScanState *scanstate = ((TidScan *) node)->scan.scanstate; + SubqueryScanState *scanstate = (SubqueryScanState *) node; - slot = scanstate->cstate.cs_ResultTupleSlot; + slot = scanstate->ss.ps.ps_ResultTupleSlot; } break; - case T_SubqueryScan: + case T_FunctionScanState: { - CommonScanState *scanstate = ((SubqueryScan *) node)->scan.scanstate; + FunctionScanState *scanstate = (FunctionScanState *) node; - slot = scanstate->cstate.cs_ResultTupleSlot; + slot = scanstate->ss.ps.ps_ResultTupleSlot; } break; - case T_FunctionScan: + case T_NestLoopState: { - CommonScanState *scanstate = ((FunctionScan *) node)->scan.scanstate; + NestLoopState *nlstate = (NestLoopState *) node; - slot = scanstate->cstate.cs_ResultTupleSlot; + slot = nlstate->js.ps.ps_ResultTupleSlot; } break; - case T_Material: + case T_MergeJoinState: { - MaterialState *matstate = ((Material *) node)->matstate; + MergeJoinState *mergestate = (MergeJoinState *) node; - slot = matstate->csstate.css_ScanTupleSlot; + slot = mergestate->js.ps.ps_ResultTupleSlot; } break; - case T_Sort: + case T_HashJoinState: { - SortState *sortstate = ((Sort *) node)->sortstate; + HashJoinState *hashjoinstate = (HashJoinState *) node; - slot = sortstate->csstate.css_ScanTupleSlot; + slot = hashjoinstate->js.ps.ps_ResultTupleSlot; } break; - case T_Agg: + case T_MaterialState: { - AggState *aggstate = ((Agg *) node)->aggstate; + MaterialState *matstate = (MaterialState *) node; - slot = aggstate->csstate.cstate.cs_ResultTupleSlot; + slot = matstate->ss.ss_ScanTupleSlot; } break; - case T_Group: + case T_SortState: { - GroupState *grpstate = ((Group *) node)->grpstate; + SortState *sortstate = (SortState *) node; - slot = grpstate->csstate.cstate.cs_ResultTupleSlot; + slot = sortstate->ss.ss_ScanTupleSlot; } break; - case T_Hash: + case T_GroupState: { - HashState *hashstate = ((Hash *) node)->hashstate; + GroupState *grpstate = (GroupState *) node; - slot = hashstate->cstate.cs_ResultTupleSlot; + slot = grpstate->ss.ps.ps_ResultTupleSlot; } break; - case T_Unique: + case T_AggState: { - UniqueState *uniquestate = ((Unique *) node)->uniquestate; + AggState *aggstate = (AggState *) node; - slot = uniquestate->cstate.cs_ResultTupleSlot; + slot = aggstate->ss.ps.ps_ResultTupleSlot; } break; - case T_SetOp: + case T_UniqueState: { - SetOpState *setopstate = ((SetOp *) node)->setopstate; + UniqueState *uniquestate = (UniqueState *) node; - slot = setopstate->cstate.cs_ResultTupleSlot; + slot = uniquestate->ps.ps_ResultTupleSlot; } break; - case T_Limit: + case T_HashState: { - LimitState *limitstate = ((Limit *) node)->limitstate; + HashState *hashstate = (HashState *) node; - slot = limitstate->cstate.cs_ResultTupleSlot; + slot = hashstate->ps.ps_ResultTupleSlot; } break; - case T_MergeJoin: + case T_SetOpState: { - MergeJoinState *mergestate = ((MergeJoin *) node)->mergestate; + SetOpState *setopstate = (SetOpState *) node; - slot = mergestate->jstate.cs_ResultTupleSlot; + slot = setopstate->ps.ps_ResultTupleSlot; } break; - case T_HashJoin: + case T_LimitState: { - HashJoinState *hashjoinstate = ((HashJoin *) node)->hashjoinstate; + LimitState *limitstate = (LimitState *) node; - slot = hashjoinstate->jstate.cs_ResultTupleSlot; + slot = limitstate->ps.ps_ResultTupleSlot; } break; diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index cb31c025df..e7c724c66e 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.112 2002/12/01 20:27:32 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.113 2002/12/05 15:50:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1766,7 +1766,8 @@ ExecEvalExpr(Node *expression, isNull, isDone); break; case SUBPLAN_EXPR: - retDatum = ExecSubPlan((SubPlan *) expr->oper, + /* XXX temporary hack to find exec state node */ + retDatum = ExecSubPlan(((SubPlan *) expr->oper)->pstate, expr->args, econtext, isNull); break; @@ -1850,6 +1851,169 @@ ExecEvalExprSwitchContext(Node *expression, } +/* + * ExecInitExpr: prepare an expression tree for execution + * + * 'node' is the root of the expression tree to examine + * 'parent' is the PlanState node that owns the expression, + * or NULL if we are preparing an expression that is not associated + * with a plan. (If so, it can't have Aggrefs or SubPlans.) + * + * Soon this will generate an expression state tree paralleling the given + * expression tree. Right now, it just searches the expression tree for + * Aggref and SubPlan nodes. + */ +Node * +ExecInitExpr(Node *node, PlanState *parent) +{ + List *temp; + + if (node == NULL) + return NULL; + switch (nodeTag(node)) + { + case T_Var: + break; + case T_Const: + break; + case T_Param: + break; + case T_Aggref: + if (parent && IsA(parent, AggState)) + { + AggState *aggstate = (AggState *) parent; + int naggs; + + aggstate->aggs = lcons(node, aggstate->aggs); + naggs = ++aggstate->numaggs; + + ExecInitExpr(((Aggref *) node)->target, parent); + + /* + * Complain if the aggregate's argument contains any + * aggregates; nested agg functions are semantically + * nonsensical. (This probably was caught earlier, + * but we defend against it here anyway.) + */ + if (naggs != aggstate->numaggs) + elog(ERROR, "Aggregate function calls may not be nested"); + } + else + elog(ERROR, "ExecInitExpr: Aggref not expected here"); + break; + case T_ArrayRef: + { + ArrayRef *aref = (ArrayRef *) node; + + ExecInitExpr((Node *) aref->refupperindexpr, parent); + ExecInitExpr((Node *) aref->reflowerindexpr, parent); + ExecInitExpr(aref->refexpr, parent); + ExecInitExpr(aref->refassgnexpr, parent); + } + break; + case T_Expr: + { + Expr *expr = (Expr *) node; + + switch (expr->opType) + { + case OP_EXPR: + break; + case FUNC_EXPR: + break; + case OR_EXPR: + break; + case AND_EXPR: + break; + case NOT_EXPR: + break; + case DISTINCT_EXPR: + break; + case SUBPLAN_EXPR: + if (parent) + { + SubLink *sublink = ((SubPlan *) expr->oper)->sublink; + + /* + * Here we just add the SubPlan nodes to + * parent->subPlan. Later they will be expanded + * to SubPlanState nodes. + */ + parent->subPlan = lcons(expr->oper, + parent->subPlan); + + /* Must recurse into oper list too */ + Assert(IsA(sublink, SubLink)); + if (sublink->lefthand) + elog(ERROR, "ExecInitExpr: sublink has not been transformed"); + ExecInitExpr((Node *) sublink->oper, parent); + } + else + elog(ERROR, "ExecInitExpr: SubPlan not expected here"); + break; + default: + elog(ERROR, "ExecInitExpr: unknown expression type %d", + expr->opType); + break; + } + /* for all Expr node types, examine args list */ + ExecInitExpr((Node *) expr->args, parent); + } + break; + case T_FieldSelect: + ExecInitExpr(((FieldSelect *) node)->arg, parent); + break; + case T_RelabelType: + ExecInitExpr(((RelabelType *) node)->arg, parent); + break; + case T_CaseExpr: + { + CaseExpr *caseexpr = (CaseExpr *) node; + + foreach(temp, caseexpr->args) + { + CaseWhen *when = (CaseWhen *) lfirst(temp); + + Assert(IsA(when, CaseWhen)); + ExecInitExpr(when->expr, parent); + ExecInitExpr(when->result, parent); + } + /* caseexpr->arg should be null, but we'll check it anyway */ + ExecInitExpr(caseexpr->arg, parent); + ExecInitExpr(caseexpr->defresult, parent); + } + break; + case T_NullTest: + ExecInitExpr(((NullTest *) node)->arg, parent); + break; + case T_BooleanTest: + ExecInitExpr(((BooleanTest *) node)->arg, parent); + break; + case T_ConstraintTest: + ExecInitExpr(((ConstraintTest *) node)->arg, parent); + ExecInitExpr(((ConstraintTest *) node)->check_expr, parent); + break; + case T_ConstraintTestValue: + break; + case T_List: + foreach(temp, (List *) node) + { + ExecInitExpr((Node *) lfirst(temp), parent); + } + break; + case T_TargetEntry: + ExecInitExpr(((TargetEntry *) node)->expr, parent); + break; + default: + elog(ERROR, "ExecInitExpr: unknown expression type %d", + nodeTag(node)); + break; + } + + return node; +} + + /* ---------------------------------------------------------------- * ExecQual / ExecTargetList / ExecProject * ---------------------------------------------------------------- diff --git a/src/backend/executor/execScan.c b/src/backend/executor/execScan.c index 9fd7c4fb00..6944e03e9b 100644 --- a/src/backend/executor/execScan.c +++ b/src/backend/executor/execScan.c @@ -12,7 +12,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execScan.c,v 1.21 2002/09/02 02:47:02 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execScan.c,v 1.22 2002/12/05 15:50:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -44,10 +44,9 @@ * ---------------------------------------------------------------- */ TupleTableSlot * -ExecScan(Scan *node, +ExecScan(ScanState *node, ExecScanAccessMtd accessMtd) /* function returning a tuple */ { - CommonScanState *scanstate; EState *estate; ExprContext *econtext; List *qual; @@ -57,23 +56,22 @@ ExecScan(Scan *node, /* * Fetch data from node */ - estate = node->plan.state; - scanstate = node->scanstate; - econtext = scanstate->cstate.cs_ExprContext; - qual = node->plan.qual; + estate = node->ps.state; + econtext = node->ps.ps_ExprContext; + qual = node->ps.qual; /* * Check to see if we're still projecting out tuples from a previous * scan tuple (because there is a function-returning-set in the * projection expressions). If so, try to project another one. */ - if (scanstate->cstate.cs_TupFromTlist) + if (node->ps.ps_TupFromTlist) { - resultSlot = ExecProject(scanstate->cstate.cs_ProjInfo, &isDone); + resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone); if (isDone == ExprMultipleResult) return resultSlot; /* Done with that source tuple... */ - scanstate->cstate.cs_TupFromTlist = false; + node->ps.ps_TupFromTlist = false; } /* @@ -104,7 +102,7 @@ ExecScan(Scan *node, if (TupIsNull(slot)) { return ExecStoreTuple(NULL, - scanstate->cstate.cs_ProjInfo->pi_slot, + node->ps.ps_ProjInfo->pi_slot, InvalidBuffer, true); } @@ -130,10 +128,10 @@ ExecScan(Scan *node, * return it --- unless we find we can project no tuples from * this scan tuple, in which case continue scan. */ - resultSlot = ExecProject(scanstate->cstate.cs_ProjInfo, &isDone); + resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone); if (isDone != ExprEndResult) { - scanstate->cstate.cs_TupFromTlist = (isDone == ExprMultipleResult); + node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult); return resultSlot; } } diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index 7b0df664c7..f5a6863b1a 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.60 2002/09/28 20:00:19 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.61 2002/12/05 15:50:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -483,11 +483,11 @@ ExecSetSlotDescriptorIsNew(TupleTableSlot *slot, /* slot to change */ * ---------------- */ void -ExecInitResultTupleSlot(EState *estate, CommonState *commonstate) +ExecInitResultTupleSlot(EState *estate, PlanState *planstate) { INIT_SLOT_DEFS; INIT_SLOT_ALLOC; - commonstate->cs_ResultTupleSlot = slot; + planstate->ps_ResultTupleSlot = slot; } /* ---------------- @@ -495,11 +495,11 @@ ExecInitResultTupleSlot(EState *estate, CommonState *commonstate) * ---------------- */ void -ExecInitScanTupleSlot(EState *estate, CommonScanState *commonscanstate) +ExecInitScanTupleSlot(EState *estate, ScanState *scanstate) { INIT_SLOT_DEFS; INIT_SLOT_ALLOC; - commonscanstate->css_ScanTupleSlot = slot; + scanstate->ss_ScanTupleSlot = slot; } /* ---------------- diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index 86440d10f9..0dd17b7965 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.90 2002/09/04 20:31:18 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.91 2002/12/05 15:50:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -142,7 +142,7 @@ DisplayTupleCount(FILE *statfp) * ---------------- */ void -ExecAssignExprContext(EState *estate, CommonState *commonstate) +ExecAssignExprContext(EState *estate, PlanState *planstate) { ExprContext *econtext = makeNode(ExprContext); @@ -166,7 +166,7 @@ ExecAssignExprContext(EState *estate, CommonState *commonstate) econtext->ecxt_aggnulls = NULL; econtext->ecxt_callbacks = NULL; - commonstate->cs_ExprContext = econtext; + planstate->ps_ExprContext = econtext; } /* ---------------- @@ -259,10 +259,10 @@ MakePerTupleExprContext(EState *estate) * ---------------- */ void -ExecAssignResultType(CommonState *commonstate, +ExecAssignResultType(PlanState *planstate, TupleDesc tupDesc, bool shouldFree) { - TupleTableSlot *slot = commonstate->cs_ResultTupleSlot; + TupleTableSlot *slot = planstate->ps_ResultTupleSlot; ExecSetSlotDescriptor(slot, tupDesc, shouldFree); } @@ -272,15 +272,15 @@ ExecAssignResultType(CommonState *commonstate, * ---------------- */ void -ExecAssignResultTypeFromOuterPlan(Plan *node, CommonState *commonstate) +ExecAssignResultTypeFromOuterPlan(PlanState *planstate) { - Plan *outerPlan; + PlanState *outerPlan; TupleDesc tupDesc; - outerPlan = outerPlan(node); + outerPlan = outerPlanState(planstate); tupDesc = ExecGetTupType(outerPlan); - ExecAssignResultType(commonstate, tupDesc, false); + ExecAssignResultType(planstate, tupDesc, false); } /* ---------------- @@ -288,7 +288,7 @@ ExecAssignResultTypeFromOuterPlan(Plan *node, CommonState *commonstate) * ---------------- */ void -ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate) +ExecAssignResultTypeFromTL(PlanState *planstate) { ResultRelInfo *ri; bool hasoid = false; @@ -311,7 +311,7 @@ ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate) * each of the child plans of the topmost Append plan. So, this is * ugly but it works, for now ... */ - ri = node->state->es_result_relation_info; + ri = planstate->state->es_result_relation_info; if (ri != NULL) { Relation rel = ri->ri_RelationDesc; @@ -320,8 +320,13 @@ ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate) hasoid = rel->rd_rel->relhasoids; } - tupDesc = ExecTypeFromTL(node->targetlist, hasoid); - ExecAssignResultType(commonstate, tupDesc, true); + /* + * XXX Some plan nodes don't bother to set up planstate->targetlist, + * so use the underlying plan's targetlist instead. This will probably + * need to be fixed later. + */ + tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid); + ExecAssignResultType(planstate, tupDesc, true); } /* ---------------- @@ -329,9 +334,9 @@ ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate) * ---------------- */ TupleDesc -ExecGetResultType(CommonState *commonstate) +ExecGetResultType(PlanState *planstate) { - TupleTableSlot *slot = commonstate->cs_ResultTupleSlot; + TupleTableSlot *slot = planstate->ps_ResultTupleSlot; return slot->ttc_tupleDescriptor; } @@ -342,23 +347,23 @@ ExecGetResultType(CommonState *commonstate) * ---------------- */ void -ExecAssignProjectionInfo(Plan *node, CommonState *commonstate) +ExecAssignProjectionInfo(PlanState *planstate) { ProjectionInfo *projInfo; List *targetList; int len; - targetList = node->targetlist; + targetList = planstate->targetlist; len = ExecTargetListLength(targetList); projInfo = makeNode(ProjectionInfo); projInfo->pi_targetlist = targetList; projInfo->pi_len = len; projInfo->pi_tupValue = (len <= 0) ? NULL : (Datum *) palloc(sizeof(Datum) * len); - projInfo->pi_exprContext = commonstate->cs_ExprContext; - projInfo->pi_slot = commonstate->cs_ResultTupleSlot; + projInfo->pi_exprContext = planstate->ps_ExprContext; + projInfo->pi_slot = planstate->ps_ResultTupleSlot; - commonstate->cs_ProjInfo = projInfo; + planstate->ps_ProjInfo = projInfo; } @@ -367,7 +372,7 @@ ExecAssignProjectionInfo(Plan *node, CommonState *commonstate) * ---------------- */ void -ExecFreeProjectionInfo(CommonState *commonstate) +ExecFreeProjectionInfo(PlanState *planstate) { ProjectionInfo *projInfo; @@ -375,7 +380,7 @@ ExecFreeProjectionInfo(CommonState *commonstate) * get projection info. if NULL then this node has none so we just * return. */ - projInfo = commonstate->cs_ProjInfo; + projInfo = planstate->ps_ProjInfo; if (projInfo == NULL) return; @@ -386,7 +391,7 @@ ExecFreeProjectionInfo(CommonState *commonstate) pfree(projInfo->pi_tupValue); pfree(projInfo); - commonstate->cs_ProjInfo = NULL; + planstate->ps_ProjInfo = NULL; } /* ---------------- @@ -394,7 +399,7 @@ ExecFreeProjectionInfo(CommonState *commonstate) * ---------------- */ void -ExecFreeExprContext(CommonState *commonstate) +ExecFreeExprContext(PlanState *planstate) { ExprContext *econtext; @@ -402,7 +407,7 @@ ExecFreeExprContext(CommonState *commonstate) * get expression context. if NULL then this node has none so we just * return. */ - econtext = commonstate->cs_ExprContext; + econtext = planstate->ps_ExprContext; if (econtext == NULL) return; @@ -416,7 +421,7 @@ ExecFreeExprContext(CommonState *commonstate) */ MemoryContextDelete(econtext->ecxt_per_tuple_memory); pfree(econtext); - commonstate->cs_ExprContext = NULL; + planstate->ps_ExprContext = NULL; } /* ---------------------------------------------------------------- @@ -434,9 +439,9 @@ ExecFreeExprContext(CommonState *commonstate) * ---------------- */ TupleDesc -ExecGetScanType(CommonScanState *csstate) +ExecGetScanType(ScanState *scanstate) { - TupleTableSlot *slot = csstate->css_ScanTupleSlot; + TupleTableSlot *slot = scanstate->ss_ScanTupleSlot; return slot->ttc_tupleDescriptor; } @@ -446,10 +451,10 @@ ExecGetScanType(CommonScanState *csstate) * ---------------- */ void -ExecAssignScanType(CommonScanState *csstate, +ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc, bool shouldFree) { - TupleTableSlot *slot = csstate->css_ScanTupleSlot; + TupleTableSlot *slot = scanstate->ss_ScanTupleSlot; ExecSetSlotDescriptor(slot, tupDesc, shouldFree); } @@ -459,15 +464,15 @@ ExecAssignScanType(CommonScanState *csstate, * ---------------- */ void -ExecAssignScanTypeFromOuterPlan(Plan *node, CommonScanState *csstate) +ExecAssignScanTypeFromOuterPlan(ScanState *scanstate) { - Plan *outerPlan; + PlanState *outerPlan; TupleDesc tupDesc; - outerPlan = outerPlan(node); + outerPlan = outerPlanState(scanstate); tupDesc = ExecGetTupType(outerPlan); - ExecAssignScanType(csstate, tupDesc, false); + ExecAssignScanType(scanstate, tupDesc, false); } @@ -718,7 +723,7 @@ ExecInsertIndexTuples(TupleTableSlot *slot, } void -SetChangedParamList(Plan *node, List *newchg) +SetChangedParamList(PlanState *node, List *newchg) { List *nl; @@ -727,8 +732,8 @@ SetChangedParamList(Plan *node, List *newchg) int paramId = lfirsti(nl); /* if this node doesn't depend on a param ... */ - if (!intMember(paramId, node->extParam) && - !intMember(paramId, node->locParam)) + if (!intMember(paramId, node->plan->extParam) && + !intMember(paramId, node->plan->locParam)) continue; /* if this param is already in list of changed ones ... */ if (intMember(paramId, node->chgParam)) diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index 71166d9096..328aea5f07 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.60 2002/11/13 00:39:47 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.61 2002/12/05 15:50:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -28,7 +28,9 @@ /* - * We have an execution_state record for each query in a function. + * We have an execution_state record for each query in a function. Each + * record contains a querytree and plantree for its query. If the query + * is currently in F_EXEC_RUN state then there's a QueryDesc too. */ typedef enum { @@ -37,10 +39,11 @@ typedef enum typedef struct local_es { - QueryDesc *qd; - EState *estate; struct local_es *next; ExecStatus status; + Query *query; + Plan *plan; + QueryDesc *qd; /* null unless status == RUN */ } execution_state; #define LAST_POSTQUEL_COMMAND(es) ((es)->next == (execution_state *) NULL) @@ -62,6 +65,8 @@ typedef struct * we end execution of the function and * free stuff */ + ParamListInfo paramLI; /* Param list representing current args */ + /* head of linked list of execution_state records */ execution_state *func_state; } SQLFunctionCache; @@ -73,10 +78,11 @@ typedef SQLFunctionCache *SQLFunctionCachePtr; static execution_state *init_execution_state(char *src, Oid *argOidVect, int nargs); static void init_sql_fcache(FmgrInfo *finfo); -static void postquel_start(execution_state *es); +static void postquel_start(execution_state *es, SQLFunctionCachePtr fcache); static TupleTableSlot *postquel_getnext(execution_state *es); static void postquel_end(execution_state *es); -static void postquel_sub_params(execution_state *es, FunctionCallInfo fcinfo); +static void postquel_sub_params(SQLFunctionCachePtr fcache, + FunctionCallInfo fcinfo); static Datum postquel_execute(execution_state *es, FunctionCallInfo fcinfo, SQLFunctionCachePtr fcache); @@ -101,7 +107,6 @@ init_execution_state(char *src, Oid *argOidVect, int nargs) Query *queryTree = lfirst(qtl_item); Plan *planTree; execution_state *newes; - EState *estate; planTree = pg_plan_query(queryTree); @@ -113,29 +118,9 @@ init_execution_state(char *src, Oid *argOidVect, int nargs) newes->next = NULL; newes->status = F_EXEC_START; - newes->qd = CreateQueryDesc(queryTree, planTree, None, NULL); - newes->estate = estate = CreateExecutorState(); - - if (nargs > 0) - { - int i; - ParamListInfo paramLI; - - paramLI = (ParamListInfo) palloc0((nargs + 1) * sizeof(ParamListInfoData)); - - estate->es_param_list_info = paramLI; - - for (i = 0; i < nargs; paramLI++, i++) - { - paramLI->kind = PARAM_NUM; - paramLI->id = i + 1; - paramLI->isnull = false; - paramLI->value = (Datum) NULL; - } - paramLI->kind = PARAM_INVALID; - } - else - estate->es_param_list_info = (ParamListInfo) NULL; + newes->query = queryTree; + newes->plan = planTree; + newes->qd = NULL; preves = newes; } @@ -219,6 +204,10 @@ init_sql_fcache(FmgrInfo *finfo) else fcache->funcSlot = NULL; + /* + * Parse and plan the queries. We need the argument info to pass + * to the parser. + */ nargs = procedureStruct->pronargs; if (nargs > 0) @@ -252,15 +241,18 @@ init_sql_fcache(FmgrInfo *finfo) static void -postquel_start(execution_state *es) +postquel_start(execution_state *es, SQLFunctionCachePtr fcache) { - /* - * Do nothing for utility commands. (create, destroy...) DZ - - * 30-8-1996 - */ - if (es->qd->operation == CMD_UTILITY) - return; - ExecutorStart(es->qd, es->estate); + Assert(es->qd == NULL); + es->qd = CreateQueryDesc(es->query, es->plan, + None, NULL, + fcache->paramLI, false); + + /* Utility commands don't need Executor. */ + if (es->qd->operation != CMD_UTILITY) + ExecutorStart(es->qd); + + es->status = F_EXEC_RUN; } static TupleTableSlot * @@ -282,40 +274,52 @@ postquel_getnext(execution_state *es) /* If it's not the last command, just run it to completion */ count = (LAST_POSTQUEL_COMMAND(es)) ? 1L : 0L; - return ExecutorRun(es->qd, es->estate, ForwardScanDirection, count); + return ExecutorRun(es->qd, ForwardScanDirection, count); } static void postquel_end(execution_state *es) { - /* - * Do nothing for utility commands. (create, destroy...) DZ - - * 30-8-1996 - */ - if (es->qd->operation == CMD_UTILITY) - return; - ExecutorEnd(es->qd, es->estate); + /* Utility commands don't need Executor. */ + if (es->qd->operation != CMD_UTILITY) + ExecutorEnd(es->qd); + + pfree(es->qd); + es->qd = NULL; + + es->status = F_EXEC_DONE; } +/* Build ParamListInfo array representing current arguments */ static void -postquel_sub_params(execution_state *es, FunctionCallInfo fcinfo) +postquel_sub_params(SQLFunctionCachePtr fcache, + FunctionCallInfo fcinfo) { - EState *estate; ParamListInfo paramLI; + int nargs = fcinfo->nargs; - estate = es->estate; - paramLI = estate->es_param_list_info; - - while (paramLI->kind != PARAM_INVALID) + if (nargs > 0) { - if (paramLI->kind == PARAM_NUM) + int i; + + paramLI = (ParamListInfo) palloc0((nargs + 1) * sizeof(ParamListInfoData)); + + for (i = 0; i < nargs; i++) { - Assert(paramLI->id <= fcinfo->nargs); - paramLI->value = fcinfo->arg[paramLI->id - 1]; - paramLI->isnull = fcinfo->argnull[paramLI->id - 1]; + paramLI[i].kind = PARAM_NUM; + paramLI[i].id = i + 1; + paramLI[i].value = fcinfo->arg[i]; + paramLI[i].isnull = fcinfo->argnull[i]; } - paramLI++; + paramLI[nargs].kind = PARAM_INVALID; } + else + paramLI = (ParamListInfo) NULL; + + if (fcache->paramLI) + pfree(fcache->paramLI); + + fcache->paramLI = paramLI; } static TupleTableSlot * @@ -359,27 +363,14 @@ postquel_execute(execution_state *es, TupleTableSlot *slot; Datum value; - /* - * It's more right place to do it (before - * postquel_start->ExecutorStart). Now - * ExecutorStart->ExecInitIndexScan->ExecEvalParam works ok. (But - * note: I HOPE we can do it here). - vadim 01/22/97 - */ - if (fcinfo->nargs > 0) - postquel_sub_params(es, fcinfo); - if (es->status == F_EXEC_START) - { - postquel_start(es); - es->status = F_EXEC_RUN; - } + postquel_start(es, fcache); slot = postquel_getnext(es); if (TupIsNull(slot)) { postquel_end(es); - es->status = F_EXEC_DONE; fcinfo->isnull = true; /* @@ -438,10 +429,7 @@ postquel_execute(execution_state *es, * execution now. */ if (!fcinfo->flinfo->fn_retset) - { postquel_end(es); - es->status = F_EXEC_DONE; - } return value; } @@ -471,7 +459,7 @@ fmgr_sql(PG_FUNCTION_ARGS) oldcontext = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt); /* - * Initialize fcache and execution state if first time through. + * Initialize fcache (build plans) if first time through. */ fcache = (SQLFunctionCachePtr) fcinfo->flinfo->fn_extra; if (fcache == NULL) @@ -482,6 +470,13 @@ fmgr_sql(PG_FUNCTION_ARGS) es = fcache->func_state; /* + * Convert params to appropriate format if starting a fresh execution. + * (If continuing execution, we can re-use prior params.) + */ + if (es && es->status == F_EXEC_START) + postquel_sub_params(fcache, fcinfo); + + /* * Find first unfinished query in function. */ while (es && es->status == F_EXEC_DONE) @@ -506,7 +501,7 @@ fmgr_sql(PG_FUNCTION_ARGS) if (es == (execution_state *) NULL) { /* - * Reset the execution states to start over again + * Reset the execution states to start over again on next call. */ es = fcache->func_state; while (es) diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 82e9f48e1e..bdbe61cb10 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -45,7 +45,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.97 2002/11/29 21:39:11 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.98 2002/12/05 15:50:32 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -212,11 +212,12 @@ static void finalize_aggregate(AggState *aggstate, AggStatePerAgg peraggstate, AggStatePerGroup pergroupstate, Datum *resultVal, bool *resultIsNull); -static void build_hash_table(Agg *node); -static AggHashEntry lookup_hash_entry(Agg *node, TupleTableSlot *slot); -static TupleTableSlot *agg_retrieve_direct(Agg *node); -static void agg_fill_hash_table(Agg *node); -static TupleTableSlot *agg_retrieve_hash_table(Agg *node); +static void build_hash_table(AggState *aggstate); +static AggHashEntry lookup_hash_entry(AggState *aggstate, + TupleTableSlot *slot); +static TupleTableSlot *agg_retrieve_direct(AggState *aggstate); +static void agg_fill_hash_table(AggState *aggstate); +static TupleTableSlot *agg_retrieve_hash_table(AggState *aggstate); static Datum GetAggInitVal(Datum textInitVal, Oid transtype); @@ -521,7 +522,7 @@ finalize_aggregate(AggState *aggstate, { MemoryContext oldContext; - oldContext = MemoryContextSwitchTo(aggstate->csstate.cstate.cs_ExprContext->ecxt_per_tuple_memory); + oldContext = MemoryContextSwitchTo(aggstate->ss.ps.ps_ExprContext->ecxt_per_tuple_memory); /* * Apply the agg's finalfn if one is provided, else return transValue. @@ -572,9 +573,9 @@ finalize_aggregate(AggState *aggstate, * The hash table always lives in the aggcontext memory context. */ static void -build_hash_table(Agg *node) +build_hash_table(AggState *aggstate) { - AggState *aggstate = node->aggstate; + Agg *node = (Agg *) aggstate->ss.ps.plan; AggHashTable hashtable; Size tabsize; @@ -596,9 +597,9 @@ build_hash_table(Agg *node) * When called, CurrentMemoryContext should be the per-query context. */ static AggHashEntry -lookup_hash_entry(Agg *node, TupleTableSlot *slot) +lookup_hash_entry(AggState *aggstate, TupleTableSlot *slot) { - AggState *aggstate = node->aggstate; + Agg *node = (Agg *) aggstate->ss.ps.plan; AggHashTable hashtable = aggstate->hashtable; MemoryContext tmpmem = aggstate->tmpcontext->ecxt_per_tuple_memory; HeapTuple tuple = slot->val; @@ -684,16 +685,14 @@ lookup_hash_entry(Agg *node, TupleTableSlot *slot) * the result tuple. */ TupleTableSlot * -ExecAgg(Agg *node) +ExecAgg(AggState *node) { - AggState *aggstate = node->aggstate; - - if (aggstate->agg_done) + if (node->agg_done) return NULL; - if (node->aggstrategy == AGG_HASHED) + if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED) { - if (!aggstate->table_filled) + if (!node->table_filled) agg_fill_hash_table(node); return agg_retrieve_hash_table(node); } @@ -707,10 +706,10 @@ ExecAgg(Agg *node) * ExecAgg for non-hashed case */ static TupleTableSlot * -agg_retrieve_direct(Agg *node) +agg_retrieve_direct(AggState *aggstate) { - AggState *aggstate; - Plan *outerPlan; + Agg *node = (Agg *) aggstate->ss.ps.plan; + PlanState *outerPlan; ExprContext *econtext; ExprContext *tmpcontext; ProjectionInfo *projInfo; @@ -726,22 +725,21 @@ agg_retrieve_direct(Agg *node) /* * get state info from node */ - aggstate = node->aggstate; - outerPlan = outerPlan(node); + outerPlan = outerPlanState(aggstate); /* econtext is the per-output-tuple expression context */ - econtext = aggstate->csstate.cstate.cs_ExprContext; + econtext = aggstate->ss.ps.ps_ExprContext; aggvalues = econtext->ecxt_aggvalues; aggnulls = econtext->ecxt_aggnulls; /* tmpcontext is the per-input-tuple expression context */ tmpcontext = aggstate->tmpcontext; - projInfo = aggstate->csstate.cstate.cs_ProjInfo; + projInfo = aggstate->ss.ps.ps_ProjInfo; peragg = aggstate->peragg; pergroup = aggstate->pergroup; - firstSlot = aggstate->csstate.css_ScanTupleSlot; + firstSlot = aggstate->ss.ss_ScanTupleSlot; /* * We loop retrieving groups until we find one matching - * node->plan.qual + * aggstate->ss.ps.qual */ do { @@ -754,7 +752,7 @@ agg_retrieve_direct(Agg *node) */ if (aggstate->grp_firstTuple == NULL) { - outerslot = ExecProcNode(outerPlan, (Plan *) node); + outerslot = ExecProcNode(outerPlan); if (!TupIsNull(outerslot)) { /* @@ -810,7 +808,7 @@ agg_retrieve_direct(Agg *node) /* Reset per-input-tuple context after each tuple */ ResetExprContext(tmpcontext); - outerslot = ExecProcNode(outerPlan, (Plan *) node); + outerslot = ExecProcNode(outerPlan); if (TupIsNull(outerslot)) { /* no more outer-plan tuples available */ @@ -917,7 +915,7 @@ agg_retrieve_direct(Agg *node) * Otherwise, return the tuple. */ } - while (!ExecQual(node->plan.qual, econtext, false)); + while (!ExecQual(aggstate->ss.ps.qual, econtext, false)); return resultSlot; } @@ -926,10 +924,9 @@ agg_retrieve_direct(Agg *node) * ExecAgg for hashed case: phase 1, read input and build hash table */ static void -agg_fill_hash_table(Agg *node) +agg_fill_hash_table(AggState *aggstate) { - AggState *aggstate; - Plan *outerPlan; + PlanState *outerPlan; ExprContext *tmpcontext; AggHashEntry entry; TupleTableSlot *outerslot; @@ -937,8 +934,7 @@ agg_fill_hash_table(Agg *node) /* * get state info from node */ - aggstate = node->aggstate; - outerPlan = outerPlan(node); + outerPlan = outerPlanState(aggstate); /* tmpcontext is the per-input-tuple expression context */ tmpcontext = aggstate->tmpcontext; @@ -948,14 +944,14 @@ agg_fill_hash_table(Agg *node) */ for (;;) { - outerslot = ExecProcNode(outerPlan, (Plan *) node); + outerslot = ExecProcNode(outerPlan); if (TupIsNull(outerslot)) break; /* set up for advance_aggregates call */ tmpcontext->ecxt_scantuple = outerslot; /* Find or build hashtable entry for this tuple's group */ - entry = lookup_hash_entry(node, outerslot); + entry = lookup_hash_entry(aggstate, outerslot); /* Advance the aggregates */ advance_aggregates(aggstate, entry->pergroup); @@ -974,9 +970,8 @@ agg_fill_hash_table(Agg *node) * ExecAgg for hashed case: phase 2, retrieving groups from hash table */ static TupleTableSlot * -agg_retrieve_hash_table(Agg *node) +agg_retrieve_hash_table(AggState *aggstate) { - AggState *aggstate; ExprContext *econtext; ProjectionInfo *projInfo; Datum *aggvalues; @@ -992,19 +987,18 @@ agg_retrieve_hash_table(Agg *node) /* * get state info from node */ - aggstate = node->aggstate; /* econtext is the per-output-tuple expression context */ - econtext = aggstate->csstate.cstate.cs_ExprContext; + econtext = aggstate->ss.ps.ps_ExprContext; aggvalues = econtext->ecxt_aggvalues; aggnulls = econtext->ecxt_aggnulls; - projInfo = aggstate->csstate.cstate.cs_ProjInfo; + projInfo = aggstate->ss.ps.ps_ProjInfo; peragg = aggstate->peragg; hashtable = aggstate->hashtable; - firstSlot = aggstate->csstate.css_ScanTupleSlot; + firstSlot = aggstate->ss.ss_ScanTupleSlot; /* - * We loop retrieving groups until we find one matching - * node->plan.qual + * We loop retrieving groups until we find one satisfying + * aggstate->ss.ps.qual */ do { @@ -1071,7 +1065,7 @@ agg_retrieve_hash_table(Agg *node) * Otherwise, return the tuple. */ } - while (!ExecQual(node->plan.qual, econtext, false)); + while (!ExecQual(aggstate->ss.ps.qual, econtext, false)); return resultSlot; } @@ -1083,8 +1077,8 @@ agg_retrieve_hash_table(Agg *node) * planner and initializes its outer subtree * ----------------- */ -bool -ExecInitAgg(Agg *node, EState *estate, Plan *parent) +AggState * +ExecInitAgg(Agg *node, EState *estate) { AggState *aggstate; AggStatePerAgg peragg; @@ -1095,15 +1089,14 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent) List *alist; /* - * assign the node's execution state - */ - node->plan.state = estate; - - /* * create state structure */ aggstate = makeNode(AggState); - node->aggstate = aggstate; + aggstate->ss.ps.plan = (Plan *) node; + aggstate->ss.ps.state = estate; + + aggstate->aggs = NIL; + aggstate->numaggs = 0; aggstate->eqfunctions = NULL; aggstate->peragg = NULL; aggstate->agg_done = false; @@ -1112,37 +1105,13 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent) aggstate->hashtable = NULL; /* - * find aggregates in targetlist and quals - * - * Note: pull_agg_clauses also checks that no aggs contain other agg - * calls in their arguments. This would make no sense under SQL - * semantics anyway (and it's forbidden by the spec). Because that is - * true, we don't need to worry about evaluating the aggs in any - * particular order. - */ - aggstate->aggs = nconc(pull_agg_clause((Node *) node->plan.targetlist), - pull_agg_clause((Node *) node->plan.qual)); - aggstate->numaggs = numaggs = length(aggstate->aggs); - if (numaggs <= 0) - { - /* - * This is not an error condition: we might be using the Agg node just - * to do hash-based grouping. Even in the regular case, - * constant-expression simplification could optimize away all of the - * Aggrefs in the targetlist and qual. So keep going, but force local - * copy of numaggs positive so that palloc()s below don't choke. - */ - numaggs = 1; - } - - /* * Create expression contexts. We need two, one for per-input-tuple * processing and one for per-output-tuple processing. We cheat a little * by using ExecAssignExprContext() to build both. */ - ExecAssignExprContext(estate, &aggstate->csstate.cstate); - aggstate->tmpcontext = aggstate->csstate.cstate.cs_ExprContext; - ExecAssignExprContext(estate, &aggstate->csstate.cstate); + ExecAssignExprContext(estate, &aggstate->ss.ps); + aggstate->tmpcontext = aggstate->ss.ps.ps_ExprContext; + ExecAssignExprContext(estate, &aggstate->ss.ps); /* * We also need a long-lived memory context for holding hashtable @@ -1163,14 +1132,64 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent) /* * tuple table initialization */ - ExecInitScanTupleSlot(estate, &aggstate->csstate); - ExecInitResultTupleSlot(estate, &aggstate->csstate.cstate); + ExecInitScanTupleSlot(estate, &aggstate->ss); + ExecInitResultTupleSlot(estate, &aggstate->ss.ps); + + /* + * initialize child expressions + * + * Note: ExecInitExpr finds Aggrefs for us, and also checks that no aggs + * contain other agg calls in their arguments. This would make no sense + * under SQL semantics anyway (and it's forbidden by the spec). Because + * that is true, we don't need to worry about evaluating the aggs in any + * particular order. + */ + aggstate->ss.ps.targetlist = (List *) + ExecInitExpr((Node *) node->plan.targetlist, + (PlanState *) aggstate); + aggstate->ss.ps.qual = (List *) + ExecInitExpr((Node *) node->plan.qual, + (PlanState *) aggstate); + + /* + * initialize child nodes + */ + outerPlan = outerPlan(node); + outerPlanState(aggstate) = ExecInitNode(outerPlan, estate); + + /* + * initialize source tuple type. + */ + ExecAssignScanTypeFromOuterPlan(&aggstate->ss); + + /* + * Initialize result tuple type and projection info. + */ + ExecAssignResultTypeFromTL(&aggstate->ss.ps); + ExecAssignProjectionInfo(&aggstate->ss.ps); + + /* + * get the count of aggregates in targetlist and quals + */ + numaggs = aggstate->numaggs; + Assert(numaggs == length(aggstate->aggs)); + if (numaggs <= 0) + { + /* + * This is not an error condition: we might be using the Agg node just + * to do hash-based grouping. Even in the regular case, + * constant-expression simplification could optimize away all of the + * Aggrefs in the targetlist and qual. So keep going, but force local + * copy of numaggs positive so that palloc()s below don't choke. + */ + numaggs = 1; + } /* * Set up aggregate-result storage in the output expr context, and also * allocate my private per-agg working storage */ - econtext = aggstate->csstate.cstate.cs_ExprContext; + econtext = aggstate->ss.ps.ps_ExprContext; econtext->ecxt_aggvalues = (Datum *) palloc0(sizeof(Datum) * numaggs); econtext->ecxt_aggnulls = (bool *) palloc0(sizeof(bool) * numaggs); @@ -1179,7 +1198,7 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent) if (node->aggstrategy == AGG_HASHED) { - build_hash_table(node); + build_hash_table(aggstate); aggstate->table_filled = false; } else @@ -1191,29 +1210,12 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent) } /* - * initialize child nodes - */ - outerPlan = outerPlan(node); - ExecInitNode(outerPlan, estate, (Plan *) node); - - /* - * initialize source tuple type. - */ - ExecAssignScanTypeFromOuterPlan((Plan *) node, &aggstate->csstate); - - /* - * Initialize result tuple type and projection info. - */ - ExecAssignResultTypeFromTL((Plan *) node, &aggstate->csstate.cstate); - ExecAssignProjectionInfo((Plan *) node, &aggstate->csstate.cstate); - - /* * If we are grouping, precompute fmgr lookup data for inner loop */ if (node->numCols > 0) { aggstate->eqfunctions = - execTuplesMatchPrepare(ExecGetScanType(&aggstate->csstate), + execTuplesMatchPrepare(ExecGetScanType(&aggstate->ss), node->numCols, node->grpColIdx); } @@ -1330,7 +1332,7 @@ ExecInitAgg(Agg *node, EState *estate, Plan *parent) ReleaseSysCache(aggTuple); } - return TRUE; + return aggstate; } static Datum @@ -1372,84 +1374,82 @@ ExecCountSlotsAgg(Agg *node) } void -ExecEndAgg(Agg *node) +ExecEndAgg(AggState *node) { - AggState *aggstate = node->aggstate; - Plan *outerPlan; + PlanState *outerPlan; int aggno; /* Make sure we have closed any open tuplesorts */ - for (aggno = 0; aggno < aggstate->numaggs; aggno++) + for (aggno = 0; aggno < node->numaggs; aggno++) { - AggStatePerAgg peraggstate = &aggstate->peragg[aggno]; + AggStatePerAgg peraggstate = &node->peragg[aggno]; if (peraggstate->sortstate) tuplesort_end(peraggstate->sortstate); } - ExecFreeProjectionInfo(&aggstate->csstate.cstate); + ExecFreeProjectionInfo(&node->ss.ps); /* * Free both the expr contexts. */ - ExecFreeExprContext(&aggstate->csstate.cstate); - aggstate->csstate.cstate.cs_ExprContext = aggstate->tmpcontext; - ExecFreeExprContext(&aggstate->csstate.cstate); + ExecFreeExprContext(&node->ss.ps); + node->ss.ps.ps_ExprContext = node->tmpcontext; + ExecFreeExprContext(&node->ss.ps); - MemoryContextDelete(aggstate->aggcontext); + MemoryContextDelete(node->aggcontext); - outerPlan = outerPlan(node); - ExecEndNode(outerPlan, (Plan *) node); + outerPlan = outerPlanState(node); + ExecEndNode(outerPlan); /* clean up tuple table */ - ExecClearTuple(aggstate->csstate.css_ScanTupleSlot); - if (aggstate->grp_firstTuple != NULL) + ExecClearTuple(node->ss.ss_ScanTupleSlot); + if (node->grp_firstTuple != NULL) { - heap_freetuple(aggstate->grp_firstTuple); - aggstate->grp_firstTuple = NULL; + heap_freetuple(node->grp_firstTuple); + node->grp_firstTuple = NULL; } } void -ExecReScanAgg(Agg *node, ExprContext *exprCtxt, Plan *parent) +ExecReScanAgg(AggState *node, ExprContext *exprCtxt) { - AggState *aggstate = node->aggstate; - ExprContext *econtext = aggstate->csstate.cstate.cs_ExprContext; + ExprContext *econtext = node->ss.ps.ps_ExprContext; int aggno; /* Make sure we have closed any open tuplesorts */ - for (aggno = 0; aggno < aggstate->numaggs; aggno++) + for (aggno = 0; aggno < node->numaggs; aggno++) { - AggStatePerAgg peraggstate = &aggstate->peragg[aggno]; + AggStatePerAgg peraggstate = &node->peragg[aggno]; if (peraggstate->sortstate) tuplesort_end(peraggstate->sortstate); peraggstate->sortstate = NULL; } - aggstate->agg_done = false; - if (aggstate->grp_firstTuple != NULL) + node->agg_done = false; + if (node->grp_firstTuple != NULL) { - heap_freetuple(aggstate->grp_firstTuple); - aggstate->grp_firstTuple = NULL; + heap_freetuple(node->grp_firstTuple); + node->grp_firstTuple = NULL; } - MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * aggstate->numaggs); - MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * aggstate->numaggs); + MemSet(econtext->ecxt_aggvalues, 0, sizeof(Datum) * node->numaggs); + MemSet(econtext->ecxt_aggnulls, 0, sizeof(bool) * node->numaggs); - MemoryContextReset(aggstate->aggcontext); + MemoryContextReset(node->aggcontext); - if (node->aggstrategy == AGG_HASHED) + if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED) { build_hash_table(node); - aggstate->table_filled = false; + node->table_filled = false; } /* * if chgParam of subnode is not null then plan will be re-scanned by * first ExecProcNode. */ - if (((Plan *) node)->lefttree->chgParam == NULL) - ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node); + if (((PlanState *) node)->lefttree->chgParam == NIL) + ExecReScan(((PlanState *) node)->lefttree, exprCtxt); } /* diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c index 9d0e564222..bcb50fb797 100644 --- a/src/backend/executor/nodeAppend.c +++ b/src/backend/executor/nodeAppend.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.50 2002/11/13 00:39:47 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeAppend.c,v 1.51 2002/12/05 15:50:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -62,30 +62,27 @@ #include "executor/nodeAppend.h" #include "parser/parsetree.h" -static bool exec_append_initialize_next(Append *node); +static bool exec_append_initialize_next(AppendState *appendstate); /* ---------------------------------------------------------------- * exec_append_initialize_next * - * Sets up the append node state (i.e. the append state node) - * for the "next" scan. + * Sets up the append state node for the "next" scan. * * Returns t iff there is a "next" scan to process. * ---------------------------------------------------------------- */ static bool -exec_append_initialize_next(Append *node) +exec_append_initialize_next(AppendState *appendstate) { EState *estate; - AppendState *appendstate; int whichplan; /* * get information from the append node */ - estate = node->plan.state; - appendstate = node->appendstate; + estate = appendstate->ps.state; whichplan = appendstate->as_whichplan; if (whichplan < appendstate->as_firstplan) @@ -116,7 +113,7 @@ exec_append_initialize_next(Append *node) * If we are controlling the target relation, select the proper * active ResultRelInfo and junk filter for this target. */ - if (node->isTarget) + if (((Append *) appendstate->ps.plan)->isTarget) { Assert(whichplan < estate->es_num_result_relations); estate->es_result_relation_info = @@ -132,9 +129,7 @@ exec_append_initialize_next(Append *node) /* ---------------------------------------------------------------- * ExecInitAppend * - * Begins all of the subscans of the append node, storing the - * scan structures in the 'initialized' vector of the append-state - * structure. + * Begin all of the subscans of the append node. * * (This is potentially wasteful, since the entire result of the * append node may not be scanned, but this way all of the @@ -146,36 +141,31 @@ exec_append_initialize_next(Append *node) * subplan that corresponds to the target relation being checked. * ---------------------------------------------------------------- */ -bool -ExecInitAppend(Append *node, EState *estate, Plan *parent) +AppendState * +ExecInitAppend(Append *node, EState *estate) { - AppendState *appendstate; + AppendState *appendstate = makeNode(AppendState); + PlanState **appendplanstates; int nplans; - List *appendplans; - bool *initialized; int i; Plan *initNode; CXT1_printf("ExecInitAppend: context is %d\n", CurrentMemoryContext); /* - * assign execution state to node and get information for append state + * Set up empty vector of subplan states */ - node->plan.state = estate; + nplans = length(node->appendplans); - appendplans = node->appendplans; - nplans = length(appendplans); - - initialized = (bool *) palloc0(nplans * sizeof(bool)); + appendplanstates = (PlanState **) palloc0(nplans * sizeof(PlanState *)); /* * create new AppendState for our append node */ - appendstate = makeNode(AppendState); + appendstate->ps.plan = (Plan *) node; + appendstate->ps.state = estate; + appendstate->appendplans = appendplanstates; appendstate->as_nplans = nplans; - appendstate->as_initialized = initialized; - - node->appendstate = appendstate; /* * Do we want to scan just one subplan? (Special case for @@ -212,36 +202,36 @@ ExecInitAppend(Append *node, EState *estate, Plan *parent) * append nodes still have Result slots, which hold pointers to * tuples, so we have to initialize them. */ - ExecInitResultTupleSlot(estate, &appendstate->cstate); + ExecInitResultTupleSlot(estate, &appendstate->ps); /* * call ExecInitNode on each of the plans to be executed and save the - * results into the array "initialized". Note we *must* set + * results into the array "appendplans". Note we *must* set * estate->es_result_relation_info correctly while we initialize each * sub-plan; ExecAssignResultTypeFromTL depends on that! */ for (i = appendstate->as_firstplan; i <= appendstate->as_lastplan; i++) { appendstate->as_whichplan = i; - exec_append_initialize_next(node); + exec_append_initialize_next(appendstate); - initNode = (Plan *) nth(i, appendplans); - initialized[i] = ExecInitNode(initNode, estate, (Plan *) node); + initNode = (Plan *) nth(i, node->appendplans); + appendplanstates[i] = ExecInitNode(initNode, estate); } /* * initialize tuple type */ - ExecAssignResultTypeFromTL((Plan *) node, &appendstate->cstate); - appendstate->cstate.cs_ProjInfo = NULL; + ExecAssignResultTypeFromTL(&appendstate->ps); + appendstate->ps.ps_ProjInfo = NULL; /* * return the result from the first subplan's initialization */ appendstate->as_whichplan = appendstate->as_firstplan; - exec_append_initialize_next(node); + exec_append_initialize_next(appendstate); - return TRUE; + return appendstate; } int @@ -264,13 +254,11 @@ ExecCountSlotsAppend(Append *node) * ---------------------------------------------------------------- */ TupleTableSlot * -ExecProcAppend(Append *node) +ExecProcAppend(AppendState *node) { EState *estate; - AppendState *appendstate; int whichplan; - List *appendplans; - Plan *subnode; + PlanState *subnode; TupleTableSlot *result; TupleTableSlot *result_slot; ScanDirection direction; @@ -278,25 +266,20 @@ ExecProcAppend(Append *node) /* * get information from the node */ - appendstate = node->appendstate; - estate = node->plan.state; + estate = node->ps.state; direction = estate->es_direction; - appendplans = node->appendplans; - whichplan = appendstate->as_whichplan; - result_slot = appendstate->cstate.cs_ResultTupleSlot; + whichplan = node->as_whichplan; + result_slot = node->ps.ps_ResultTupleSlot; /* * figure out which subplan we are currently processing */ - subnode = (Plan *) nth(whichplan, appendplans); - - if (subnode == NULL) - elog(DEBUG1, "ExecProcAppend: subnode is NULL"); + subnode = node->appendplans[whichplan]; /* * get a tuple from the subplan */ - result = ExecProcNode(subnode, (Plan *) node); + result = ExecProcNode(subnode); if (!TupIsNull(result)) { @@ -316,9 +299,9 @@ ExecProcAppend(Append *node) * try processing again (recursively) */ if (ScanDirectionIsForward(direction)) - appendstate->as_whichplan++; + node->as_whichplan++; else - appendstate->as_whichplan--; + node->as_whichplan--; /* * return something from next node or an empty slot if all of our @@ -343,65 +326,56 @@ ExecProcAppend(Append *node) * ---------------------------------------------------------------- */ void -ExecEndAppend(Append *node) +ExecEndAppend(AppendState *node) { - EState *estate; - AppendState *appendstate; + PlanState **appendplans; int nplans; - List *appendplans; - bool *initialized; int i; /* * get information from the node */ - appendstate = node->appendstate; - estate = node->plan.state; appendplans = node->appendplans; - nplans = appendstate->as_nplans; - initialized = appendstate->as_initialized; + nplans = node->as_nplans; /* - * shut down each of the subscans + * shut down each of the subscans (that we've initialized) */ for (i = 0; i < nplans; i++) { - if (initialized[i]) - ExecEndNode((Plan *) nth(i, appendplans), (Plan *) node); + if (appendplans[i]) + ExecEndNode(appendplans[i]); } } void -ExecReScanAppend(Append *node, ExprContext *exprCtxt, Plan *parent) +ExecReScanAppend(AppendState *node, ExprContext *exprCtxt) { - AppendState *appendstate = node->appendstate; int i; - for (i = appendstate->as_firstplan; i <= appendstate->as_lastplan; i++) + for (i = node->as_firstplan; i <= node->as_lastplan; i++) { - Plan *subnode; - - subnode = (Plan *) nth(i, node->appendplans); + PlanState *subnode = node->appendplans[i]; /* * ExecReScan doesn't know about my subplans, so I have to do * changed-parameter signaling myself. */ - if (node->plan.chgParam != NULL) - SetChangedParamList(subnode, node->plan.chgParam); + if (node->ps.chgParam != NIL) + SetChangedParamList(subnode, node->ps.chgParam); /* * if chgParam of subnode is not null then plan will be re-scanned * by first ExecProcNode. */ - if (subnode->chgParam == NULL) + if (subnode->chgParam == NIL) { /* make sure estate is correct for this subnode (needed??) */ - appendstate->as_whichplan = i; + node->as_whichplan = i; exec_append_initialize_next(node); - ExecReScan(subnode, exprCtxt, (Plan *) node); + ExecReScan(subnode, exprCtxt); } } - appendstate->as_whichplan = appendstate->as_firstplan; + node->as_whichplan = node->as_firstplan; exec_append_initialize_next(node); } diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c index 97da70b2b7..f6df416d0f 100644 --- a/src/backend/executor/nodeFunctionscan.c +++ b/src/backend/executor/nodeFunctionscan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.13 2002/12/01 20:27:32 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.14 2002/12/05 15:50:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -34,7 +34,7 @@ #include "utils/lsyscache.h" -static TupleTableSlot *FunctionNext(FunctionScan *node); +static TupleTableSlot *FunctionNext(FunctionScanState *node); static bool tupledesc_mismatch(TupleDesc tupdesc1, TupleDesc tupdesc2); /* ---------------------------------------------------------------- @@ -48,24 +48,22 @@ static bool tupledesc_mismatch(TupleDesc tupdesc1, TupleDesc tupdesc2); * ---------------------------------------------------------------- */ static TupleTableSlot * -FunctionNext(FunctionScan *node) +FunctionNext(FunctionScanState *node) { TupleTableSlot *slot; EState *estate; ScanDirection direction; Tuplestorestate *tuplestorestate; - FunctionScanState *scanstate; bool should_free; HeapTuple heapTuple; /* * get information from the estate and scan state */ - scanstate = (FunctionScanState *) node->scan.scanstate; - estate = node->scan.plan.state; + estate = node->ss.ps.state; direction = estate->es_direction; - tuplestorestate = scanstate->tuplestorestate; + tuplestorestate = node->tuplestorestate; /* * If first time through, read all tuples from function and put them @@ -74,13 +72,13 @@ FunctionNext(FunctionScan *node) */ if (tuplestorestate == NULL) { - ExprContext *econtext = scanstate->csstate.cstate.cs_ExprContext; + ExprContext *econtext = node->ss.ps.ps_ExprContext; TupleDesc funcTupdesc; - scanstate->tuplestorestate = tuplestorestate = - ExecMakeTableFunctionResult(scanstate->funcexpr, + node->tuplestorestate = tuplestorestate = + ExecMakeTableFunctionResult(node->funcexpr, econtext, - scanstate->tupdesc, + node->tupdesc, &funcTupdesc); /* @@ -89,14 +87,14 @@ FunctionNext(FunctionScan *node) * well do it always. */ if (funcTupdesc && - tupledesc_mismatch(scanstate->tupdesc, funcTupdesc)) + tupledesc_mismatch(node->tupdesc, funcTupdesc)) elog(ERROR, "Query-specified return tuple and actual function return tuple do not match"); } /* * Get the next tuple from tuplestore. Return NULL if no more tuples. */ - slot = scanstate->csstate.css_ScanTupleSlot; + slot = node->ss.ss_ScanTupleSlot; if (tuplestorestate) heapTuple = tuplestore_getheaptuple(tuplestorestate, ScanDirectionIsForward(direction), @@ -121,20 +119,20 @@ FunctionNext(FunctionScan *node) */ TupleTableSlot * -ExecFunctionScan(FunctionScan *node) +ExecFunctionScan(FunctionScanState *node) { /* * use FunctionNext as access method */ - return ExecScan(&node->scan, (ExecScanAccessMtd) FunctionNext); + return ExecScan(&node->ss, (ExecScanAccessMtd) FunctionNext); } /* ---------------------------------------------------------------- * ExecInitFunctionScan * ---------------------------------------------------------------- */ -bool -ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent) +FunctionScanState * +ExecInitFunctionScan(FunctionScan *node, EState *estate) { FunctionScanState *scanstate; RangeTblEntry *rte; @@ -145,34 +143,40 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent) /* * FunctionScan should not have any children. */ - Assert(outerPlan((Plan *) node) == NULL); - Assert(innerPlan((Plan *) node) == NULL); - - /* - * assign the node's execution state - */ - node->scan.plan.state = estate; + Assert(outerPlan(node) == NULL); + Assert(innerPlan(node) == NULL); /* * create new ScanState for node */ scanstate = makeNode(FunctionScanState); - node->scan.scanstate = &scanstate->csstate; + scanstate->ss.ps.plan = (Plan *) node; + scanstate->ss.ps.state = estate; /* * Miscellaneous initialization * * create expression context for node */ - ExecAssignExprContext(estate, &scanstate->csstate.cstate); + ExecAssignExprContext(estate, &scanstate->ss.ps); #define FUNCTIONSCAN_NSLOTS 2 /* * tuple table initialization */ - ExecInitResultTupleSlot(estate, &scanstate->csstate.cstate); - ExecInitScanTupleSlot(estate, &scanstate->csstate); + ExecInitResultTupleSlot(estate, &scanstate->ss.ps); + ExecInitScanTupleSlot(estate, &scanstate->ss); + + /* + * initialize child expressions + */ + scanstate->ss.ps.targetlist = (List *) + ExecInitExpr((Node *) node->scan.plan.targetlist, + (PlanState *) scanstate); + scanstate->ss.ps.qual = (List *) + ExecInitExpr((Node *) node->scan.plan.qual, + (PlanState *) scanstate); /* * get info about function @@ -230,7 +234,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent) elog(ERROR, "Unknown kind of return type specified for function"); scanstate->tupdesc = tupdesc; - ExecSetSlotDescriptor(scanstate->csstate.css_ScanTupleSlot, + ExecSetSlotDescriptor(scanstate->ss.ss_ScanTupleSlot, tupdesc, false); /* @@ -239,15 +243,15 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, Plan *parent) scanstate->tuplestorestate = NULL; scanstate->funcexpr = rte->funcexpr; - scanstate->csstate.cstate.cs_TupFromTlist = false; + scanstate->ss.ps.ps_TupFromTlist = false; /* * initialize tuple type */ - ExecAssignResultTypeFromTL((Plan *) node, &scanstate->csstate.cstate); - ExecAssignProjectionInfo((Plan *) node, &scanstate->csstate.cstate); + ExecAssignResultTypeFromTL(&scanstate->ss.ps); + ExecAssignProjectionInfo(&scanstate->ss.ps); - return TRUE; + return scanstate; } int @@ -265,39 +269,26 @@ ExecCountSlotsFunctionScan(FunctionScan *node) * ---------------------------------------------------------------- */ void -ExecEndFunctionScan(FunctionScan *node) +ExecEndFunctionScan(FunctionScanState *node) { - FunctionScanState *scanstate; - EState *estate; - - /* - * get information from node - */ - scanstate = (FunctionScanState *) node->scan.scanstate; - estate = node->scan.plan.state; - /* * Free the projection info and the scan attribute info - * - * Note: we don't ExecFreeResultType(scanstate) because the rule manager - * depends on the tupType returned by ExecMain(). So for now, this is - * freed at end-transaction time. -cim 6/2/91 */ - ExecFreeProjectionInfo(&scanstate->csstate.cstate); - ExecFreeExprContext(&scanstate->csstate.cstate); + ExecFreeProjectionInfo(&node->ss.ps); + ExecFreeExprContext(&node->ss.ps); /* * clean out the tuple table */ - ExecClearTuple(scanstate->csstate.cstate.cs_ResultTupleSlot); - ExecClearTuple(scanstate->csstate.css_ScanTupleSlot); + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + ExecClearTuple(node->ss.ss_ScanTupleSlot); /* * Release tuplestore resources */ - if (scanstate->tuplestorestate != NULL) - tuplestore_end(scanstate->tuplestorestate); - scanstate->tuplestorestate = NULL; + if (node->tuplestorestate != NULL) + tuplestore_end(node->tuplestorestate); + node->tuplestorestate = NULL; } /* ---------------------------------------------------------------- @@ -307,19 +298,15 @@ ExecEndFunctionScan(FunctionScan *node) * ---------------------------------------------------------------- */ void -ExecFunctionMarkPos(FunctionScan *node) +ExecFunctionMarkPos(FunctionScanState *node) { - FunctionScanState *scanstate; - - scanstate = (FunctionScanState *) node->scan.scanstate; - /* * if we haven't materialized yet, just return. */ - if (!scanstate->tuplestorestate) + if (!node->tuplestorestate) return; - tuplestore_markpos(scanstate->tuplestorestate); + tuplestore_markpos(node->tuplestorestate); } /* ---------------------------------------------------------------- @@ -329,19 +316,15 @@ ExecFunctionMarkPos(FunctionScan *node) * ---------------------------------------------------------------- */ void -ExecFunctionRestrPos(FunctionScan *node) +ExecFunctionRestrPos(FunctionScanState *node) { - FunctionScanState *scanstate; - - scanstate = (FunctionScanState *) node->scan.scanstate; - /* * if we haven't materialized yet, just return. */ - if (!scanstate->tuplestorestate) + if (!node->tuplestorestate) return; - tuplestore_restorepos(scanstate->tuplestorestate); + tuplestore_restorepos(node->tuplestorestate); } /* ---------------------------------------------------------------- @@ -351,21 +334,14 @@ ExecFunctionRestrPos(FunctionScan *node) * ---------------------------------------------------------------- */ void -ExecFunctionReScan(FunctionScan *node, ExprContext *exprCtxt, Plan *parent) +ExecFunctionReScan(FunctionScanState *node, ExprContext *exprCtxt) { - FunctionScanState *scanstate; - - /* - * get information from node - */ - scanstate = (FunctionScanState *) node->scan.scanstate; - - ExecClearTuple(scanstate->csstate.cstate.cs_ResultTupleSlot); + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); /* * If we haven't materialized yet, just return. */ - if (!scanstate->tuplestorestate) + if (!node->tuplestorestate) return; /* @@ -374,13 +350,13 @@ ExecFunctionReScan(FunctionScan *node, ExprContext *exprCtxt, Plan *parent) * whether the function expression contains parameters and/or is * marked volatile. FIXME soon. */ - if (node->scan.plan.chgParam != NULL) + if (node->ss.ps.chgParam != NULL) { - tuplestore_end(scanstate->tuplestorestate); - scanstate->tuplestorestate = NULL; + tuplestore_end(node->tuplestorestate); + node->tuplestorestate = NULL; } else - tuplestore_rescan(scanstate->tuplestorestate); + tuplestore_rescan(node->tuplestorestate); } diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c index d41bcbb6fc..3d562a476b 100644 --- a/src/backend/executor/nodeGroup.c +++ b/src/backend/executor/nodeGroup.c @@ -15,7 +15,7 @@ * locate group boundaries. * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.50 2002/11/29 21:39:11 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.51 2002/12/05 15:50:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -38,12 +38,13 @@ * Return one tuple for each group of matching input tuples. */ TupleTableSlot * -ExecGroup(Group *node) +ExecGroup(GroupState *node) { - GroupState *grpstate; EState *estate; ExprContext *econtext; TupleDesc tupdesc; + int numCols; + AttrNumber *grpColIdx; HeapTuple outerTuple = NULL; HeapTuple firsttuple; TupleTableSlot *outerslot; @@ -53,12 +54,13 @@ ExecGroup(Group *node) /* * get state info from node */ - grpstate = node->grpstate; - if (grpstate->grp_done) + if (node->grp_done) return NULL; - estate = node->plan.state; - econtext = node->grpstate->csstate.cstate.cs_ExprContext; - tupdesc = ExecGetScanType(&grpstate->csstate); + estate = node->ss.ps.state; + econtext = node->ss.ps.ps_ExprContext; + tupdesc = ExecGetScanType(&node->ss); + numCols = ((Group *) node->ss.ps.plan)->numCols; + grpColIdx = ((Group *) node->ss.ps.plan)->grpColIdx; /* * We need not call ResetExprContext here because execTuplesMatch will @@ -67,16 +69,16 @@ ExecGroup(Group *node) /* If we don't already have first tuple of group, fetch it */ /* this should occur on the first call only */ - firsttuple = grpstate->grp_firstTuple; + firsttuple = node->grp_firstTuple; if (firsttuple == NULL) { - outerslot = ExecProcNode(outerPlan(node), (Plan *) node); + outerslot = ExecProcNode(outerPlanState(node)); if (TupIsNull(outerslot)) { - grpstate->grp_done = TRUE; + node->grp_done = TRUE; return NULL; } - grpstate->grp_firstTuple = firsttuple = + node->grp_firstTuple = firsttuple = heap_copytuple(outerslot->val); } @@ -85,10 +87,10 @@ ExecGroup(Group *node) */ for (;;) { - outerslot = ExecProcNode(outerPlan(node), (Plan *) node); + outerslot = ExecProcNode(outerPlanState(node)); if (TupIsNull(outerslot)) { - grpstate->grp_done = TRUE; + node->grp_done = TRUE; outerTuple = NULL; break; } @@ -100,8 +102,8 @@ ExecGroup(Group *node) */ if (!execTuplesMatch(firsttuple, outerTuple, tupdesc, - node->numCols, node->grpColIdx, - grpstate->eqfunctions, + numCols, grpColIdx, + node->eqfunctions, econtext->ecxt_per_tuple_memory)) break; } @@ -111,18 +113,18 @@ ExecGroup(Group *node) * group, and store it in the result tuple slot. */ ExecStoreTuple(firsttuple, - grpstate->csstate.css_ScanTupleSlot, + node->ss.ss_ScanTupleSlot, InvalidBuffer, false); - econtext->ecxt_scantuple = grpstate->csstate.css_ScanTupleSlot; - projInfo = grpstate->csstate.cstate.cs_ProjInfo; + econtext->ecxt_scantuple = node->ss.ss_ScanTupleSlot; + projInfo = node->ss.ps.ps_ProjInfo; resultSlot = ExecProject(projInfo, NULL); /* save first tuple of next group, if we are not done yet */ - if (!grpstate->grp_done) + if (!node->grp_done) { heap_freetuple(firsttuple); - grpstate->grp_firstTuple = heap_copytuple(outerTuple); + node->grp_firstTuple = heap_copytuple(outerTuple); } return resultSlot; @@ -135,65 +137,69 @@ ExecGroup(Group *node) * planner and initializes its outer subtree * ----------------- */ -bool -ExecInitGroup(Group *node, EState *estate, Plan *parent) +GroupState * +ExecInitGroup(Group *node, EState *estate) { GroupState *grpstate; - Plan *outerPlan; - - /* - * assign the node's execution state - */ - node->plan.state = estate; /* * create state structure */ grpstate = makeNode(GroupState); - node->grpstate = grpstate; + grpstate->ss.ps.plan = (Plan *) node; + grpstate->ss.ps.state = estate; grpstate->grp_firstTuple = NULL; grpstate->grp_done = FALSE; /* * create expression context */ - ExecAssignExprContext(estate, &grpstate->csstate.cstate); + ExecAssignExprContext(estate, &grpstate->ss.ps); #define GROUP_NSLOTS 2 /* * tuple table initialization */ - ExecInitScanTupleSlot(estate, &grpstate->csstate); - ExecInitResultTupleSlot(estate, &grpstate->csstate.cstate); + ExecInitScanTupleSlot(estate, &grpstate->ss); + ExecInitResultTupleSlot(estate, &grpstate->ss.ps); + + /* + * initialize child expressions + */ + grpstate->ss.ps.targetlist = (List *) + ExecInitExpr((Node *) node->plan.targetlist, + (PlanState *) grpstate); + grpstate->ss.ps.qual = (List *) + ExecInitExpr((Node *) node->plan.qual, + (PlanState *) grpstate); /* - * initializes child nodes + * initialize child nodes */ - outerPlan = outerPlan(node); - ExecInitNode(outerPlan, estate, (Plan *) node); + outerPlanState(grpstate) = ExecInitNode(outerPlan(node), estate); /* * initialize tuple type. */ - ExecAssignScanTypeFromOuterPlan((Plan *) node, &grpstate->csstate); + ExecAssignScanTypeFromOuterPlan(&grpstate->ss); /* * Initialize tuple type for both result and scan. This node does no * projection */ - ExecAssignResultTypeFromTL((Plan *) node, &grpstate->csstate.cstate); - ExecAssignProjectionInfo((Plan *) node, &grpstate->csstate.cstate); + ExecAssignResultTypeFromTL(&grpstate->ss.ps); + ExecAssignProjectionInfo(&grpstate->ss.ps); /* * Precompute fmgr lookup data for inner loop */ grpstate->eqfunctions = - execTuplesMatchPrepare(ExecGetScanType(&grpstate->csstate), + execTuplesMatchPrepare(ExecGetScanType(&grpstate->ss), node->numCols, node->grpColIdx); - return TRUE; + return grpstate; } int @@ -208,43 +214,38 @@ ExecCountSlotsGroup(Group *node) * ----------------------- */ void -ExecEndGroup(Group *node) +ExecEndGroup(GroupState *node) { - GroupState *grpstate; - Plan *outerPlan; + PlanState *outerPlan; - grpstate = node->grpstate; + ExecFreeProjectionInfo(&node->ss.ps); + ExecFreeExprContext(&node->ss.ps); - ExecFreeProjectionInfo(&grpstate->csstate.cstate); - ExecFreeExprContext(&grpstate->csstate.cstate); - - outerPlan = outerPlan(node); - ExecEndNode(outerPlan, (Plan *) node); + outerPlan = outerPlanState(node); + ExecEndNode(outerPlan); /* clean up tuple table */ - ExecClearTuple(grpstate->csstate.css_ScanTupleSlot); - if (grpstate->grp_firstTuple != NULL) + ExecClearTuple(node->ss.ss_ScanTupleSlot); + if (node->grp_firstTuple != NULL) { - heap_freetuple(grpstate->grp_firstTuple); - grpstate->grp_firstTuple = NULL; + heap_freetuple(node->grp_firstTuple); + node->grp_firstTuple = NULL; } } void -ExecReScanGroup(Group *node, ExprContext *exprCtxt, Plan *parent) +ExecReScanGroup(GroupState *node, ExprContext *exprCtxt) { - GroupState *grpstate = node->grpstate; - - grpstate->grp_done = FALSE; - if (grpstate->grp_firstTuple != NULL) + node->grp_done = FALSE; + if (node->grp_firstTuple != NULL) { - heap_freetuple(grpstate->grp_firstTuple); - grpstate->grp_firstTuple = NULL; + heap_freetuple(node->grp_firstTuple); + node->grp_firstTuple = NULL; } - if (((Plan *) node)->lefttree && - ((Plan *) node)->lefttree->chgParam == NULL) - ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node); + if (((PlanState *) node)->lefttree && + ((PlanState *) node)->lefttree->chgParam == NULL) + ExecReScan(((PlanState *) node)->lefttree, exprCtxt); } /***************************************************************************** diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c index c2c3ab6664..9448ee466a 100644 --- a/src/backend/executor/nodeHash.c +++ b/src/backend/executor/nodeHash.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeHash.c,v 1.68 2002/11/30 00:08:15 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeHash.c,v 1.69 2002/12/05 15:50:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -40,11 +40,10 @@ * ---------------------------------------------------------------- */ TupleTableSlot * -ExecHash(Hash *node) +ExecHash(HashState *node) { EState *estate; - HashState *hashstate; - Plan *outerNode; + PlanState *outerNode; List *hashkeys; HashJoinTable hashtable; TupleTableSlot *slot; @@ -55,12 +54,10 @@ ExecHash(Hash *node) /* * get state info from node */ + estate = node->ps.state; + outerNode = outerPlanState(node); - hashstate = node->hashstate; - estate = node->plan.state; - outerNode = outerPlan(node); - - hashtable = hashstate->hashtable; + hashtable = node->hashtable; if (hashtable == NULL) elog(ERROR, "ExecHash: hash table is NULL."); @@ -79,15 +76,15 @@ ExecHash(Hash *node) /* * set expression context */ - hashkeys = node->hashkeys; - econtext = hashstate->cstate.cs_ExprContext; + hashkeys = ((Hash *) node->ps.plan)->hashkeys; + econtext = node->ps.ps_ExprContext; /* * get all inner tuples and insert into the hash table (or temp files) */ for (;;) { - slot = ExecProcNode(outerNode, (Plan *) node); + slot = ExecProcNode(outerNode); if (TupIsNull(slot)) break; econtext->ecxt_innertuple = slot; @@ -108,24 +105,19 @@ ExecHash(Hash *node) * Init routine for Hash node * ---------------------------------------------------------------- */ -bool -ExecInitHash(Hash *node, EState *estate, Plan *parent) +HashState * +ExecInitHash(Hash *node, EState *estate) { HashState *hashstate; - Plan *outerPlan; SO_printf("ExecInitHash: initializing hash node\n"); /* - * assign the node's execution state - */ - node->plan.state = estate; - - /* * create state structure */ hashstate = makeNode(HashState); - node->hashstate = hashstate; + hashstate->ps.plan = (Plan *) node; + hashstate->ps.state = estate; hashstate->hashtable = NULL; /* @@ -133,29 +125,38 @@ ExecInitHash(Hash *node, EState *estate, Plan *parent) * * create expression context for node */ - ExecAssignExprContext(estate, &hashstate->cstate); + ExecAssignExprContext(estate, &hashstate->ps); #define HASH_NSLOTS 1 /* * initialize our result slot */ - ExecInitResultTupleSlot(estate, &hashstate->cstate); + ExecInitResultTupleSlot(estate, &hashstate->ps); /* - * initializes child nodes + * initialize child expressions */ - outerPlan = outerPlan(node); - ExecInitNode(outerPlan, estate, (Plan *) node); + hashstate->ps.targetlist = (List *) + ExecInitExpr((Node *) node->plan.targetlist, + (PlanState *) hashstate); + hashstate->ps.qual = (List *) + ExecInitExpr((Node *) node->plan.qual, + (PlanState *) hashstate); + + /* + * initialize child nodes + */ + outerPlanState(hashstate) = ExecInitNode(outerPlan(node), estate); /* * initialize tuple type. no need to initialize projection info * because this node doesn't do projections */ - ExecAssignResultTypeFromOuterPlan((Plan *) node, &hashstate->cstate); - hashstate->cstate.cs_ProjInfo = NULL; + ExecAssignResultTypeFromOuterPlan(&hashstate->ps); + hashstate->ps.ps_ProjInfo = NULL; - return TRUE; + return hashstate; } int @@ -173,28 +174,22 @@ ExecCountSlotsHash(Hash *node) * ---------------------------------------------------------------- */ void -ExecEndHash(Hash *node) +ExecEndHash(HashState *node) { - HashState *hashstate; - Plan *outerPlan; - - /* - * get info from the hash state - */ - hashstate = node->hashstate; + PlanState *outerPlan; /* * free projection info. no need to free result type info because * that came from the outer plan... */ - ExecFreeProjectionInfo(&hashstate->cstate); - ExecFreeExprContext(&hashstate->cstate); + ExecFreeProjectionInfo(&node->ps); + ExecFreeExprContext(&node->ps); /* * shut down the subplan */ - outerPlan = outerPlan(node); - ExecEndNode(outerPlan, (Plan *) node); + outerPlan = outerPlanState(node); + ExecEndNode(outerPlan); } @@ -758,12 +753,12 @@ ExecHashTableReset(HashJoinTable hashtable, long ntuples) } void -ExecReScanHash(Hash *node, ExprContext *exprCtxt, Plan *parent) +ExecReScanHash(HashState *node, ExprContext *exprCtxt) { /* * if chgParam of subnode is not null then plan will be re-scanned by * first ExecProcNode. */ - if (((Plan *) node)->lefttree->chgParam == NULL) - ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node); + if (((PlanState *) node)->lefttree->chgParam == NULL) + ExecReScan(((PlanState *) node)->lefttree, exprCtxt); } diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c index 8f0e700ac3..06796c590e 100644 --- a/src/backend/executor/nodeHashjoin.c +++ b/src/backend/executor/nodeHashjoin.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.42 2002/11/30 00:08:15 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.43 2002/12/05 15:50:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -22,8 +22,8 @@ #include "utils/memutils.h" -static TupleTableSlot *ExecHashJoinOuterGetTuple(Plan *node, Plan *parent, - HashJoinState *hjstate); +static TupleTableSlot *ExecHashJoinOuterGetTuple(PlanState *node, + HashJoinState *hjstate); static TupleTableSlot *ExecHashJoinGetSavedTuple(HashJoinState *hjstate, BufFile *file, TupleTableSlot *tupleSlot); @@ -41,12 +41,11 @@ static int ExecHashJoinNewBatch(HashJoinState *hjstate); * ---------------------------------------------------------------- */ TupleTableSlot * /* return: a tuple or NULL */ -ExecHashJoin(HashJoin *node) +ExecHashJoin(HashJoinState *node) { - HashJoinState *hjstate; EState *estate; - Plan *outerNode; - Hash *hashNode; + PlanState *outerNode; + HashState *hashNode; List *hjclauses; List *outerkeys; List *joinqual; @@ -65,37 +64,36 @@ ExecHashJoin(HashJoin *node) /* * get information from HashJoin node */ - hjstate = node->hashjoinstate; hjclauses = node->hashclauses; - estate = node->join.plan.state; - joinqual = node->join.joinqual; - otherqual = node->join.plan.qual; - hashNode = (Hash *) innerPlan(node); - outerNode = outerPlan(node); - hashPhaseDone = hjstate->hj_hashdone; + estate = node->js.ps.state; + joinqual = node->js.joinqual; + otherqual = node->js.ps.qual; + hashNode = (HashState *) innerPlanState(node); + outerNode = outerPlanState(node); + hashPhaseDone = node->hj_hashdone; dir = estate->es_direction; /* * get information from HashJoin state */ - hashtable = hjstate->hj_HashTable; - outerkeys = hjstate->hj_OuterHashKeys; - econtext = hjstate->jstate.cs_ExprContext; + hashtable = node->hj_HashTable; + outerkeys = node->hj_OuterHashKeys; + econtext = node->js.ps.ps_ExprContext; /* * Check to see if we're still projecting out tuples from a previous * join tuple (because there is a function-returning-set in the * projection expressions). If so, try to project another one. */ - if (hjstate->jstate.cs_TupFromTlist) + if (node->js.ps.ps_TupFromTlist) { TupleTableSlot *result; - result = ExecProject(hjstate->jstate.cs_ProjInfo, &isDone); + result = ExecProject(node->js.ps.ps_ProjInfo, &isDone); if (isDone == ExprMultipleResult) return result; /* Done with that source tuple... */ - hjstate->jstate.cs_TupFromTlist = false; + node->js.ps.ps_TupFromTlist = false; } /* @@ -116,16 +114,16 @@ ExecHashJoin(HashJoin *node) /* * create the hash table */ - hashtable = ExecHashTableCreate(hashNode); - hjstate->hj_HashTable = hashtable; + hashtable = ExecHashTableCreate((Hash *) hashNode->ps.plan); + node->hj_HashTable = hashtable; /* * execute the Hash node, to build the hash table */ - hashNode->hashstate->hashtable = hashtable; - innerTupleSlot = ExecProcNode((Plan *) hashNode, (Plan *) node); + hashNode->hashtable = hashtable; + innerTupleSlot = ExecProcNode((PlanState *) hashNode); } - hjstate->hj_hashdone = true; + node->hj_hashdone = true; /* * Open temp files for outer batches, if needed. Note that file @@ -140,40 +138,39 @@ ExecHashJoin(HashJoin *node) /* * Now get an outer tuple and probe into the hash table for matches */ - outerTupleSlot = hjstate->jstate.cs_OuterTupleSlot; + outerTupleSlot = node->js.ps.ps_OuterTupleSlot; for (;;) { /* * If we don't have an outer tuple, get the next one */ - if (hjstate->hj_NeedNewOuter) + if (node->hj_NeedNewOuter) { outerTupleSlot = ExecHashJoinOuterGetTuple(outerNode, - (Plan *) node, - hjstate); + node); if (TupIsNull(outerTupleSlot)) { /* * when the last batch runs out, clean up and exit */ ExecHashTableDestroy(hashtable); - hjstate->hj_HashTable = NULL; + node->hj_HashTable = NULL; return NULL; } - hjstate->jstate.cs_OuterTupleSlot = outerTupleSlot; + node->js.ps.ps_OuterTupleSlot = outerTupleSlot; econtext->ecxt_outertuple = outerTupleSlot; - hjstate->hj_NeedNewOuter = false; - hjstate->hj_MatchedOuter = false; + node->hj_NeedNewOuter = false; + node->hj_MatchedOuter = false; /* * now we have an outer tuple, find the corresponding bucket * for this tuple from the hash table */ - hjstate->hj_CurBucketNo = ExecHashGetBucket(hashtable, econtext, + node->hj_CurBucketNo = ExecHashGetBucket(hashtable, econtext, outerkeys); - hjstate->hj_CurTuple = NULL; + node->hj_CurTuple = NULL; /* * Now we've got an outer tuple and the corresponding hash @@ -182,7 +179,7 @@ ExecHashJoin(HashJoin *node) */ if (hashtable->curbatch == 0) { - int batch = ExecHashJoinGetBatch(hjstate->hj_CurBucketNo, + int batch = ExecHashJoinGetBatch(node->hj_CurBucketNo, hashtable); if (batch > 0) @@ -196,7 +193,7 @@ ExecHashJoin(HashJoin *node) hashtable->outerBatchSize[batchno]++; ExecHashJoinSaveTuple(outerTupleSlot->val, hashtable->outerBatchFile[batchno]); - hjstate->hj_NeedNewOuter = true; + node->hj_NeedNewOuter = true; continue; /* loop around for a new outer tuple */ } } @@ -207,7 +204,7 @@ ExecHashJoin(HashJoin *node) */ for (;;) { - curtuple = ExecScanHashBucket(hjstate, + curtuple = ExecScanHashBucket(node, hjclauses, econtext); if (curtuple == NULL) @@ -217,7 +214,7 @@ ExecHashJoin(HashJoin *node) * we've got a match, but still need to test non-hashed quals */ inntuple = ExecStoreTuple(curtuple, - hjstate->hj_HashTupleSlot, + node->hj_HashTupleSlot, InvalidBuffer, false); /* don't pfree this tuple */ econtext->ecxt_innertuple = inntuple; @@ -235,17 +232,17 @@ ExecHashJoin(HashJoin *node) */ if (ExecQual(joinqual, econtext, false)) { - hjstate->hj_MatchedOuter = true; + node->hj_MatchedOuter = true; if (otherqual == NIL || ExecQual(otherqual, econtext, false)) { TupleTableSlot *result; - result = ExecProject(hjstate->jstate.cs_ProjInfo, &isDone); + result = ExecProject(node->js.ps.ps_ProjInfo, &isDone); if (isDone != ExprEndResult) { - hjstate->jstate.cs_TupFromTlist = + node->js.ps.ps_TupFromTlist = (isDone == ExprMultipleResult); return result; } @@ -258,10 +255,10 @@ ExecHashJoin(HashJoin *node) * whether to emit a dummy outer-join tuple. If not, loop around * to get a new outer tuple. */ - hjstate->hj_NeedNewOuter = true; + node->hj_NeedNewOuter = true; - if (!hjstate->hj_MatchedOuter && - node->join.jointype == JOIN_LEFT) + if (!node->hj_MatchedOuter && + node->js.jointype == JOIN_LEFT) { /* * We are doing an outer join and there were no join matches @@ -269,7 +266,7 @@ ExecHashJoin(HashJoin *node) * nulls for the inner tuple, and return it if it passes the * non-join quals. */ - econtext->ecxt_innertuple = hjstate->hj_NullInnerTupleSlot; + econtext->ecxt_innertuple = node->hj_NullInnerTupleSlot; if (ExecQual(otherqual, econtext, false)) { @@ -280,11 +277,11 @@ ExecHashJoin(HashJoin *node) */ TupleTableSlot *result; - result = ExecProject(hjstate->jstate.cs_ProjInfo, &isDone); + result = ExecProject(node->js.ps.ps_ProjInfo, &isDone); if (isDone != ExprEndResult) { - hjstate->jstate.cs_TupFromTlist = + node->js.ps.ps_TupFromTlist = (isDone == ExprMultipleResult); return result; } @@ -299,8 +296,8 @@ ExecHashJoin(HashJoin *node) * Init routine for HashJoin node. * ---------------------------------------------------------------- */ -bool /* return: initialization status */ -ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent) +HashJoinState * +ExecInitHashJoin(HashJoin *node, EState *estate) { HashJoinState *hjstate; Plan *outerNode; @@ -308,38 +305,51 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent) List *hcl; /* - * assign the node's execution state - */ - node->join.plan.state = estate; - - /* * create state structure */ hjstate = makeNode(HashJoinState); - node->hashjoinstate = hjstate; + hjstate->js.ps.plan = (Plan *) node; + hjstate->js.ps.state = estate; /* * Miscellaneous initialization * * create expression context for node */ - ExecAssignExprContext(estate, &hjstate->jstate); + ExecAssignExprContext(estate, &hjstate->js.ps); + + /* + * initialize child expressions + */ + hjstate->js.ps.targetlist = (List *) + ExecInitExpr((Node *) node->join.plan.targetlist, + (PlanState *) hjstate); + hjstate->js.ps.qual = (List *) + ExecInitExpr((Node *) node->join.plan.qual, + (PlanState *) hjstate); + hjstate->js.jointype = node->join.jointype; + hjstate->js.joinqual = (List *) + ExecInitExpr((Node *) node->join.joinqual, + (PlanState *) hjstate); + hjstate->hashclauses = (List *) + ExecInitExpr((Node *) node->hashclauses, + (PlanState *) hjstate); /* - * initializes child nodes + * initialize child nodes */ - outerNode = outerPlan((Plan *) node); - hashNode = (Hash *) innerPlan((Plan *) node); + outerNode = outerPlan(node); + hashNode = (Hash *) innerPlan(node); - ExecInitNode(outerNode, estate, (Plan *) node); - ExecInitNode((Plan *) hashNode, estate, (Plan *) node); + outerPlanState(hjstate) = ExecInitNode(outerNode, estate); + innerPlanState(hjstate) = ExecInitNode((Plan *) hashNode, estate); #define HASHJOIN_NSLOTS 3 /* * tuple table initialization */ - ExecInitResultTupleSlot(estate, &hjstate->jstate); + ExecInitResultTupleSlot(estate, &hjstate->js.ps); hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate); switch (node->join.jointype) @@ -349,7 +359,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent) case JOIN_LEFT: hjstate->hj_NullInnerTupleSlot = ExecInitNullTupleSlot(estate, - ExecGetTupType((Plan *) hashNode)); + ExecGetTupType(innerPlanState(hjstate))); break; default: elog(ERROR, "ExecInitHashJoin: unsupported join type %d", @@ -364,8 +374,8 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent) * the contents of the hash table. -cim 6/9/91 */ { - HashState *hashstate = hashNode->hashstate; - TupleTableSlot *slot = hashstate->cstate.cs_ResultTupleSlot; + HashState *hashstate = (HashState *) innerPlanState(hjstate); + TupleTableSlot *slot = hashstate->ps.ps_ResultTupleSlot; hjstate->hj_HashTupleSlot = slot; } @@ -373,11 +383,11 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent) /* * initialize tuple type and projection info */ - ExecAssignResultTypeFromTL((Plan *) node, &hjstate->jstate); - ExecAssignProjectionInfo((Plan *) node, &hjstate->jstate); + ExecAssignResultTypeFromTL(&hjstate->js.ps); + ExecAssignProjectionInfo(&hjstate->js.ps); ExecSetSlotDescriptor(hjstate->hj_OuterTupleSlot, - ExecGetTupType(outerNode), + ExecGetTupType(outerPlanState(hjstate)), false); /* @@ -402,12 +412,12 @@ ExecInitHashJoin(HashJoin *node, EState *estate, Plan *parent) get_leftop(lfirst(hcl))); } - hjstate->jstate.cs_OuterTupleSlot = NULL; - hjstate->jstate.cs_TupFromTlist = false; + hjstate->js.ps.ps_OuterTupleSlot = NULL; + hjstate->js.ps.ps_TupFromTlist = false; hjstate->hj_NeedNewOuter = true; hjstate->hj_MatchedOuter = false; - return TRUE; + return hjstate; } int @@ -425,46 +435,35 @@ ExecCountSlotsHashJoin(HashJoin *node) * ---------------------------------------------------------------- */ void -ExecEndHashJoin(HashJoin *node) +ExecEndHashJoin(HashJoinState *node) { - HashJoinState *hjstate; - - /* - * get info from the HashJoin state - */ - hjstate = node->hashjoinstate; - /* * free hash table in case we end plan before all tuples are retrieved */ - if (hjstate->hj_HashTable) + if (node->hj_HashTable) { - ExecHashTableDestroy(hjstate->hj_HashTable); - hjstate->hj_HashTable = NULL; + ExecHashTableDestroy(node->hj_HashTable); + node->hj_HashTable = NULL; } /* * Free the projection info and the scan attribute info - * - * Note: we don't ExecFreeResultType(hjstate) because the rule manager - * depends on the tupType returned by ExecMain(). So for now, this is - * freed at end-transaction time. -cim 6/2/91 */ - ExecFreeProjectionInfo(&hjstate->jstate); - ExecFreeExprContext(&hjstate->jstate); + ExecFreeProjectionInfo(&node->js.ps); + ExecFreeExprContext(&node->js.ps); /* * clean up subtrees */ - ExecEndNode(outerPlan((Plan *) node), (Plan *) node); - ExecEndNode(innerPlan((Plan *) node), (Plan *) node); + ExecEndNode(outerPlanState(node)); + ExecEndNode(innerPlanState(node)); /* * clean out the tuple table */ - ExecClearTuple(hjstate->jstate.cs_ResultTupleSlot); - ExecClearTuple(hjstate->hj_OuterTupleSlot); - ExecClearTuple(hjstate->hj_HashTupleSlot); + ExecClearTuple(node->js.ps.ps_ResultTupleSlot); + ExecClearTuple(node->hj_OuterTupleSlot); + ExecClearTuple(node->hj_HashTupleSlot); } @@ -478,7 +477,7 @@ ExecEndHashJoin(HashJoin *node) */ static TupleTableSlot * -ExecHashJoinOuterGetTuple(Plan *node, Plan *parent, HashJoinState *hjstate) +ExecHashJoinOuterGetTuple(PlanState *node, HashJoinState *hjstate) { HashJoinTable hashtable = hjstate->hj_HashTable; int curbatch = hashtable->curbatch; @@ -486,7 +485,7 @@ ExecHashJoinOuterGetTuple(Plan *node, Plan *parent, HashJoinState *hjstate) if (curbatch == 0) { /* if it is the first pass */ - slot = ExecProcNode(node, parent); + slot = ExecProcNode(node); if (!TupIsNull(slot)) return slot; @@ -611,7 +610,7 @@ ExecHashJoinNewBatch(HashJoinState *hjstate) */ ExecHashTableReset(hashtable, innerBatchSize[newbatch - 1]); - econtext = hjstate->jstate.cs_ExprContext; + econtext = hjstate->js.ps.ps_ExprContext; innerhashkeys = hjstate->hj_InnerHashKeys; while ((slot = ExecHashJoinGetSavedTuple(hjstate, @@ -682,39 +681,37 @@ ExecHashJoinSaveTuple(HeapTuple heapTuple, } void -ExecReScanHashJoin(HashJoin *node, ExprContext *exprCtxt, Plan *parent) +ExecReScanHashJoin(HashJoinState *node, ExprContext *exprCtxt) { - HashJoinState *hjstate = node->hashjoinstate; - - if (!hjstate->hj_hashdone) + if (!node->hj_hashdone) return; - hjstate->hj_hashdone = false; + node->hj_hashdone = false; /* * Unfortunately, currently we have to destroy hashtable in all * cases... */ - if (hjstate->hj_HashTable) + if (node->hj_HashTable) { - ExecHashTableDestroy(hjstate->hj_HashTable); - hjstate->hj_HashTable = NULL; + ExecHashTableDestroy(node->hj_HashTable); + node->hj_HashTable = NULL; } - hjstate->hj_CurBucketNo = 0; - hjstate->hj_CurTuple = (HashJoinTuple) NULL; + node->hj_CurBucketNo = 0; + node->hj_CurTuple = (HashJoinTuple) NULL; - hjstate->jstate.cs_OuterTupleSlot = (TupleTableSlot *) NULL; - hjstate->jstate.cs_TupFromTlist = false; - hjstate->hj_NeedNewOuter = true; - hjstate->hj_MatchedOuter = false; + node->js.ps.ps_OuterTupleSlot = (TupleTableSlot *) NULL; + node->js.ps.ps_TupFromTlist = false; + node->hj_NeedNewOuter = true; + node->hj_MatchedOuter = false; /* * if chgParam of subnodes is not null then plans will be re-scanned * by first ExecProcNode. */ - if (((Plan *) node)->lefttree->chgParam == NULL) - ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node); - if (((Plan *) node)->righttree->chgParam == NULL) - ExecReScan(((Plan *) node)->righttree, exprCtxt, (Plan *) node); + if (((PlanState *) node)->lefttree->chgParam == NULL) + ExecReScan(((PlanState *) node)->lefttree, exprCtxt); + if (((PlanState *) node)->righttree->chgParam == NULL) + ExecReScan(((PlanState *) node)->righttree, exprCtxt); } diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index 78f5ad0ba2..e9888c4d3f 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.71 2002/09/04 20:31:18 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.72 2002/12/05 15:50:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -40,7 +40,7 @@ #define LEFT_OP 1 #define RIGHT_OP 2 -static TupleTableSlot *IndexNext(IndexScan *node); +static TupleTableSlot *IndexNext(IndexScanState *node); /* ---------------------------------------------------------------- * IndexNext @@ -65,15 +65,14 @@ static TupleTableSlot *IndexNext(IndexScan *node); * ---------------------------------------------------------------- */ static TupleTableSlot * -IndexNext(IndexScan *node) +IndexNext(IndexScanState *node) { EState *estate; - CommonScanState *scanstate; - IndexScanState *indexstate; ExprContext *econtext; ScanDirection direction; IndexScanDescPtr scanDescs; IndexScanDesc scandesc; + Index scanrelid; HeapTuple tuple; TupleTableSlot *slot; int numIndices; @@ -83,21 +82,20 @@ IndexNext(IndexScan *node) /* * extract necessary information from index scan node */ - estate = node->scan.plan.state; + estate = node->ss.ps.state; direction = estate->es_direction; - if (ScanDirectionIsBackward(node->indxorderdir)) + if (ScanDirectionIsBackward(((IndexScan *) node->ss.ps.plan)->indxorderdir)) { if (ScanDirectionIsForward(direction)) direction = BackwardScanDirection; else if (ScanDirectionIsBackward(direction)) direction = ForwardScanDirection; } - scanstate = node->scan.scanstate; - indexstate = node->indxstate; - scanDescs = indexstate->iss_ScanDescs; - numIndices = indexstate->iss_NumIndices; - econtext = scanstate->cstate.cs_ExprContext; - slot = scanstate->css_ScanTupleSlot; + scanDescs = node->iss_ScanDescs; + numIndices = node->iss_NumIndices; + econtext = node->ss.ps.ps_ExprContext; + slot = node->ss.ss_ScanTupleSlot; + scanrelid = ((IndexScan *) node->ss.ps.plan)->scan.scanrelid; /* * Check if we are evaluating PlanQual for tuple of this relation. @@ -106,15 +104,15 @@ IndexNext(IndexScan *node) * switching in Init/ReScan plan... */ if (estate->es_evTuple != NULL && - estate->es_evTuple[node->scan.scanrelid - 1] != NULL) + estate->es_evTuple[scanrelid - 1] != NULL) { List *qual; ExecClearTuple(slot); - if (estate->es_evTupleNull[node->scan.scanrelid - 1]) + if (estate->es_evTupleNull[scanrelid - 1]) return slot; /* return empty slot */ - ExecStoreTuple(estate->es_evTuple[node->scan.scanrelid - 1], + ExecStoreTuple(estate->es_evTuple[scanrelid - 1], slot, InvalidBuffer, false); /* Does the tuple meet any of the OR'd indxqual conditions? */ @@ -131,7 +129,7 @@ IndexNext(IndexScan *node) slot->val = NULL; /* Flag for the next call that no more tuples */ - estate->es_evTupleNull[node->scan.scanrelid - 1] = true; + estate->es_evTupleNull[scanrelid - 1] = true; return slot; } @@ -144,24 +142,24 @@ IndexNext(IndexScan *node) bBackward = ScanDirectionIsBackward(direction); if (bBackward) { - indexNumber = numIndices - indexstate->iss_IndexPtr - 1; + indexNumber = numIndices - node->iss_IndexPtr - 1; if (indexNumber < 0) { indexNumber = 0; - indexstate->iss_IndexPtr = numIndices - 1; + node->iss_IndexPtr = numIndices - 1; } } else { - if ((indexNumber = indexstate->iss_IndexPtr) < 0) + if ((indexNumber = node->iss_IndexPtr) < 0) { indexNumber = 0; - indexstate->iss_IndexPtr = 0; + node->iss_IndexPtr = 0; } } while (indexNumber < numIndices) { - scandesc = scanDescs[indexstate->iss_IndexPtr]; + scandesc = scanDescs[node->iss_IndexPtr]; while ((tuple = index_getnext(scandesc, direction)) != NULL) { /* @@ -181,7 +179,7 @@ IndexNext(IndexScan *node) * We do this by passing the tuple through ExecQual and * checking for failure with all previous qualifications. */ - if (indexstate->iss_IndexPtr > 0) + if (node->iss_IndexPtr > 0) { bool prev_matches = false; int prev_index; @@ -191,7 +189,7 @@ IndexNext(IndexScan *node) ResetExprContext(econtext); qual = node->indxqualorig; for (prev_index = 0; - prev_index < indexstate->iss_IndexPtr; + prev_index < node->iss_IndexPtr; prev_index++) { if (ExecQual((List *) lfirst(qual), econtext, false)) @@ -216,9 +214,9 @@ IndexNext(IndexScan *node) { indexNumber++; if (bBackward) - indexstate->iss_IndexPtr--; + node->iss_IndexPtr--; else - indexstate->iss_IndexPtr++; + node->iss_IndexPtr++; } } @@ -251,21 +249,19 @@ IndexNext(IndexScan *node) * ---------------------------------------------------------------- */ TupleTableSlot * -ExecIndexScan(IndexScan *node) +ExecIndexScan(IndexScanState *node) { - IndexScanState *indexstate = node->indxstate; - /* * If we have runtime keys and they've not already been set up, do it * now. */ - if (indexstate->iss_RuntimeKeyInfo && !indexstate->iss_RuntimeKeysReady) - ExecReScan((Plan *) node, NULL, NULL); + if (node->iss_RuntimeKeyInfo && !node->iss_RuntimeKeysReady) + ExecReScan((PlanState *) node, NULL); /* * use IndexNext as access method */ - return ExecScan(&node->scan, (ExecScanAccessMtd) IndexNext); + return ExecScan(&node->ss, (ExecScanAccessMtd) IndexNext); } /* ---------------------------------------------------------------- @@ -280,28 +276,27 @@ ExecIndexScan(IndexScan *node) * ---------------------------------------------------------------- */ void -ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent) +ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt) { EState *estate; - IndexScanState *indexstate; ExprContext *econtext; int numIndices; IndexScanDescPtr scanDescs; ScanKey *scanKeys; int **runtimeKeyInfo; int *numScanKeys; + Index scanrelid; int i; int j; - estate = node->scan.plan.state; - indexstate = node->indxstate; - econtext = indexstate->iss_RuntimeContext; /* context for runtime - * keys */ - numIndices = indexstate->iss_NumIndices; - scanDescs = indexstate->iss_ScanDescs; - scanKeys = indexstate->iss_ScanKeys; - runtimeKeyInfo = indexstate->iss_RuntimeKeyInfo; - numScanKeys = indexstate->iss_NumScanKeys; + estate = node->ss.ps.state; + econtext = node->iss_RuntimeContext; /* context for runtime keys */ + numIndices = node->iss_NumIndices; + scanDescs = node->iss_ScanDescs; + scanKeys = node->iss_ScanKeys; + runtimeKeyInfo = node->iss_RuntimeKeyInfo; + numScanKeys = node->iss_NumScanKeys; + scanrelid = ((IndexScan *) node->ss.ps.plan)->scan.scanrelid; if (econtext) { @@ -315,7 +310,7 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent) ExprContext *stdecontext; econtext->ecxt_outertuple = exprCtxt->ecxt_outertuple; - stdecontext = node->scan.scanstate->cstate.cs_ExprContext; + stdecontext = node->ss.ps.ps_ExprContext; stdecontext->ecxt_outertuple = exprCtxt->ecxt_outertuple; } @@ -392,22 +387,22 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent) } } - indexstate->iss_RuntimeKeysReady = true; + node->iss_RuntimeKeysReady = true; } /* If this is re-scanning of PlanQual ... */ if (estate->es_evTuple != NULL && - estate->es_evTuple[node->scan.scanrelid - 1] != NULL) + estate->es_evTuple[scanrelid - 1] != NULL) { - estate->es_evTupleNull[node->scan.scanrelid - 1] = false; + estate->es_evTupleNull[scanrelid - 1] = false; return; } /* reset index scans */ - if (ScanDirectionIsBackward(node->indxorderdir)) - indexstate->iss_IndexPtr = numIndices; + if (ScanDirectionIsBackward(((IndexScan *) node->ss.ps.plan)->indxorderdir)) + node->iss_IndexPtr = numIndices; else - indexstate->iss_IndexPtr = -1; + node->iss_IndexPtr = -1; for (i = 0; i < numIndices; i++) { @@ -427,13 +422,10 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent) * ---------------------------------------------------------------- */ void -ExecEndIndexScan(IndexScan *node) +ExecEndIndexScan(IndexScanState *node) { - CommonScanState *scanstate; - IndexScanState *indexstate; int **runtimeKeyInfo; ScanKey *scanKeys; - List *indxqual; int *numScanKeys; int numIndices; Relation relation; @@ -441,32 +433,25 @@ ExecEndIndexScan(IndexScan *node) IndexScanDescPtr indexScanDescs; int i; - scanstate = node->scan.scanstate; - indexstate = node->indxstate; - indxqual = node->indxqual; - runtimeKeyInfo = indexstate->iss_RuntimeKeyInfo; + runtimeKeyInfo = node->iss_RuntimeKeyInfo; /* * extract information from the node */ - numIndices = indexstate->iss_NumIndices; - scanKeys = indexstate->iss_ScanKeys; - numScanKeys = indexstate->iss_NumScanKeys; - indexRelationDescs = indexstate->iss_RelationDescs; - indexScanDescs = indexstate->iss_ScanDescs; - relation = scanstate->css_currentRelation; + numIndices = node->iss_NumIndices; + scanKeys = node->iss_ScanKeys; + numScanKeys = node->iss_NumScanKeys; + indexRelationDescs = node->iss_RelationDescs; + indexScanDescs = node->iss_ScanDescs; + relation = node->ss.ss_currentRelation; /* * Free the projection info and the scan attribute info - * - * Note: we don't ExecFreeResultType(scanstate) because the rule manager - * depends on the tupType returned by ExecMain(). So for now, this is - * freed at end-transaction time. -cim 6/2/91 */ - ExecFreeProjectionInfo(&scanstate->cstate); - ExecFreeExprContext(&scanstate->cstate); - if (indexstate->iss_RuntimeContext) - FreeExprContext(indexstate->iss_RuntimeContext); + ExecFreeProjectionInfo(&node->ss.ps); + ExecFreeExprContext(&node->ss.ps); + if (node->iss_RuntimeContext) + FreeExprContext(node->iss_RuntimeContext); /* * close the index relations @@ -514,12 +499,11 @@ ExecEndIndexScan(IndexScan *node) /* * clear out tuple table slots */ - ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot); - ExecClearTuple(scanstate->css_ScanTupleSlot); - pfree(scanstate); - pfree(indexstate->iss_RelationDescs); - pfree(indexstate->iss_ScanDescs); - pfree(indexstate); + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + ExecClearTuple(node->ss.ss_ScanTupleSlot); + pfree(node->iss_RelationDescs); + pfree(node->iss_ScanDescs); + pfree(node); } /* ---------------------------------------------------------------- @@ -531,21 +515,16 @@ ExecEndIndexScan(IndexScan *node) * ---------------------------------------------------------------- */ void -ExecIndexMarkPos(IndexScan *node) +ExecIndexMarkPos(IndexScanState *node) { - IndexScanState *indexstate; IndexScanDescPtr indexScanDescs; IndexScanDesc scanDesc; int indexPtr; - indexstate = node->indxstate; - indexPtr = indexstate->iss_MarkIndexPtr = indexstate->iss_IndexPtr; - indexScanDescs = indexstate->iss_ScanDescs; + indexPtr = node->iss_MarkIndexPtr = node->iss_IndexPtr; + indexScanDescs = node->iss_ScanDescs; scanDesc = indexScanDescs[indexPtr]; -#ifdef NOT_USED - IndexScanMarkPosition(scanDesc); -#endif index_markpos(scanDesc); } @@ -560,21 +539,16 @@ ExecIndexMarkPos(IndexScan *node) * ---------------------------------------------------------------- */ void -ExecIndexRestrPos(IndexScan *node) +ExecIndexRestrPos(IndexScanState *node) { - IndexScanState *indexstate; IndexScanDescPtr indexScanDescs; IndexScanDesc scanDesc; int indexPtr; - indexstate = node->indxstate; - indexPtr = indexstate->iss_IndexPtr = indexstate->iss_MarkIndexPtr; - indexScanDescs = indexstate->iss_ScanDescs; + indexPtr = node->iss_IndexPtr = node->iss_MarkIndexPtr; + indexScanDescs = node->iss_ScanDescs; scanDesc = indexScanDescs[indexPtr]; -#ifdef NOT_USED - IndexScanRestorePosition(scanDesc); -#endif index_restrpos(scanDesc); } @@ -597,11 +571,10 @@ ExecIndexRestrPos(IndexScan *node) * estate: the execution state initialized in InitPlan. * ---------------------------------------------------------------- */ -bool -ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent) +IndexScanState * +ExecInitIndexScan(IndexScan *node, EState *estate) { IndexScanState *indexstate; - CommonScanState *scanstate; List *indxqual; List *indxid; List *listscan; @@ -620,45 +593,52 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent) Relation currentRelation; /* - * assign execution state to node + * create state structure */ - node->scan.plan.state = estate; + indexstate = makeNode(IndexScanState); + indexstate->ss.ps.plan = (Plan *) node; + indexstate->ss.ps.state = estate; /* - * Part 1) initialize scan state + * Miscellaneous initialization * - * create new CommonScanState for node + * create expression context for node */ - scanstate = makeNode(CommonScanState); - node->scan.scanstate = scanstate; + ExecAssignExprContext(estate, &indexstate->ss.ps); /* - * Miscellaneous initialization - * - * create expression context for node + * initialize child expressions */ - ExecAssignExprContext(estate, &scanstate->cstate); + indexstate->ss.ps.targetlist = (List *) + ExecInitExpr((Node *) node->scan.plan.targetlist, + (PlanState *) indexstate); + indexstate->ss.ps.qual = (List *) + ExecInitExpr((Node *) node->scan.plan.qual, + (PlanState *) indexstate); + indexstate->indxqual = (List *) + ExecInitExpr((Node *) node->indxqual, + (PlanState *) indexstate); + indexstate->indxqualorig = (List *) + ExecInitExpr((Node *) node->indxqualorig, + (PlanState *) indexstate); #define INDEXSCAN_NSLOTS 2 /* * tuple table initialization */ - ExecInitResultTupleSlot(estate, &scanstate->cstate); - ExecInitScanTupleSlot(estate, scanstate); + ExecInitResultTupleSlot(estate, &indexstate->ss.ps); + ExecInitScanTupleSlot(estate, &indexstate->ss); /* * initialize projection info. result type comes from scan desc * below.. */ - ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate); + ExecAssignProjectionInfo(&indexstate->ss.ps); /* - * Part 2) initialize index scan state - * - * create new IndexScanState for node + * Initialize index-specific scan state */ - indexstate = makeNode(IndexScanState); indexstate->iss_NumIndices = 0; indexstate->iss_IndexPtr = -1; indexstate->iss_ScanKeys = NULL; @@ -669,8 +649,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent) indexstate->iss_RelationDescs = NULL; indexstate->iss_ScanDescs = NULL; - node->indxstate = indexstate; - /* * get the index node information */ @@ -836,7 +814,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent) { /* treat Param like a constant */ scanvalue = ExecEvalParam((Param *) leftop, - scanstate->cstate.cs_ExprContext, + indexstate->ss.ps.ps_ExprContext, &isnull); if (isnull) flags |= SK_ISNULL; @@ -911,7 +889,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent) { /* treat Param like a constant */ scanvalue = ExecEvalParam((Param *) rightop, - scanstate->cstate.cs_ExprContext, + indexstate->ss.ps.ps_ExprContext, &isnull); if (isnull) flags |= SK_ISNULL; @@ -976,12 +954,12 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent) */ if (have_runtime_keys) { - ExprContext *stdecontext = scanstate->cstate.cs_ExprContext; + ExprContext *stdecontext = indexstate->ss.ps.ps_ExprContext; - ExecAssignExprContext(estate, &scanstate->cstate); + ExecAssignExprContext(estate, &indexstate->ss.ps); indexstate->iss_RuntimeKeyInfo = runtimeKeyInfo; - indexstate->iss_RuntimeContext = scanstate->cstate.cs_ExprContext; - scanstate->cstate.cs_ExprContext = stdecontext; + indexstate->iss_RuntimeContext = indexstate->ss.ps.ps_ExprContext; + indexstate->ss.ps.ps_ExprContext = stdecontext; } else { @@ -1008,14 +986,14 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent) if (!RelationGetForm(currentRelation)->relhasindex) elog(ERROR, "indexes of the relation %u was inactivated", reloid); - scanstate->css_currentRelation = currentRelation; - scanstate->css_currentScanDesc = NULL; /* no heap scan here */ + indexstate->ss.ss_currentRelation = currentRelation; + indexstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */ /* * get the scan type from the relation descriptor. */ - ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false); - ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate); + ExecAssignScanType(&indexstate->ss, RelationGetDescr(currentRelation), false); + ExecAssignResultTypeFromTL(&indexstate->ss.ps); /* * open the index relations and initialize relation and scan @@ -1043,7 +1021,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent) /* * all done. */ - return TRUE; + return indexstate; } int diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c index 4b22b93d57..1ea3aa62b5 100644 --- a/src/backend/executor/nodeLimit.c +++ b/src/backend/executor/nodeLimit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeLimit.c,v 1.11 2002/11/22 22:10:01 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeLimit.c,v 1.12 2002/12/05 15:50:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -24,7 +24,7 @@ #include "executor/executor.h" #include "executor/nodeLimit.h" -static void recompute_limits(Limit *node); +static void recompute_limits(LimitState *node); /* ---------------------------------------------------------------- @@ -35,26 +35,24 @@ static void recompute_limits(Limit *node); * ---------------------------------------------------------------- */ TupleTableSlot * /* return: a tuple or NULL */ -ExecLimit(Limit *node) +ExecLimit(LimitState *node) { - LimitState *limitstate; ScanDirection direction; TupleTableSlot *resultTupleSlot; TupleTableSlot *slot; - Plan *outerPlan; + PlanState *outerPlan; /* * get information from the node */ - limitstate = node->limitstate; - direction = node->plan.state->es_direction; - outerPlan = outerPlan((Plan *) node); - resultTupleSlot = limitstate->cstate.cs_ResultTupleSlot; + direction = node->ps.state->es_direction; + outerPlan = outerPlanState(node); + resultTupleSlot = node->ps.ps_ResultTupleSlot; /* * The main logic is a simple state machine. */ - switch (limitstate->lstate) + switch (node->lstate) { case LIMIT_INITIAL: /* @@ -71,9 +69,9 @@ ExecLimit(Limit *node) /* * Check for empty window; if so, treat like empty subplan. */ - if (limitstate->count <= 0 && !limitstate->noCount) + if (node->count <= 0 && !node->noCount) { - limitstate->lstate = LIMIT_EMPTY; + node->lstate = LIMIT_EMPTY; return NULL; } /* @@ -81,24 +79,24 @@ ExecLimit(Limit *node) */ for (;;) { - slot = ExecProcNode(outerPlan, (Plan *) node); + slot = ExecProcNode(outerPlan); if (TupIsNull(slot)) { /* * The subplan returns too few tuples for us to produce * any output at all. */ - limitstate->lstate = LIMIT_EMPTY; + node->lstate = LIMIT_EMPTY; return NULL; } - limitstate->subSlot = slot; - if (++limitstate->position > limitstate->offset) + node->subSlot = slot; + if (++node->position > node->offset) break; } /* * Okay, we have the first tuple of the window. */ - limitstate->lstate = LIMIT_INWINDOW; + node->lstate = LIMIT_INWINDOW; break; case LIMIT_EMPTY: @@ -117,23 +115,23 @@ ExecLimit(Limit *node) * advancing the subplan or the position variable; but * change the state machine state to record having done so. */ - if (!limitstate->noCount && - limitstate->position >= limitstate->offset + limitstate->count) + if (!node->noCount && + node->position >= node->offset + node->count) { - limitstate->lstate = LIMIT_WINDOWEND; + node->lstate = LIMIT_WINDOWEND; return NULL; } /* * Get next tuple from subplan, if any. */ - slot = ExecProcNode(outerPlan, (Plan *) node); + slot = ExecProcNode(outerPlan); if (TupIsNull(slot)) { - limitstate->lstate = LIMIT_SUBPLANEOF; + node->lstate = LIMIT_SUBPLANEOF; return NULL; } - limitstate->subSlot = slot; - limitstate->position++; + node->subSlot = slot; + node->position++; } else { @@ -141,19 +139,19 @@ ExecLimit(Limit *node) * Backwards scan, so check for stepping off start of window. * As above, change only state-machine status if so. */ - if (limitstate->position <= limitstate->offset + 1) + if (node->position <= node->offset + 1) { - limitstate->lstate = LIMIT_WINDOWSTART; + node->lstate = LIMIT_WINDOWSTART; return NULL; } /* * Get previous tuple from subplan; there should be one! */ - slot = ExecProcNode(outerPlan, (Plan *) node); + slot = ExecProcNode(outerPlan); if (TupIsNull(slot)) elog(ERROR, "ExecLimit: subplan failed to run backwards"); - limitstate->subSlot = slot; - limitstate->position--; + node->subSlot = slot; + node->position--; } break; @@ -164,11 +162,11 @@ ExecLimit(Limit *node) * Backing up from subplan EOF, so re-fetch previous tuple; * there should be one! Note previous tuple must be in window. */ - slot = ExecProcNode(outerPlan, (Plan *) node); + slot = ExecProcNode(outerPlan); if (TupIsNull(slot)) elog(ERROR, "ExecLimit: subplan failed to run backwards"); - limitstate->subSlot = slot; - limitstate->lstate = LIMIT_INWINDOW; + node->subSlot = slot; + node->lstate = LIMIT_INWINDOW; /* position does not change 'cause we didn't advance it before */ break; @@ -179,8 +177,8 @@ ExecLimit(Limit *node) * Backing up from window end: simply re-return the last * tuple fetched from the subplan. */ - slot = limitstate->subSlot; - limitstate->lstate = LIMIT_INWINDOW; + slot = node->subSlot; + node->lstate = LIMIT_INWINDOW; /* position does not change 'cause we didn't advance it before */ break; @@ -191,14 +189,14 @@ ExecLimit(Limit *node) * Advancing after having backed off window start: simply * re-return the last tuple fetched from the subplan. */ - slot = limitstate->subSlot; - limitstate->lstate = LIMIT_INWINDOW; + slot = node->subSlot; + node->lstate = LIMIT_INWINDOW; /* position does not change 'cause we didn't change it before */ break; default: elog(ERROR, "ExecLimit: impossible state %d", - (int) limitstate->lstate); + (int) node->lstate); slot = NULL; /* keep compiler quiet */ break; } @@ -220,55 +218,54 @@ ExecLimit(Limit *node) * This is also a handy place to reset the current-position state info. */ static void -recompute_limits(Limit *node) +recompute_limits(LimitState *node) { - LimitState *limitstate = node->limitstate; - ExprContext *econtext = limitstate->cstate.cs_ExprContext; + ExprContext *econtext = node->ps.ps_ExprContext; bool isNull; if (node->limitOffset) { - limitstate->offset = + node->offset = DatumGetInt32(ExecEvalExprSwitchContext(node->limitOffset, econtext, &isNull, NULL)); /* Interpret NULL offset as no offset */ if (isNull) - limitstate->offset = 0; - else if (limitstate->offset < 0) - limitstate->offset = 0; + node->offset = 0; + else if (node->offset < 0) + node->offset = 0; } else { /* No OFFSET supplied */ - limitstate->offset = 0; + node->offset = 0; } if (node->limitCount) { - limitstate->noCount = false; - limitstate->count = + node->noCount = false; + node->count = DatumGetInt32(ExecEvalExprSwitchContext(node->limitCount, econtext, &isNull, NULL)); /* Interpret NULL count as no count (LIMIT ALL) */ if (isNull) - limitstate->noCount = true; - else if (limitstate->count < 0) - limitstate->count = 0; + node->noCount = true; + else if (node->count < 0) + node->count = 0; } else { /* No COUNT supplied */ - limitstate->count = 0; - limitstate->noCount = true; + node->count = 0; + node->noCount = true; } /* Reset position to start-of-scan */ - limitstate->position = 0; - limitstate->subSlot = NULL; + node->position = 0; + node->subSlot = NULL; } /* ---------------------------------------------------------------- @@ -278,22 +275,19 @@ recompute_limits(Limit *node) * the node's subplan. * ---------------------------------------------------------------- */ -bool /* return: initialization status */ -ExecInitLimit(Limit *node, EState *estate, Plan *parent) +LimitState * +ExecInitLimit(Limit *node, EState *estate) { LimitState *limitstate; Plan *outerPlan; /* - * assign execution state to node - */ - node->plan.state = estate; - - /* - * create new LimitState for node + * create state structure */ limitstate = makeNode(LimitState); - node->limitstate = limitstate; + limitstate->ps.plan = (Plan *) node; + limitstate->ps.state = estate; + limitstate->lstate = LIMIT_INITIAL; /* @@ -302,29 +296,37 @@ ExecInitLimit(Limit *node, EState *estate, Plan *parent) * Limit nodes never call ExecQual or ExecProject, but they need an * exprcontext anyway to evaluate the limit/offset parameters in. */ - ExecAssignExprContext(estate, &limitstate->cstate); + ExecAssignExprContext(estate, &limitstate->ps); + + /* + * initialize child expressions + */ + limitstate->limitOffset = ExecInitExpr(node->limitOffset, + (PlanState *) limitstate); + limitstate->limitCount = ExecInitExpr(node->limitCount, + (PlanState *) limitstate); #define LIMIT_NSLOTS 1 /* * Tuple table initialization */ - ExecInitResultTupleSlot(estate, &limitstate->cstate); + ExecInitResultTupleSlot(estate, &limitstate->ps); /* * then initialize outer plan */ - outerPlan = outerPlan((Plan *) node); - ExecInitNode(outerPlan, estate, (Plan *) node); + outerPlan = outerPlan(node); + outerPlanState(limitstate) = ExecInitNode(outerPlan, estate); /* * limit nodes do no projections, so initialize projection info for * this node appropriately */ - ExecAssignResultTypeFromOuterPlan((Plan *) node, &limitstate->cstate); - limitstate->cstate.cs_ProjInfo = NULL; + ExecAssignResultTypeFromOuterPlan(&limitstate->ps); + limitstate->ps.ps_ProjInfo = NULL; - return TRUE; + return limitstate; } int @@ -343,33 +345,29 @@ ExecCountSlotsLimit(Limit *node) * ---------------------------------------------------------------- */ void -ExecEndLimit(Limit *node) +ExecEndLimit(LimitState *node) { - LimitState *limitstate = node->limitstate; + ExecFreeExprContext(&node->ps); - ExecFreeExprContext(&limitstate->cstate); - - ExecEndNode(outerPlan((Plan *) node), (Plan *) node); + ExecEndNode(outerPlanState(node)); /* clean up tuple table */ - ExecClearTuple(limitstate->cstate.cs_ResultTupleSlot); + ExecClearTuple(node->ps.ps_ResultTupleSlot); } void -ExecReScanLimit(Limit *node, ExprContext *exprCtxt, Plan *parent) +ExecReScanLimit(LimitState *node, ExprContext *exprCtxt) { - LimitState *limitstate = node->limitstate; - /* resetting lstate will force offset/limit recalculation */ - limitstate->lstate = LIMIT_INITIAL; + node->lstate = LIMIT_INITIAL; - ExecClearTuple(limitstate->cstate.cs_ResultTupleSlot); + ExecClearTuple(node->ps.ps_ResultTupleSlot); /* * if chgParam of subnode is not null then plan will be re-scanned by * first ExecProcNode. */ - if (((Plan *) node)->lefttree->chgParam == NULL) - ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node); + if (((PlanState *) node)->lefttree->chgParam == NULL) + ExecReScan(((PlanState *) node)->lefttree, exprCtxt); } diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c index 30eb9a285b..cf7ca89f4a 100644 --- a/src/backend/executor/nodeMaterial.c +++ b/src/backend/executor/nodeMaterial.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeMaterial.c,v 1.38 2002/06/20 20:29:28 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeMaterial.c,v 1.39 2002/12/05 15:50:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -43,10 +43,9 @@ * ---------------------------------------------------------------- */ TupleTableSlot * /* result tuple from subplan */ -ExecMaterial(Material *node) +ExecMaterial(MaterialState *node) { EState *estate; - MaterialState *matstate; ScanDirection dir; Tuplestorestate *tuplestorestate; HeapTuple heapTuple; @@ -56,10 +55,9 @@ ExecMaterial(Material *node) /* * get state info from node */ - matstate = node->matstate; - estate = node->plan.state; + estate = node->ss.ps.state; dir = estate->es_direction; - tuplestorestate = (Tuplestorestate *) matstate->tuplestorestate; + tuplestorestate = (Tuplestorestate *) node->tuplestorestate; /* * If first time through, read all tuples from outer plan and pass @@ -69,7 +67,7 @@ ExecMaterial(Material *node) if (tuplestorestate == NULL) { - Plan *outerNode; + PlanState *outerNode; /* * Want to scan subplan in the forward direction while creating @@ -84,16 +82,16 @@ ExecMaterial(Material *node) tuplestorestate = tuplestore_begin_heap(true, /* randomAccess */ SortMem); - matstate->tuplestorestate = (void *) tuplestorestate; + node->tuplestorestate = (void *) tuplestorestate; /* * Scan the subplan and feed all the tuples to tuplestore. */ - outerNode = outerPlan((Plan *) node); + outerNode = outerPlanState(node); for (;;) { - slot = ExecProcNode(outerNode, (Plan *) node); + slot = ExecProcNode(outerNode); if (TupIsNull(slot)) break; @@ -117,7 +115,7 @@ ExecMaterial(Material *node) * Get the first or next tuple from tuplestore. Returns NULL if no * more tuples. */ - slot = (TupleTableSlot *) matstate->csstate.cstate.cs_ResultTupleSlot; + slot = (TupleTableSlot *) node->ss.ps.ps_ResultTupleSlot; heapTuple = tuplestore_getheaptuple(tuplestorestate, ScanDirectionIsForward(dir), &should_free); @@ -129,23 +127,20 @@ ExecMaterial(Material *node) * ExecInitMaterial * ---------------------------------------------------------------- */ -bool /* initialization status */ -ExecInitMaterial(Material *node, EState *estate, Plan *parent) +MaterialState * +ExecInitMaterial(Material *node, EState *estate) { MaterialState *matstate; Plan *outerPlan; /* - * assign the node's execution state - */ - node->plan.state = estate; - - /* * create state structure */ matstate = makeNode(MaterialState); + matstate->ss.ps.plan = (Plan *) node; + matstate->ss.ps.state = estate; + matstate->tuplestorestate = NULL; - node->matstate = matstate; /* * Miscellaneous initialization @@ -161,24 +156,24 @@ ExecInitMaterial(Material *node, EState *estate, Plan *parent) * * material nodes only return tuples from their materialized relation. */ - ExecInitResultTupleSlot(estate, &matstate->csstate.cstate); - ExecInitScanTupleSlot(estate, &matstate->csstate); + ExecInitResultTupleSlot(estate, &matstate->ss.ps); + ExecInitScanTupleSlot(estate, &matstate->ss); /* * initializes child nodes */ - outerPlan = outerPlan((Plan *) node); - ExecInitNode(outerPlan, estate, (Plan *) node); + outerPlan = outerPlan(node); + outerPlanState(matstate) = ExecInitNode(outerPlan, estate); /* * initialize tuple type. no need to initialize projection info * because this node doesn't do projections. */ - ExecAssignResultTypeFromOuterPlan((Plan *) node, &matstate->csstate.cstate); - ExecAssignScanTypeFromOuterPlan((Plan *) node, &matstate->csstate); - matstate->csstate.cstate.cs_ProjInfo = NULL; + ExecAssignResultTypeFromOuterPlan(&matstate->ss.ps); + ExecAssignScanTypeFromOuterPlan(&matstate->ss); + matstate->ss.ps.ps_ProjInfo = NULL; - return TRUE; + return matstate; } int @@ -194,33 +189,24 @@ ExecCountSlotsMaterial(Material *node) * ---------------------------------------------------------------- */ void -ExecEndMaterial(Material *node) +ExecEndMaterial(MaterialState *node) { - MaterialState *matstate; - Plan *outerPlan; - /* - * get info from the material state + * clean out the tuple table */ - matstate = node->matstate; + ExecClearTuple(node->ss.ss_ScanTupleSlot); /* * shut down the subplan */ - outerPlan = outerPlan((Plan *) node); - ExecEndNode(outerPlan, (Plan *) node); - - /* - * clean out the tuple table - */ - ExecClearTuple(matstate->csstate.css_ScanTupleSlot); + ExecEndNode(outerPlanState(node)); /* * Release tuplestore resources */ - if (matstate->tuplestorestate != NULL) - tuplestore_end((Tuplestorestate *) matstate->tuplestorestate); - matstate->tuplestorestate = NULL; + if (node->tuplestorestate != NULL) + tuplestore_end((Tuplestorestate *) node->tuplestorestate); + node->tuplestorestate = NULL; } /* ---------------------------------------------------------------- @@ -230,17 +216,15 @@ ExecEndMaterial(Material *node) * ---------------------------------------------------------------- */ void -ExecMaterialMarkPos(Material *node) +ExecMaterialMarkPos(MaterialState *node) { - MaterialState *matstate = node->matstate; - /* * if we haven't materialized yet, just return. */ - if (!matstate->tuplestorestate) + if (!node->tuplestorestate) return; - tuplestore_markpos((Tuplestorestate *) matstate->tuplestorestate); + tuplestore_markpos((Tuplestorestate *) node->tuplestorestate); } /* ---------------------------------------------------------------- @@ -250,20 +234,18 @@ ExecMaterialMarkPos(Material *node) * ---------------------------------------------------------------- */ void -ExecMaterialRestrPos(Material *node) +ExecMaterialRestrPos(MaterialState *node) { - MaterialState *matstate = node->matstate; - /* * if we haven't materialized yet, just return. */ - if (!matstate->tuplestorestate) + if (!node->tuplestorestate) return; /* * restore the scan to the previously marked position */ - tuplestore_restorepos((Tuplestorestate *) matstate->tuplestorestate); + tuplestore_restorepos((Tuplestorestate *) node->tuplestorestate); } /* ---------------------------------------------------------------- @@ -273,19 +255,17 @@ ExecMaterialRestrPos(Material *node) * ---------------------------------------------------------------- */ void -ExecMaterialReScan(Material *node, ExprContext *exprCtxt, Plan *parent) +ExecMaterialReScan(MaterialState *node, ExprContext *exprCtxt) { - MaterialState *matstate = node->matstate; - /* * If we haven't materialized yet, just return. If outerplan' chgParam * is not NULL then it will be re-scanned by ExecProcNode, else - no * reason to re-scan it at all. */ - if (!matstate->tuplestorestate) + if (!node->tuplestorestate) return; - ExecClearTuple(matstate->csstate.cstate.cs_ResultTupleSlot); + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); /* * If subnode is to be rescanned then we forget previous stored @@ -293,11 +273,11 @@ ExecMaterialReScan(Material *node, ExprContext *exprCtxt, Plan *parent) * * Otherwise we can just rewind and rescan the stored output. */ - if (((Plan *) node)->lefttree->chgParam != NULL) + if (((PlanState *) node)->lefttree->chgParam != NULL) { - tuplestore_end((Tuplestorestate *) matstate->tuplestorestate); - matstate->tuplestorestate = NULL; + tuplestore_end((Tuplestorestate *) node->tuplestorestate); + node->tuplestorestate = NULL; } else - tuplestore_rescan((Tuplestorestate *) matstate->tuplestorestate); + tuplestore_rescan((Tuplestorestate *) node->tuplestorestate); } diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c index 4237618b0e..171738dd34 100644 --- a/src/backend/executor/nodeMergejoin.c +++ b/src/backend/executor/nodeMergejoin.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.51 2002/09/04 20:31:18 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.52 2002/12/05 15:50:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -340,10 +340,9 @@ ExecMergeTupleDump(MergeJoinState *mergestate) * ---------------------------------------------------------------- */ TupleTableSlot * -ExecMergeJoin(MergeJoin *node) +ExecMergeJoin(MergeJoinState *node) { EState *estate; - MergeJoinState *mergestate; ScanDirection direction; List *innerSkipQual; List *outerSkipQual; @@ -352,9 +351,9 @@ ExecMergeJoin(MergeJoin *node) List *otherqual; bool qualResult; bool compareResult; - Plan *innerPlan; + PlanState *innerPlan; TupleTableSlot *innerTupleSlot; - Plan *outerPlan; + PlanState *outerPlan; TupleTableSlot *outerTupleSlot; ExprContext *econtext; bool doFillOuter; @@ -363,17 +362,16 @@ ExecMergeJoin(MergeJoin *node) /* * get information from node */ - mergestate = node->mergestate; - estate = node->join.plan.state; + estate = node->js.ps.state; direction = estate->es_direction; - innerPlan = innerPlan((Plan *) node); - outerPlan = outerPlan((Plan *) node); - econtext = mergestate->jstate.cs_ExprContext; + innerPlan = innerPlanState(node); + outerPlan = outerPlanState(node); + econtext = node->js.ps.ps_ExprContext; mergeclauses = node->mergeclauses; - joinqual = node->join.joinqual; - otherqual = node->join.plan.qual; + joinqual = node->js.joinqual; + otherqual = node->js.ps.qual; - switch (node->join.jointype) + switch (node->js.jointype) { case JOIN_INNER: doFillOuter = false; @@ -393,7 +391,7 @@ ExecMergeJoin(MergeJoin *node) break; default: elog(ERROR, "ExecMergeJoin: unsupported join type %d", - (int) node->join.jointype); + (int) node->js.jointype); doFillOuter = false; /* keep compiler quiet */ doFillInner = false; break; @@ -401,13 +399,13 @@ ExecMergeJoin(MergeJoin *node) if (ScanDirectionIsForward(direction)) { - outerSkipQual = mergestate->mj_OuterSkipQual; - innerSkipQual = mergestate->mj_InnerSkipQual; + outerSkipQual = node->mj_OuterSkipQual; + innerSkipQual = node->mj_InnerSkipQual; } else { - outerSkipQual = mergestate->mj_InnerSkipQual; - innerSkipQual = mergestate->mj_OuterSkipQual; + outerSkipQual = node->mj_InnerSkipQual; + innerSkipQual = node->mj_OuterSkipQual; } /* @@ -415,16 +413,16 @@ ExecMergeJoin(MergeJoin *node) * join tuple (because there is a function-returning-set in the * projection expressions). If so, try to project another one. */ - if (mergestate->jstate.cs_TupFromTlist) + if (node->js.ps.ps_TupFromTlist) { TupleTableSlot *result; ExprDoneCond isDone; - result = ExecProject(mergestate->jstate.cs_ProjInfo, &isDone); + result = ExecProject(node->js.ps.ps_ProjInfo, &isDone); if (isDone == ExprMultipleResult) return result; /* Done with that source tuple... */ - mergestate->jstate.cs_TupFromTlist = false; + node->js.ps.ps_TupFromTlist = false; } /* @@ -444,9 +442,9 @@ ExecMergeJoin(MergeJoin *node) * Note: The join states are highlighted with 32-* comments for * improved readability. */ - MJ_dump(mergestate); + MJ_dump(node); - switch (mergestate->mj_JoinState) + switch (node->mj_JoinState) { /* * EXEC_MJ_INITIALIZE means that this is the first time @@ -459,8 +457,8 @@ ExecMergeJoin(MergeJoin *node) case EXEC_MJ_INITIALIZE: MJ_printf("ExecMergeJoin: EXEC_MJ_INITIALIZE\n"); - outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node); - mergestate->mj_OuterTupleSlot = outerTupleSlot; + outerTupleSlot = ExecProcNode(outerPlan); + node->mj_OuterTupleSlot = outerTupleSlot; if (TupIsNull(outerTupleSlot)) { MJ_printf("ExecMergeJoin: outer subplan is empty\n"); @@ -471,16 +469,16 @@ ExecMergeJoin(MergeJoin *node) * inner tuples. We set MatchedInner = true to * force the ENDOUTER state to advance inner. */ - mergestate->mj_JoinState = EXEC_MJ_ENDOUTER; - mergestate->mj_MatchedInner = true; + node->mj_JoinState = EXEC_MJ_ENDOUTER; + node->mj_MatchedInner = true; break; } /* Otherwise we're done. */ return NULL; } - innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node); - mergestate->mj_InnerTupleSlot = innerTupleSlot; + innerTupleSlot = ExecProcNode(innerPlan); + node->mj_InnerTupleSlot = innerTupleSlot; if (TupIsNull(innerTupleSlot)) { MJ_printf("ExecMergeJoin: inner subplan is empty\n"); @@ -493,8 +491,8 @@ ExecMergeJoin(MergeJoin *node) * state to emit this tuple before advancing * outer. */ - mergestate->mj_JoinState = EXEC_MJ_ENDINNER; - mergestate->mj_MatchedOuter = false; + node->mj_JoinState = EXEC_MJ_ENDINNER; + node->mj_MatchedOuter = false; break; } /* Otherwise we're done. */ @@ -505,7 +503,7 @@ ExecMergeJoin(MergeJoin *node) * OK, we have the initial tuples. Begin by skipping * unmatched inner tuples. */ - mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_BEGIN; + node->mj_JoinState = EXEC_MJ_SKIPINNER_BEGIN; break; /* @@ -519,9 +517,9 @@ ExecMergeJoin(MergeJoin *node) ExecMarkPos(innerPlan); - MarkInnerTuple(mergestate->mj_InnerTupleSlot, mergestate); + MarkInnerTuple(node->mj_InnerTupleSlot, node); - mergestate->mj_JoinState = EXEC_MJ_JOINTEST; + node->mj_JoinState = EXEC_MJ_JOINTEST; break; /* @@ -538,18 +536,18 @@ ExecMergeJoin(MergeJoin *node) ResetExprContext(econtext); - outerTupleSlot = mergestate->mj_OuterTupleSlot; + outerTupleSlot = node->mj_OuterTupleSlot; econtext->ecxt_outertuple = outerTupleSlot; - innerTupleSlot = mergestate->mj_InnerTupleSlot; + innerTupleSlot = node->mj_InnerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot; qualResult = ExecQual(mergeclauses, econtext, false); MJ_DEBUG_QUAL(mergeclauses, qualResult); if (qualResult) - mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES; + node->mj_JoinState = EXEC_MJ_JOINTUPLES; else - mergestate->mj_JoinState = EXEC_MJ_NEXTOUTER; + node->mj_JoinState = EXEC_MJ_NEXTOUTER; break; /* @@ -560,7 +558,7 @@ ExecMergeJoin(MergeJoin *node) case EXEC_MJ_JOINTUPLES: MJ_printf("ExecMergeJoin: EXEC_MJ_JOINTUPLES\n"); - mergestate->mj_JoinState = EXEC_MJ_NEXTINNER; + node->mj_JoinState = EXEC_MJ_NEXTINNER; /* * Check the extra qual conditions to see if we actually @@ -582,8 +580,8 @@ ExecMergeJoin(MergeJoin *node) if (qualResult) { - mergestate->mj_MatchedOuter = true; - mergestate->mj_MatchedInner = true; + node->mj_MatchedOuter = true; + node->mj_MatchedInner = true; qualResult = (otherqual == NIL || ExecQual(otherqual, econtext, false)); @@ -601,12 +599,12 @@ ExecMergeJoin(MergeJoin *node) MJ_printf("ExecMergeJoin: returning tuple\n"); - result = ExecProject(mergestate->jstate.cs_ProjInfo, + result = ExecProject(node->js.ps.ps_ProjInfo, &isDone); if (isDone != ExprEndResult) { - mergestate->jstate.cs_TupFromTlist = + node->js.ps.ps_TupFromTlist = (isDone == ExprMultipleResult); return result; } @@ -625,20 +623,20 @@ ExecMergeJoin(MergeJoin *node) case EXEC_MJ_NEXTINNER: MJ_printf("ExecMergeJoin: EXEC_MJ_NEXTINNER\n"); - if (doFillInner && !mergestate->mj_MatchedInner) + if (doFillInner && !node->mj_MatchedInner) { /* * Generate a fake join tuple with nulls for the outer * tuple, and return it if it passes the non-join * quals. */ - mergestate->mj_MatchedInner = true; /* do it only once */ + node->mj_MatchedInner = true; /* do it only once */ ResetExprContext(econtext); - outerTupleSlot = mergestate->mj_NullOuterTupleSlot; + outerTupleSlot = node->mj_NullOuterTupleSlot; econtext->ecxt_outertuple = outerTupleSlot; - innerTupleSlot = mergestate->mj_InnerTupleSlot; + innerTupleSlot = node->mj_InnerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot; if (ExecQual(otherqual, econtext, false)) @@ -653,12 +651,12 @@ ExecMergeJoin(MergeJoin *node) MJ_printf("ExecMergeJoin: returning fill tuple\n"); - result = ExecProject(mergestate->jstate.cs_ProjInfo, + result = ExecProject(node->js.ps.ps_ProjInfo, &isDone); if (isDone != ExprEndResult) { - mergestate->jstate.cs_TupFromTlist = + node->js.ps.ps_TupFromTlist = (isDone == ExprMultipleResult); return result; } @@ -668,15 +666,15 @@ ExecMergeJoin(MergeJoin *node) /* * now we get the next inner tuple, if any */ - innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node); - mergestate->mj_InnerTupleSlot = innerTupleSlot; + innerTupleSlot = ExecProcNode(innerPlan); + node->mj_InnerTupleSlot = innerTupleSlot; MJ_DEBUG_PROC_NODE(innerTupleSlot); - mergestate->mj_MatchedInner = false; + node->mj_MatchedInner = false; if (TupIsNull(innerTupleSlot)) - mergestate->mj_JoinState = EXEC_MJ_NEXTOUTER; + node->mj_JoinState = EXEC_MJ_NEXTOUTER; else - mergestate->mj_JoinState = EXEC_MJ_JOINTEST; + node->mj_JoinState = EXEC_MJ_JOINTEST; break; /*------------------------------------------- @@ -701,20 +699,20 @@ ExecMergeJoin(MergeJoin *node) case EXEC_MJ_NEXTOUTER: MJ_printf("ExecMergeJoin: EXEC_MJ_NEXTOUTER\n"); - if (doFillOuter && !mergestate->mj_MatchedOuter) + if (doFillOuter && !node->mj_MatchedOuter) { /* * Generate a fake join tuple with nulls for the inner * tuple, and return it if it passes the non-join * quals. */ - mergestate->mj_MatchedOuter = true; /* do it only once */ + node->mj_MatchedOuter = true; /* do it only once */ ResetExprContext(econtext); - outerTupleSlot = mergestate->mj_OuterTupleSlot; + outerTupleSlot = node->mj_OuterTupleSlot; econtext->ecxt_outertuple = outerTupleSlot; - innerTupleSlot = mergestate->mj_NullInnerTupleSlot; + innerTupleSlot = node->mj_NullInnerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot; if (ExecQual(otherqual, econtext, false)) @@ -729,12 +727,12 @@ ExecMergeJoin(MergeJoin *node) MJ_printf("ExecMergeJoin: returning fill tuple\n"); - result = ExecProject(mergestate->jstate.cs_ProjInfo, + result = ExecProject(node->js.ps.ps_ProjInfo, &isDone); if (isDone != ExprEndResult) { - mergestate->jstate.cs_TupFromTlist = + node->js.ps.ps_TupFromTlist = (isDone == ExprMultipleResult); return result; } @@ -744,10 +742,10 @@ ExecMergeJoin(MergeJoin *node) /* * now we get the next outer tuple, if any */ - outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node); - mergestate->mj_OuterTupleSlot = outerTupleSlot; + outerTupleSlot = ExecProcNode(outerPlan); + node->mj_OuterTupleSlot = outerTupleSlot; MJ_DEBUG_PROC_NODE(outerTupleSlot); - mergestate->mj_MatchedOuter = false; + node->mj_MatchedOuter = false; /* * if the outer tuple is null then we are done with the @@ -756,21 +754,21 @@ ExecMergeJoin(MergeJoin *node) if (TupIsNull(outerTupleSlot)) { MJ_printf("ExecMergeJoin: end of outer subplan\n"); - innerTupleSlot = mergestate->mj_InnerTupleSlot; + innerTupleSlot = node->mj_InnerTupleSlot; if (doFillInner && !TupIsNull(innerTupleSlot)) { /* * Need to emit right-join tuples for remaining * inner tuples. */ - mergestate->mj_JoinState = EXEC_MJ_ENDOUTER; + node->mj_JoinState = EXEC_MJ_ENDOUTER; break; } /* Otherwise we're done. */ return NULL; } - mergestate->mj_JoinState = EXEC_MJ_TESTOUTER; + node->mj_JoinState = EXEC_MJ_TESTOUTER; break; /*-------------------------------------------------------- @@ -816,9 +814,9 @@ ExecMergeJoin(MergeJoin *node) */ ResetExprContext(econtext); - outerTupleSlot = mergestate->mj_OuterTupleSlot; + outerTupleSlot = node->mj_OuterTupleSlot; econtext->ecxt_outertuple = outerTupleSlot; - innerTupleSlot = mergestate->mj_MarkedTupleSlot; + innerTupleSlot = node->mj_MarkedTupleSlot; econtext->ecxt_innertuple = innerTupleSlot; qualResult = ExecQual(mergeclauses, econtext, false); @@ -843,7 +841,7 @@ ExecMergeJoin(MergeJoin *node) * the extra joinquals. */ ExecRestrPos(innerPlan); - mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES; + node->mj_JoinState = EXEC_MJ_JOINTUPLES; } else { @@ -862,7 +860,7 @@ ExecMergeJoin(MergeJoin *node) * larger than our marked inner tuples. So we're done. * ---------------- */ - innerTupleSlot = mergestate->mj_InnerTupleSlot; + innerTupleSlot = node->mj_InnerTupleSlot; if (TupIsNull(innerTupleSlot)) { if (doFillOuter) @@ -871,7 +869,7 @@ ExecMergeJoin(MergeJoin *node) * Need to emit left-join tuples for remaining * outer tuples. */ - mergestate->mj_JoinState = EXEC_MJ_ENDINNER; + node->mj_JoinState = EXEC_MJ_ENDINNER; break; } /* Otherwise we're done. */ @@ -879,7 +877,7 @@ ExecMergeJoin(MergeJoin *node) } /* continue on to skip outer tuples */ - mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER_BEGIN; + node->mj_JoinState = EXEC_MJ_SKIPOUTER_BEGIN; } break; @@ -913,9 +911,9 @@ ExecMergeJoin(MergeJoin *node) */ ResetExprContext(econtext); - outerTupleSlot = mergestate->mj_OuterTupleSlot; + outerTupleSlot = node->mj_OuterTupleSlot; econtext->ecxt_outertuple = outerTupleSlot; - innerTupleSlot = mergestate->mj_InnerTupleSlot; + innerTupleSlot = node->mj_InnerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot; qualResult = ExecQual(mergeclauses, econtext, false); @@ -925,13 +923,13 @@ ExecMergeJoin(MergeJoin *node) { ExecMarkPos(innerPlan); - MarkInnerTuple(innerTupleSlot, mergestate); + MarkInnerTuple(innerTupleSlot, node); - mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES; + node->mj_JoinState = EXEC_MJ_JOINTUPLES; break; } - mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER_TEST; + node->mj_JoinState = EXEC_MJ_SKIPOUTER_TEST; break; case EXEC_MJ_SKIPOUTER_TEST: @@ -940,9 +938,9 @@ ExecMergeJoin(MergeJoin *node) /* * ok, now test the skip qualification */ - outerTupleSlot = mergestate->mj_OuterTupleSlot; + outerTupleSlot = node->mj_OuterTupleSlot; econtext->ecxt_outertuple = outerTupleSlot; - innerTupleSlot = mergestate->mj_InnerTupleSlot; + innerTupleSlot = node->mj_InnerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot; compareResult = MergeCompare(mergeclauses, @@ -957,7 +955,7 @@ ExecMergeJoin(MergeJoin *node) */ if (compareResult) { - mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER_ADVANCE; + node->mj_JoinState = EXEC_MJ_SKIPOUTER_ADVANCE; break; } @@ -973,9 +971,9 @@ ExecMergeJoin(MergeJoin *node) MJ_DEBUG_MERGE_COMPARE(innerSkipQual, compareResult); if (compareResult) - mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_BEGIN; + node->mj_JoinState = EXEC_MJ_SKIPINNER_BEGIN; else - mergestate->mj_JoinState = EXEC_MJ_JOINMARK; + node->mj_JoinState = EXEC_MJ_JOINMARK; break; /* @@ -985,20 +983,20 @@ ExecMergeJoin(MergeJoin *node) case EXEC_MJ_SKIPOUTER_ADVANCE: MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPOUTER_ADVANCE\n"); - if (doFillOuter && !mergestate->mj_MatchedOuter) + if (doFillOuter && !node->mj_MatchedOuter) { /* * Generate a fake join tuple with nulls for the inner * tuple, and return it if it passes the non-join * quals. */ - mergestate->mj_MatchedOuter = true; /* do it only once */ + node->mj_MatchedOuter = true; /* do it only once */ ResetExprContext(econtext); - outerTupleSlot = mergestate->mj_OuterTupleSlot; + outerTupleSlot = node->mj_OuterTupleSlot; econtext->ecxt_outertuple = outerTupleSlot; - innerTupleSlot = mergestate->mj_NullInnerTupleSlot; + innerTupleSlot = node->mj_NullInnerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot; if (ExecQual(otherqual, econtext, false)) @@ -1013,12 +1011,12 @@ ExecMergeJoin(MergeJoin *node) MJ_printf("ExecMergeJoin: returning fill tuple\n"); - result = ExecProject(mergestate->jstate.cs_ProjInfo, + result = ExecProject(node->js.ps.ps_ProjInfo, &isDone); if (isDone != ExprEndResult) { - mergestate->jstate.cs_TupFromTlist = + node->js.ps.ps_TupFromTlist = (isDone == ExprMultipleResult); return result; } @@ -1028,10 +1026,10 @@ ExecMergeJoin(MergeJoin *node) /* * now we get the next outer tuple, if any */ - outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node); - mergestate->mj_OuterTupleSlot = outerTupleSlot; + outerTupleSlot = ExecProcNode(outerPlan); + node->mj_OuterTupleSlot = outerTupleSlot; MJ_DEBUG_PROC_NODE(outerTupleSlot); - mergestate->mj_MatchedOuter = false; + node->mj_MatchedOuter = false; /* * if the outer tuple is null then we are done with the @@ -1040,14 +1038,14 @@ ExecMergeJoin(MergeJoin *node) if (TupIsNull(outerTupleSlot)) { MJ_printf("ExecMergeJoin: end of outer subplan\n"); - innerTupleSlot = mergestate->mj_InnerTupleSlot; + innerTupleSlot = node->mj_InnerTupleSlot; if (doFillInner && !TupIsNull(innerTupleSlot)) { /* * Need to emit right-join tuples for remaining * inner tuples. */ - mergestate->mj_JoinState = EXEC_MJ_ENDOUTER; + node->mj_JoinState = EXEC_MJ_ENDOUTER; break; } /* Otherwise we're done. */ @@ -1057,7 +1055,7 @@ ExecMergeJoin(MergeJoin *node) /* * otherwise test the new tuple against the skip qual. */ - mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER_TEST; + node->mj_JoinState = EXEC_MJ_SKIPOUTER_TEST; break; /*----------------------------------------------------------- @@ -1090,9 +1088,9 @@ ExecMergeJoin(MergeJoin *node) */ ResetExprContext(econtext); - outerTupleSlot = mergestate->mj_OuterTupleSlot; + outerTupleSlot = node->mj_OuterTupleSlot; econtext->ecxt_outertuple = outerTupleSlot; - innerTupleSlot = mergestate->mj_InnerTupleSlot; + innerTupleSlot = node->mj_InnerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot; qualResult = ExecQual(mergeclauses, econtext, false); @@ -1102,13 +1100,13 @@ ExecMergeJoin(MergeJoin *node) { ExecMarkPos(innerPlan); - MarkInnerTuple(innerTupleSlot, mergestate); + MarkInnerTuple(innerTupleSlot, node); - mergestate->mj_JoinState = EXEC_MJ_JOINTUPLES; + node->mj_JoinState = EXEC_MJ_JOINTUPLES; break; } - mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_TEST; + node->mj_JoinState = EXEC_MJ_SKIPINNER_TEST; break; case EXEC_MJ_SKIPINNER_TEST: @@ -1117,9 +1115,9 @@ ExecMergeJoin(MergeJoin *node) /* * ok, now test the skip qualification */ - outerTupleSlot = mergestate->mj_OuterTupleSlot; + outerTupleSlot = node->mj_OuterTupleSlot; econtext->ecxt_outertuple = outerTupleSlot; - innerTupleSlot = mergestate->mj_InnerTupleSlot; + innerTupleSlot = node->mj_InnerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot; compareResult = MergeCompare(mergeclauses, @@ -1134,7 +1132,7 @@ ExecMergeJoin(MergeJoin *node) */ if (compareResult) { - mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_ADVANCE; + node->mj_JoinState = EXEC_MJ_SKIPINNER_ADVANCE; break; } @@ -1150,9 +1148,9 @@ ExecMergeJoin(MergeJoin *node) MJ_DEBUG_MERGE_COMPARE(outerSkipQual, compareResult); if (compareResult) - mergestate->mj_JoinState = EXEC_MJ_SKIPOUTER_BEGIN; + node->mj_JoinState = EXEC_MJ_SKIPOUTER_BEGIN; else - mergestate->mj_JoinState = EXEC_MJ_JOINMARK; + node->mj_JoinState = EXEC_MJ_JOINMARK; break; /* @@ -1162,20 +1160,20 @@ ExecMergeJoin(MergeJoin *node) case EXEC_MJ_SKIPINNER_ADVANCE: MJ_printf("ExecMergeJoin: EXEC_MJ_SKIPINNER_ADVANCE\n"); - if (doFillInner && !mergestate->mj_MatchedInner) + if (doFillInner && !node->mj_MatchedInner) { /* * Generate a fake join tuple with nulls for the outer * tuple, and return it if it passes the non-join * quals. */ - mergestate->mj_MatchedInner = true; /* do it only once */ + node->mj_MatchedInner = true; /* do it only once */ ResetExprContext(econtext); - outerTupleSlot = mergestate->mj_NullOuterTupleSlot; + outerTupleSlot = node->mj_NullOuterTupleSlot; econtext->ecxt_outertuple = outerTupleSlot; - innerTupleSlot = mergestate->mj_InnerTupleSlot; + innerTupleSlot = node->mj_InnerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot; if (ExecQual(otherqual, econtext, false)) @@ -1190,12 +1188,12 @@ ExecMergeJoin(MergeJoin *node) MJ_printf("ExecMergeJoin: returning fill tuple\n"); - result = ExecProject(mergestate->jstate.cs_ProjInfo, + result = ExecProject(node->js.ps.ps_ProjInfo, &isDone); if (isDone != ExprEndResult) { - mergestate->jstate.cs_TupFromTlist = + node->js.ps.ps_TupFromTlist = (isDone == ExprMultipleResult); return result; } @@ -1205,10 +1203,10 @@ ExecMergeJoin(MergeJoin *node) /* * now we get the next inner tuple, if any */ - innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node); - mergestate->mj_InnerTupleSlot = innerTupleSlot; + innerTupleSlot = ExecProcNode(innerPlan); + node->mj_InnerTupleSlot = innerTupleSlot; MJ_DEBUG_PROC_NODE(innerTupleSlot); - mergestate->mj_MatchedInner = false; + node->mj_MatchedInner = false; /* * if the inner tuple is null then we are done with the @@ -1217,14 +1215,14 @@ ExecMergeJoin(MergeJoin *node) if (TupIsNull(innerTupleSlot)) { MJ_printf("ExecMergeJoin: end of inner subplan\n"); - outerTupleSlot = mergestate->mj_OuterTupleSlot; + outerTupleSlot = node->mj_OuterTupleSlot; if (doFillOuter && !TupIsNull(outerTupleSlot)) { /* * Need to emit left-join tuples for remaining * outer tuples. */ - mergestate->mj_JoinState = EXEC_MJ_ENDINNER; + node->mj_JoinState = EXEC_MJ_ENDINNER; break; } /* Otherwise we're done. */ @@ -1234,7 +1232,7 @@ ExecMergeJoin(MergeJoin *node) /* * otherwise test the new tuple against the skip qual. */ - mergestate->mj_JoinState = EXEC_MJ_SKIPINNER_TEST; + node->mj_JoinState = EXEC_MJ_SKIPINNER_TEST; break; /* @@ -1247,20 +1245,20 @@ ExecMergeJoin(MergeJoin *node) Assert(doFillInner); - if (!mergestate->mj_MatchedInner) + if (!node->mj_MatchedInner) { /* * Generate a fake join tuple with nulls for the outer * tuple, and return it if it passes the non-join * quals. */ - mergestate->mj_MatchedInner = true; /* do it only once */ + node->mj_MatchedInner = true; /* do it only once */ ResetExprContext(econtext); - outerTupleSlot = mergestate->mj_NullOuterTupleSlot; + outerTupleSlot = node->mj_NullOuterTupleSlot; econtext->ecxt_outertuple = outerTupleSlot; - innerTupleSlot = mergestate->mj_InnerTupleSlot; + innerTupleSlot = node->mj_InnerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot; if (ExecQual(otherqual, econtext, false)) @@ -1275,12 +1273,12 @@ ExecMergeJoin(MergeJoin *node) MJ_printf("ExecMergeJoin: returning fill tuple\n"); - result = ExecProject(mergestate->jstate.cs_ProjInfo, + result = ExecProject(node->js.ps.ps_ProjInfo, &isDone); if (isDone != ExprEndResult) { - mergestate->jstate.cs_TupFromTlist = + node->js.ps.ps_TupFromTlist = (isDone == ExprMultipleResult); return result; } @@ -1290,10 +1288,10 @@ ExecMergeJoin(MergeJoin *node) /* * now we get the next inner tuple, if any */ - innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node); - mergestate->mj_InnerTupleSlot = innerTupleSlot; + innerTupleSlot = ExecProcNode(innerPlan); + node->mj_InnerTupleSlot = innerTupleSlot; MJ_DEBUG_PROC_NODE(innerTupleSlot); - mergestate->mj_MatchedInner = false; + node->mj_MatchedInner = false; if (TupIsNull(innerTupleSlot)) { @@ -1314,20 +1312,20 @@ ExecMergeJoin(MergeJoin *node) Assert(doFillOuter); - if (!mergestate->mj_MatchedOuter) + if (!node->mj_MatchedOuter) { /* * Generate a fake join tuple with nulls for the inner * tuple, and return it if it passes the non-join * quals. */ - mergestate->mj_MatchedOuter = true; /* do it only once */ + node->mj_MatchedOuter = true; /* do it only once */ ResetExprContext(econtext); - outerTupleSlot = mergestate->mj_OuterTupleSlot; + outerTupleSlot = node->mj_OuterTupleSlot; econtext->ecxt_outertuple = outerTupleSlot; - innerTupleSlot = mergestate->mj_NullInnerTupleSlot; + innerTupleSlot = node->mj_NullInnerTupleSlot; econtext->ecxt_innertuple = innerTupleSlot; if (ExecQual(otherqual, econtext, false)) @@ -1342,12 +1340,12 @@ ExecMergeJoin(MergeJoin *node) MJ_printf("ExecMergeJoin: returning fill tuple\n"); - result = ExecProject(mergestate->jstate.cs_ProjInfo, + result = ExecProject(node->js.ps.ps_ProjInfo, &isDone); if (isDone != ExprEndResult) { - mergestate->jstate.cs_TupFromTlist = + node->js.ps.ps_TupFromTlist = (isDone == ExprMultipleResult); return result; } @@ -1357,10 +1355,10 @@ ExecMergeJoin(MergeJoin *node) /* * now we get the next outer tuple, if any */ - outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node); - mergestate->mj_OuterTupleSlot = outerTupleSlot; + outerTupleSlot = ExecProcNode(outerPlan); + node->mj_OuterTupleSlot = outerTupleSlot; MJ_DEBUG_PROC_NODE(outerTupleSlot); - mergestate->mj_MatchedOuter = false; + node->mj_MatchedOuter = false; if (TupIsNull(outerTupleSlot)) { @@ -1377,7 +1375,7 @@ ExecMergeJoin(MergeJoin *node) */ default: elog(WARNING, "ExecMergeJoin: invalid join state %d, aborting", - mergestate->mj_JoinState); + node->mj_JoinState); return NULL; } } @@ -1385,14 +1383,10 @@ ExecMergeJoin(MergeJoin *node) /* ---------------------------------------------------------------- * ExecInitMergeJoin - * - * old comments - * Creates the run-time state information for the node and - * sets the relation id to contain relevant decriptors. * ---------------------------------------------------------------- */ -bool -ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent) +MergeJoinState * +ExecInitMergeJoin(MergeJoin *node, EState *estate) { MergeJoinState *mergestate; @@ -1400,40 +1394,52 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent) "initializing node"); /* - * assign the node's execution state and get the range table and - * direction from it - */ - node->join.plan.state = estate; - - /* - * create new merge state for node + * create state structure */ mergestate = makeNode(MergeJoinState); - node->mergestate = mergestate; + mergestate->js.ps.plan = (Plan *) node; + mergestate->js.ps.state = estate; /* * Miscellaneous initialization * * create expression context for node */ - ExecAssignExprContext(estate, &mergestate->jstate); + ExecAssignExprContext(estate, &mergestate->js.ps); + + /* + * initialize child expressions + */ + mergestate->js.ps.targetlist = (List *) + ExecInitExpr((Node *) node->join.plan.targetlist, + (PlanState *) mergestate); + mergestate->js.ps.qual = (List *) + ExecInitExpr((Node *) node->join.plan.qual, + (PlanState *) mergestate); + mergestate->js.jointype = node->join.jointype; + mergestate->js.joinqual = (List *) + ExecInitExpr((Node *) node->join.joinqual, + (PlanState *) mergestate); + mergestate->mergeclauses = (List *) + ExecInitExpr((Node *) node->mergeclauses, + (PlanState *) mergestate); /* - * initialize subplans + * initialize child nodes */ - ExecInitNode(outerPlan((Plan *) node), estate, (Plan *) node); - ExecInitNode(innerPlan((Plan *) node), estate, (Plan *) node); + outerPlanState(mergestate) = ExecInitNode(outerPlan(node), estate); + innerPlanState(mergestate) = ExecInitNode(innerPlan(node), estate); #define MERGEJOIN_NSLOTS 4 /* * tuple table initialization */ - ExecInitResultTupleSlot(estate, &mergestate->jstate); + ExecInitResultTupleSlot(estate, &mergestate->js.ps); mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate); ExecSetSlotDescriptor(mergestate->mj_MarkedTupleSlot, - ExecGetTupType(innerPlan((Plan *) node)), + ExecGetTupType(innerPlanState(mergestate)), false); switch (node->join.jointype) @@ -1443,12 +1449,12 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent) case JOIN_LEFT: mergestate->mj_NullInnerTupleSlot = ExecInitNullTupleSlot(estate, - ExecGetTupType(innerPlan((Plan *) node))); + ExecGetTupType(innerPlanState(mergestate))); break; case JOIN_RIGHT: mergestate->mj_NullOuterTupleSlot = ExecInitNullTupleSlot(estate, - ExecGetTupType(outerPlan((Plan *) node))); + ExecGetTupType(outerPlanState(mergestate))); /* * Can't handle right or full join with non-nil extra @@ -1460,10 +1466,10 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent) case JOIN_FULL: mergestate->mj_NullOuterTupleSlot = ExecInitNullTupleSlot(estate, - ExecGetTupType(outerPlan((Plan *) node))); + ExecGetTupType(outerPlanState(mergestate))); mergestate->mj_NullInnerTupleSlot = ExecInitNullTupleSlot(estate, - ExecGetTupType(innerPlan((Plan *) node))); + ExecGetTupType(innerPlanState(mergestate))); /* * Can't handle right or full join with non-nil extra @@ -1480,8 +1486,8 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent) /* * initialize tuple type and projection info */ - ExecAssignResultTypeFromTL((Plan *) node, &mergestate->jstate); - ExecAssignProjectionInfo((Plan *) node, &mergestate->jstate); + ExecAssignResultTypeFromTL(&mergestate->js.ps); + ExecAssignProjectionInfo(&mergestate->js.ps); /* * form merge skip qualifications @@ -1500,7 +1506,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent) * initialize join state */ mergestate->mj_JoinState = EXEC_MJ_INITIALIZE; - mergestate->jstate.cs_TupFromTlist = false; + mergestate->js.ps.ps_TupFromTlist = false; mergestate->mj_MatchedOuter = false; mergestate->mj_MatchedInner = false; mergestate->mj_OuterTupleSlot = NULL; @@ -1512,7 +1518,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent) MJ1_printf("ExecInitMergeJoin: %s\n", "node initialized"); - return TRUE; + return mergestate; } int @@ -1531,65 +1537,52 @@ ExecCountSlotsMergeJoin(MergeJoin *node) * ---------------------------------------------------------------- */ void -ExecEndMergeJoin(MergeJoin *node) +ExecEndMergeJoin(MergeJoinState *node) { - MergeJoinState *mergestate; - MJ1_printf("ExecEndMergeJoin: %s\n", "ending node processing"); /* - * get state information from the node - */ - mergestate = node->mergestate; - - /* * Free the projection info and the scan attribute info - * - * Note: we don't ExecFreeResultType(mergestate) because the rule manager - * depends on the tupType returned by ExecMain(). So for now, this is - * freed at end-transaction time. -cim 6/2/91 */ - ExecFreeProjectionInfo(&mergestate->jstate); - ExecFreeExprContext(&mergestate->jstate); + ExecFreeProjectionInfo(&node->js.ps); + ExecFreeExprContext(&node->js.ps); /* * shut down the subplans */ - ExecEndNode((Plan *) innerPlan((Plan *) node), (Plan *) node); - ExecEndNode((Plan *) outerPlan((Plan *) node), (Plan *) node); + ExecEndNode(innerPlanState(node)); + ExecEndNode(outerPlanState(node)); /* * clean out the tuple table */ - ExecClearTuple(mergestate->jstate.cs_ResultTupleSlot); - ExecClearTuple(mergestate->mj_MarkedTupleSlot); + ExecClearTuple(node->js.ps.ps_ResultTupleSlot); + ExecClearTuple(node->mj_MarkedTupleSlot); MJ1_printf("ExecEndMergeJoin: %s\n", "node processing ended"); } void -ExecReScanMergeJoin(MergeJoin *node, ExprContext *exprCtxt, Plan *parent) +ExecReScanMergeJoin(MergeJoinState *node, ExprContext *exprCtxt) { - MergeJoinState *mergestate = node->mergestate; - - ExecClearTuple(mergestate->mj_MarkedTupleSlot); + ExecClearTuple(node->mj_MarkedTupleSlot); - mergestate->mj_JoinState = EXEC_MJ_INITIALIZE; - mergestate->jstate.cs_TupFromTlist = false; - mergestate->mj_MatchedOuter = false; - mergestate->mj_MatchedInner = false; - mergestate->mj_OuterTupleSlot = NULL; - mergestate->mj_InnerTupleSlot = NULL; + node->mj_JoinState = EXEC_MJ_INITIALIZE; + node->js.ps.ps_TupFromTlist = false; + node->mj_MatchedOuter = false; + node->mj_MatchedInner = false; + node->mj_OuterTupleSlot = NULL; + node->mj_InnerTupleSlot = NULL; /* * if chgParam of subnodes is not null then plans will be re-scanned * by first ExecProcNode. */ - if (((Plan *) node)->lefttree->chgParam == NULL) - ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node); - if (((Plan *) node)->righttree->chgParam == NULL) - ExecReScan(((Plan *) node)->righttree, exprCtxt, (Plan *) node); + if (((PlanState *) node)->lefttree->chgParam == NULL) + ExecReScan(((PlanState *) node)->lefttree, exprCtxt); + if (((PlanState *) node)->righttree->chgParam == NULL) + ExecReScan(((PlanState *) node)->righttree, exprCtxt); } diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c index 2bd26938fc..ae2061aa96 100644 --- a/src/backend/executor/nodeNestloop.c +++ b/src/backend/executor/nodeNestloop.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeNestloop.c,v 1.26 2002/06/20 20:29:28 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeNestloop.c,v 1.27 2002/12/05 15:50:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -57,11 +57,10 @@ * ---------------------------------------------------------------- */ TupleTableSlot * -ExecNestLoop(NestLoop *node) +ExecNestLoop(NestLoopState *node) { - NestLoopState *nlstate; - Plan *innerPlan; - Plan *outerPlan; + PlanState *innerPlan; + PlanState *outerPlan; TupleTableSlot *outerTupleSlot; TupleTableSlot *innerTupleSlot; List *joinqual; @@ -73,17 +72,16 @@ ExecNestLoop(NestLoop *node) */ ENL1_printf("getting info from node"); - nlstate = node->nlstate; - joinqual = node->join.joinqual; - otherqual = node->join.plan.qual; - outerPlan = outerPlan((Plan *) node); - innerPlan = innerPlan((Plan *) node); - econtext = nlstate->jstate.cs_ExprContext; + joinqual = node->js.joinqual; + otherqual = node->js.ps.qual; + outerPlan = outerPlanState(node); + innerPlan = innerPlanState(node); + econtext = node->js.ps.ps_ExprContext; /* * get the current outer tuple */ - outerTupleSlot = nlstate->jstate.cs_OuterTupleSlot; + outerTupleSlot = node->js.ps.ps_OuterTupleSlot; econtext->ecxt_outertuple = outerTupleSlot; /* @@ -91,16 +89,16 @@ ExecNestLoop(NestLoop *node) * join tuple (because there is a function-returning-set in the * projection expressions). If so, try to project another one. */ - if (nlstate->jstate.cs_TupFromTlist) + if (node->js.ps.ps_TupFromTlist) { TupleTableSlot *result; ExprDoneCond isDone; - result = ExecProject(nlstate->jstate.cs_ProjInfo, &isDone); + result = ExecProject(node->js.ps.ps_ProjInfo, &isDone); if (isDone == ExprMultipleResult) return result; /* Done with that source tuple... */ - nlstate->jstate.cs_TupFromTlist = false; + node->js.ps.ps_TupFromTlist = false; } /* @@ -122,10 +120,10 @@ ExecNestLoop(NestLoop *node) * If we don't have an outer tuple, get the next one and reset the * inner scan. */ - if (nlstate->nl_NeedNewOuter) + if (node->nl_NeedNewOuter) { ENL1_printf("getting new outer tuple"); - outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node); + outerTupleSlot = ExecProcNode(outerPlan); /* * if there are no more outer tuples, then the join is @@ -138,10 +136,10 @@ ExecNestLoop(NestLoop *node) } ENL1_printf("saving new outer tuple information"); - nlstate->jstate.cs_OuterTupleSlot = outerTupleSlot; + node->js.ps.ps_OuterTupleSlot = outerTupleSlot; econtext->ecxt_outertuple = outerTupleSlot; - nlstate->nl_NeedNewOuter = false; - nlstate->nl_MatchedOuter = false; + node->nl_NeedNewOuter = false; + node->nl_MatchedOuter = false; /* * now rescan the inner plan @@ -153,7 +151,7 @@ ExecNestLoop(NestLoop *node) * outer tuple (e.g. in index scans), that's why we pass our * expr context. */ - ExecReScan(innerPlan, econtext, (Plan *) node); + ExecReScan(innerPlan, econtext); } /* @@ -161,17 +159,17 @@ ExecNestLoop(NestLoop *node) */ ENL1_printf("getting new inner tuple"); - innerTupleSlot = ExecProcNode(innerPlan, (Plan *) node); + innerTupleSlot = ExecProcNode(innerPlan); econtext->ecxt_innertuple = innerTupleSlot; if (TupIsNull(innerTupleSlot)) { ENL1_printf("no inner tuple, need new outer tuple"); - nlstate->nl_NeedNewOuter = true; + node->nl_NeedNewOuter = true; - if (!nlstate->nl_MatchedOuter && - node->join.jointype == JOIN_LEFT) + if (!node->nl_MatchedOuter && + node->js.jointype == JOIN_LEFT) { /* * We are doing an outer join and there were no join @@ -179,7 +177,7 @@ ExecNestLoop(NestLoop *node) * tuple with nulls for the inner tuple, and return it if * it passes the non-join quals. */ - econtext->ecxt_innertuple = nlstate->nl_NullInnerTupleSlot; + econtext->ecxt_innertuple = node->nl_NullInnerTupleSlot; ENL1_printf("testing qualification for outer-join tuple"); @@ -195,11 +193,11 @@ ExecNestLoop(NestLoop *node) ENL1_printf("qualification succeeded, projecting tuple"); - result = ExecProject(nlstate->jstate.cs_ProjInfo, &isDone); + result = ExecProject(node->js.ps.ps_ProjInfo, &isDone); if (isDone != ExprEndResult) { - nlstate->jstate.cs_TupFromTlist = + node->js.ps.ps_TupFromTlist = (isDone == ExprMultipleResult); return result; } @@ -224,7 +222,7 @@ ExecNestLoop(NestLoop *node) if (ExecQual(joinqual, econtext, false)) { - nlstate->nl_MatchedOuter = true; + node->nl_MatchedOuter = true; if (otherqual == NIL || ExecQual(otherqual, econtext, false)) { @@ -238,11 +236,11 @@ ExecNestLoop(NestLoop *node) ENL1_printf("qualification succeeded, projecting tuple"); - result = ExecProject(nlstate->jstate.cs_ProjInfo, &isDone); + result = ExecProject(node->js.ps.ps_ProjInfo, &isDone); if (isDone != ExprEndResult) { - nlstate->jstate.cs_TupFromTlist = + node->js.ps.ps_TupFromTlist = (isDone == ExprMultipleResult); return result; } @@ -260,14 +258,10 @@ ExecNestLoop(NestLoop *node) /* ---------------------------------------------------------------- * ExecInitNestLoop - * - * Creates the run-time state information for the nestloop node - * produced by the planner and initailizes inner and outer relations - * (child nodes). * ---------------------------------------------------------------- */ -bool -ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent) +NestLoopState * +ExecInitNestLoop(NestLoop *node, EState *estate) { NestLoopState *nlstate; @@ -275,35 +269,45 @@ ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent) "initializing node"); /* - * assign execution state to node - */ - node->join.plan.state = estate; - - /* - * create new nest loop state + * create state structure */ nlstate = makeNode(NestLoopState); - node->nlstate = nlstate; + nlstate->js.ps.plan = (Plan *) node; + nlstate->js.ps.state = estate; /* * Miscellaneous initialization * * create expression context for node */ - ExecAssignExprContext(estate, &nlstate->jstate); + ExecAssignExprContext(estate, &nlstate->js.ps); /* - * now initialize children + * initialize child expressions */ - ExecInitNode(outerPlan((Plan *) node), estate, (Plan *) node); - ExecInitNode(innerPlan((Plan *) node), estate, (Plan *) node); + nlstate->js.ps.targetlist = (List *) + ExecInitExpr((Node *) node->join.plan.targetlist, + (PlanState *) nlstate); + nlstate->js.ps.qual = (List *) + ExecInitExpr((Node *) node->join.plan.qual, + (PlanState *) nlstate); + nlstate->js.jointype = node->join.jointype; + nlstate->js.joinqual = (List *) + ExecInitExpr((Node *) node->join.joinqual, + (PlanState *) nlstate); + + /* + * initialize child nodes + */ + outerPlanState(nlstate) = ExecInitNode(outerPlan(node), estate); + innerPlanState(nlstate) = ExecInitNode(innerPlan(node), estate); #define NESTLOOP_NSLOTS 2 /* * tuple table initialization */ - ExecInitResultTupleSlot(estate, &nlstate->jstate); + ExecInitResultTupleSlot(estate, &nlstate->js.ps); switch (node->join.jointype) { @@ -312,7 +316,7 @@ ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent) case JOIN_LEFT: nlstate->nl_NullInnerTupleSlot = ExecInitNullTupleSlot(estate, - ExecGetTupType(innerPlan((Plan *) node))); + ExecGetTupType(innerPlanState(nlstate))); break; default: elog(ERROR, "ExecInitNestLoop: unsupported join type %d", @@ -322,20 +326,21 @@ ExecInitNestLoop(NestLoop *node, EState *estate, Plan *parent) /* * initialize tuple type and projection info */ - ExecAssignResultTypeFromTL((Plan *) node, &nlstate->jstate); - ExecAssignProjectionInfo((Plan *) node, &nlstate->jstate); + ExecAssignResultTypeFromTL(&nlstate->js.ps); + ExecAssignProjectionInfo(&nlstate->js.ps); /* * finally, wipe the current outer tuple clean. */ - nlstate->jstate.cs_OuterTupleSlot = NULL; - nlstate->jstate.cs_TupFromTlist = false; + nlstate->js.ps.ps_OuterTupleSlot = NULL; + nlstate->js.ps.ps_TupFromTlist = false; nlstate->nl_NeedNewOuter = true; nlstate->nl_MatchedOuter = false; NL1_printf("ExecInitNestLoop: %s\n", "node initialized"); - return TRUE; + + return nlstate; } int @@ -353,38 +358,27 @@ ExecCountSlotsNestLoop(NestLoop *node) * ---------------------------------------------------------------- */ void -ExecEndNestLoop(NestLoop *node) +ExecEndNestLoop(NestLoopState *node) { - NestLoopState *nlstate; - NL1_printf("ExecEndNestLoop: %s\n", "ending node processing"); /* - * get info from the node - */ - nlstate = node->nlstate; - - /* * Free the projection info - * - * Note: we don't ExecFreeResultType(nlstate) because the rule manager - * depends on the tupType returned by ExecMain(). So for now, this is - * freed at end-transaction time. -cim 6/2/91 */ - ExecFreeProjectionInfo(&nlstate->jstate); - ExecFreeExprContext(&nlstate->jstate); + ExecFreeProjectionInfo(&node->js.ps); + ExecFreeExprContext(&node->js.ps); /* * close down subplans */ - ExecEndNode(outerPlan((Plan *) node), (Plan *) node); - ExecEndNode(innerPlan((Plan *) node), (Plan *) node); + ExecEndNode(outerPlanState(node)); + ExecEndNode(innerPlanState(node)); /* * clean out the tuple table */ - ExecClearTuple(nlstate->jstate.cs_ResultTupleSlot); + ExecClearTuple(node->js.ps.ps_ResultTupleSlot); NL1_printf("ExecEndNestLoop: %s\n", "node processing ended"); @@ -395,10 +389,9 @@ ExecEndNestLoop(NestLoop *node) * ---------------------------------------------------------------- */ void -ExecReScanNestLoop(NestLoop *node, ExprContext *exprCtxt, Plan *parent) +ExecReScanNestLoop(NestLoopState *node, ExprContext *exprCtxt) { - NestLoopState *nlstate = node->nlstate; - Plan *outerPlan = outerPlan((Plan *) node); + PlanState *outerPlan = outerPlanState(node); /* * If outerPlan->chgParam is not null then plan will be automatically @@ -408,11 +401,11 @@ ExecReScanNestLoop(NestLoop *node, ExprContext *exprCtxt, Plan *parent) * run-time keys... */ if (outerPlan->chgParam == NULL) - ExecReScan(outerPlan, exprCtxt, (Plan *) node); + ExecReScan(outerPlan, exprCtxt); /* let outerPlan to free its result tuple ... */ - nlstate->jstate.cs_OuterTupleSlot = NULL; - nlstate->jstate.cs_TupFromTlist = false; - nlstate->nl_NeedNewOuter = true; - nlstate->nl_MatchedOuter = false; + node->js.ps.ps_OuterTupleSlot = NULL; + node->js.ps.ps_TupFromTlist = false; + node->nl_NeedNewOuter = true; + node->nl_MatchedOuter = false; } diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c index d9d1608a81..f14fd01c42 100644 --- a/src/backend/executor/nodeResult.c +++ b/src/backend/executor/nodeResult.c @@ -34,7 +34,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeResult.c,v 1.21 2002/06/20 20:29:28 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeResult.c,v 1.22 2002/12/05 15:50:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -60,34 +60,29 @@ * ---------------------------------------------------------------- */ TupleTableSlot * -ExecResult(Result *node) +ExecResult(ResultState *node) { - ResultState *resstate; TupleTableSlot *outerTupleSlot; TupleTableSlot *resultSlot; - Plan *outerPlan; + PlanState *outerPlan; ExprContext *econtext; ExprDoneCond isDone; - /* - * initialize the result node's state - */ - resstate = node->resstate; - econtext = resstate->cstate.cs_ExprContext; + econtext = node->ps.ps_ExprContext; /* * check constant qualifications like (2 > 1), if not already done */ - if (resstate->rs_checkqual) + if (node->rs_checkqual) { bool qualResult = ExecQual((List *) node->resconstantqual, econtext, false); - resstate->rs_checkqual = false; - if (qualResult == false) + node->rs_checkqual = false; + if (!qualResult) { - resstate->rs_done = true; + node->rs_done = true; return NULL; } } @@ -97,13 +92,13 @@ ExecResult(Result *node) * scan tuple (because there is a function-returning-set in the * projection expressions). If so, try to project another one. */ - if (resstate->cstate.cs_TupFromTlist) + if (node->ps.ps_TupFromTlist) { - resultSlot = ExecProject(resstate->cstate.cs_ProjInfo, &isDone); + resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone); if (isDone == ExprMultipleResult) return resultSlot; /* Done with that source tuple... */ - resstate->cstate.cs_TupFromTlist = false; + node->ps.ps_TupFromTlist = false; } /* @@ -119,9 +114,9 @@ ExecResult(Result *node) * called, OR that we failed the constant qual check. Either way, now * we are through. */ - while (!resstate->rs_done) + while (!node->rs_done) { - outerPlan = outerPlan(node); + outerPlan = outerPlanState(node); if (outerPlan != NULL) { @@ -129,12 +124,12 @@ ExecResult(Result *node) * retrieve tuples from the outer plan until there are no * more. */ - outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node); + outerTupleSlot = ExecProcNode(outerPlan); if (TupIsNull(outerTupleSlot)) return NULL; - resstate->cstate.cs_OuterTupleSlot = outerTupleSlot; + node->ps.ps_OuterTupleSlot = outerTupleSlot; /* * XXX gross hack. use outer tuple as scan tuple for @@ -149,7 +144,7 @@ ExecResult(Result *node) * if we don't have an outer plan, then we are just generating * the results from a constant target list. Do it only once. */ - resstate->rs_done = true; + node->rs_done = true; } /* @@ -157,11 +152,11 @@ ExecResult(Result *node) * unless the projection produces an empty set, in which case we * must loop back to see if there are more outerPlan tuples. */ - resultSlot = ExecProject(resstate->cstate.cs_ProjInfo, &isDone); + resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone); if (isDone != ExprEndResult) { - resstate->cstate.cs_TupFromTlist = (isDone == ExprMultipleResult); + node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult); return resultSlot; } } @@ -177,42 +172,51 @@ ExecResult(Result *node) * (child nodes). * ---------------------------------------------------------------- */ -bool -ExecInitResult(Result *node, EState *estate, Plan *parent) +ResultState * +ExecInitResult(Result *node, EState *estate) { ResultState *resstate; /* - * assign execution state to node - */ - node->plan.state = estate; - - /* - * create new ResultState for node + * create state structure */ resstate = makeNode(ResultState); + resstate->ps.plan = (Plan *) node; + resstate->ps.state = estate; + resstate->rs_done = false; resstate->rs_checkqual = (node->resconstantqual == NULL) ? false : true; - node->resstate = resstate; /* * Miscellaneous initialization * * create expression context for node */ - ExecAssignExprContext(estate, &resstate->cstate); + ExecAssignExprContext(estate, &resstate->ps); #define RESULT_NSLOTS 1 /* * tuple table initialization */ - ExecInitResultTupleSlot(estate, &resstate->cstate); + ExecInitResultTupleSlot(estate, &resstate->ps); /* - * then initialize children + * initialize child expressions */ - ExecInitNode(outerPlan(node), estate, (Plan *) node); + resstate->ps.targetlist = (List *) + ExecInitExpr((Node *) node->plan.targetlist, + (PlanState *) resstate); + resstate->ps.qual = (List *) + ExecInitExpr((Node *) node->plan.qual, + (PlanState *) resstate); + resstate->resconstantqual = ExecInitExpr(node->resconstantqual, + (PlanState *) resstate); + + /* + * initialize child nodes + */ + outerPlanState(resstate) = ExecInitNode(outerPlan(node), estate); /* * we don't use inner plan @@ -222,10 +226,10 @@ ExecInitResult(Result *node, EState *estate, Plan *parent) /* * initialize tuple type and projection info */ - ExecAssignResultTypeFromTL((Plan *) node, &resstate->cstate); - ExecAssignProjectionInfo((Plan *) node, &resstate->cstate); + ExecAssignResultTypeFromTL(&resstate->ps); + ExecAssignProjectionInfo(&resstate->ps); - return TRUE; + return resstate; } int @@ -241,49 +245,37 @@ ExecCountSlotsResult(Result *node) * ---------------------------------------------------------------- */ void -ExecEndResult(Result *node) +ExecEndResult(ResultState *node) { - ResultState *resstate; - - resstate = node->resstate; - /* * Free the projection info - * - * Note: we don't ExecFreeResultType(resstate) because the rule manager - * depends on the tupType returned by ExecMain(). So for now, this is - * freed at end-transaction time. -cim 6/2/91 */ - ExecFreeProjectionInfo(&resstate->cstate); - ExecFreeExprContext(&resstate->cstate); + ExecFreeProjectionInfo(&node->ps); + ExecFreeExprContext(&node->ps); /* - * shut down subplans + * clean out the tuple table */ - ExecEndNode(outerPlan(node), (Plan *) node); + ExecClearTuple(node->ps.ps_ResultTupleSlot); /* - * clean out the tuple table + * shut down subplans */ - ExecClearTuple(resstate->cstate.cs_ResultTupleSlot); - pfree(resstate); - node->resstate = NULL; /* XXX - new for us - er1p */ + ExecEndNode(outerPlanState(node)); } void -ExecReScanResult(Result *node, ExprContext *exprCtxt, Plan *parent) +ExecReScanResult(ResultState *node, ExprContext *exprCtxt) { - ResultState *resstate = node->resstate; - - resstate->rs_done = false; - resstate->cstate.cs_TupFromTlist = false; - resstate->rs_checkqual = (node->resconstantqual == NULL) ? false : true; + node->rs_done = false; + node->ps.ps_TupFromTlist = false; + node->rs_checkqual = (node->resconstantqual == NULL) ? false : true; /* * if chgParam of subnode is not null then plan will be re-scanned by * first ExecProcNode. */ - if (((Plan *) node)->lefttree && - ((Plan *) node)->lefttree->chgParam == NULL) - ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node); + if (((PlanState *) node)->lefttree && + ((PlanState *) node)->lefttree->chgParam == NULL) + ExecReScan(((PlanState *) node)->lefttree, exprCtxt); } diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c index b6848d6c4b..e19098fba2 100644 --- a/src/backend/executor/nodeSeqscan.c +++ b/src/backend/executor/nodeSeqscan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.38 2002/11/30 05:21:01 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.39 2002/12/05 15:50:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -29,9 +29,8 @@ #include "executor/nodeSeqscan.h" #include "parser/parsetree.h" -static Oid InitScanRelation(SeqScan *node, EState *estate, - CommonScanState *scanstate); -static TupleTableSlot *SeqNext(SeqScan *node); +static void InitScanRelation(SeqScanState *node, EState *estate); +static TupleTableSlot *SeqNext(SeqScanState *node); /* ---------------------------------------------------------------- * Scan Support @@ -44,11 +43,11 @@ static TupleTableSlot *SeqNext(SeqScan *node); * ---------------------------------------------------------------- */ static TupleTableSlot * -SeqNext(SeqScan *node) +SeqNext(SeqScanState *node) { HeapTuple tuple; HeapScanDesc scandesc; - CommonScanState *scanstate; + Index scanrelid; EState *estate; ScanDirection direction; TupleTableSlot *slot; @@ -56,11 +55,11 @@ SeqNext(SeqScan *node) /* * get information from the estate and scan state */ - estate = node->plan.state; - scanstate = node->scanstate; - scandesc = scanstate->css_currentScanDesc; + estate = node->ps.state; + scandesc = node->ss_currentScanDesc; + scanrelid = ((SeqScan *) node->ps.plan)->scanrelid; direction = estate->es_direction; - slot = scanstate->css_ScanTupleSlot; + slot = node->ss_ScanTupleSlot; /* * Check if we are evaluating PlanQual for tuple of this relation. @@ -69,13 +68,13 @@ SeqNext(SeqScan *node) * switching in Init/ReScan plan... */ if (estate->es_evTuple != NULL && - estate->es_evTuple[node->scanrelid - 1] != NULL) + estate->es_evTuple[scanrelid - 1] != NULL) { ExecClearTuple(slot); - if (estate->es_evTupleNull[node->scanrelid - 1]) + if (estate->es_evTupleNull[scanrelid - 1]) return slot; /* return empty slot */ - ExecStoreTuple(estate->es_evTuple[node->scanrelid - 1], + ExecStoreTuple(estate->es_evTuple[scanrelid - 1], slot, InvalidBuffer, false); /* @@ -85,7 +84,7 @@ SeqNext(SeqScan *node) */ /* Flag for the next call that no more tuples */ - estate->es_evTupleNull[node->scanrelid - 1] = true; + estate->es_evTupleNull[scanrelid - 1] = true; return (slot); } @@ -124,12 +123,12 @@ SeqNext(SeqScan *node) */ TupleTableSlot * -ExecSeqScan(SeqScan *node) +ExecSeqScan(SeqScanState *node) { /* * use SeqNext as access method */ - return ExecScan(node, (ExecScanAccessMtd) SeqNext); + return ExecScan((ScanState *) node, (ExecScanAccessMtd) SeqNext); } /* ---------------------------------------------------------------- @@ -139,9 +138,8 @@ ExecSeqScan(SeqScan *node) * subplans of scans. * ---------------------------------------------------------------- */ -static Oid -InitScanRelation(SeqScan *node, EState *estate, - CommonScanState *scanstate) +static void +InitScanRelation(SeqScanState *node, EState *estate) { Index relid; List *rangeTable; @@ -156,7 +154,7 @@ InitScanRelation(SeqScan *node, EState *estate, * * We acquire AccessShareLock for the duration of the scan. */ - relid = node->scanrelid; + relid = ((SeqScan *) node->ps.plan)->scanrelid; rangeTable = estate->es_range_table; rtentry = rt_fetch(relid, rangeTable); reloid = rtentry->relid; @@ -168,12 +166,10 @@ InitScanRelation(SeqScan *node, EState *estate, 0, NULL); - scanstate->css_currentRelation = currentRelation; - scanstate->css_currentScanDesc = currentScanDesc; + node->ss_currentRelation = currentRelation; + node->ss_currentScanDesc = currentScanDesc; - ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false); - - return reloid; + ExecAssignScanType(node, RelationGetDescr(currentRelation), false); } @@ -181,59 +177,64 @@ InitScanRelation(SeqScan *node, EState *estate, * ExecInitSeqScan * ---------------------------------------------------------------- */ -bool -ExecInitSeqScan(SeqScan *node, EState *estate, Plan *parent) +SeqScanState * +ExecInitSeqScan(SeqScan *node, EState *estate) { - CommonScanState *scanstate; - Oid reloid; + SeqScanState *scanstate; /* * Once upon a time it was possible to have an outerPlan of a SeqScan, * but not any more. */ - Assert(outerPlan((Plan *) node) == NULL); - Assert(innerPlan((Plan *) node) == NULL); - - /* - * assign the node's execution state - */ - node->plan.state = estate; + Assert(outerPlan(node) == NULL); + Assert(innerPlan(node) == NULL); /* - * create new CommonScanState for node + * create state structure */ - scanstate = makeNode(CommonScanState); - node->scanstate = scanstate; + scanstate = makeNode(SeqScanState); + scanstate->ps.plan = (Plan *) node; + scanstate->ps.state = estate; /* * Miscellaneous initialization * * create expression context for node */ - ExecAssignExprContext(estate, &scanstate->cstate); + ExecAssignExprContext(estate, &scanstate->ps); + + /* + * initialize child expressions + */ + scanstate->ps.targetlist = (List *) + ExecInitExpr((Node *) node->plan.targetlist, + (PlanState *) scanstate); + scanstate->ps.qual = (List *) + ExecInitExpr((Node *) node->plan.qual, + (PlanState *) scanstate); #define SEQSCAN_NSLOTS 2 /* * tuple table initialization */ - ExecInitResultTupleSlot(estate, &scanstate->cstate); + ExecInitResultTupleSlot(estate, &scanstate->ps); ExecInitScanTupleSlot(estate, scanstate); /* * initialize scan relation */ - reloid = InitScanRelation(node, estate, scanstate); + InitScanRelation(scanstate, estate); - scanstate->cstate.cs_TupFromTlist = false; + scanstate->ps.ps_TupFromTlist = false; /* * initialize tuple type */ - ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate); - ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate); + ExecAssignResultTypeFromTL(&scanstate->ps); + ExecAssignProjectionInfo(&scanstate->ps); - return TRUE; + return scanstate; } int @@ -251,28 +252,22 @@ ExecCountSlotsSeqScan(SeqScan *node) * ---------------------------------------------------------------- */ void -ExecEndSeqScan(SeqScan *node) +ExecEndSeqScan(SeqScanState *node) { - CommonScanState *scanstate; Relation relation; HeapScanDesc scanDesc; /* * get information from node */ - scanstate = node->scanstate; - relation = scanstate->css_currentRelation; - scanDesc = scanstate->css_currentScanDesc; + relation = node->ss_currentRelation; + scanDesc = node->ss_currentScanDesc; /* * Free the projection info and the scan attribute info - * - * Note: we don't ExecFreeResultType(scanstate) because the rule manager - * depends on the tupType returned by ExecMain(). So for now, this is - * freed at end-transaction time. -cim 6/2/91 */ - ExecFreeProjectionInfo(&scanstate->cstate); - ExecFreeExprContext(&scanstate->cstate); + ExecFreeProjectionInfo(&node->ps); + ExecFreeExprContext(&node->ps); /* * close heap scan @@ -280,6 +275,12 @@ ExecEndSeqScan(SeqScan *node) heap_endscan(scanDesc); /* + * clean out the tuple table + */ + ExecClearTuple(node->ps.ps_ResultTupleSlot); + ExecClearTuple(node->ss_ScanTupleSlot); + + /* * close the heap relation. * * Currently, we do not release the AccessShareLock acquired by @@ -288,12 +289,6 @@ ExecEndSeqScan(SeqScan *node) * locking, however.) */ heap_close(relation, NoLock); - - /* - * clean out the tuple table - */ - ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot); - ExecClearTuple(scanstate->css_ScanTupleSlot); } /* ---------------------------------------------------------------- @@ -308,24 +303,24 @@ ExecEndSeqScan(SeqScan *node) * ---------------------------------------------------------------- */ void -ExecSeqReScan(SeqScan *node, ExprContext *exprCtxt, Plan *parent) +ExecSeqReScan(SeqScanState *node, ExprContext *exprCtxt) { - CommonScanState *scanstate; EState *estate; + Index scanrelid; HeapScanDesc scan; - scanstate = node->scanstate; - estate = node->plan.state; + estate = node->ps.state; + scanrelid = ((SeqScan *) node->ps.plan)->scanrelid; /* If this is re-scanning of PlanQual ... */ if (estate->es_evTuple != NULL && - estate->es_evTuple[node->scanrelid - 1] != NULL) + estate->es_evTuple[scanrelid - 1] != NULL) { - estate->es_evTupleNull[node->scanrelid - 1] = false; + estate->es_evTupleNull[scanrelid - 1] = false; return; } - scan = scanstate->css_currentScanDesc; + scan = node->ss_currentScanDesc; heap_rescan(scan, /* scan desc */ NULL); /* new scan keys */ @@ -338,13 +333,11 @@ ExecSeqReScan(SeqScan *node, ExprContext *exprCtxt, Plan *parent) * ---------------------------------------------------------------- */ void -ExecSeqMarkPos(SeqScan *node) +ExecSeqMarkPos(SeqScanState *node) { - CommonScanState *scanstate; HeapScanDesc scan; - scanstate = node->scanstate; - scan = scanstate->css_currentScanDesc; + scan = node->ss_currentScanDesc; heap_markpos(scan); } @@ -355,12 +348,10 @@ ExecSeqMarkPos(SeqScan *node) * ---------------------------------------------------------------- */ void -ExecSeqRestrPos(SeqScan *node) +ExecSeqRestrPos(SeqScanState *node) { - CommonScanState *scanstate; HeapScanDesc scan; - scanstate = node->scanstate; - scan = scanstate->css_currentScanDesc; + scan = node->ss_currentScanDesc; heap_restrpos(scan); } diff --git a/src/backend/executor/nodeSetOp.c b/src/backend/executor/nodeSetOp.c index 3d1cf2c8ef..a81a4a29d9 100644 --- a/src/backend/executor/nodeSetOp.c +++ b/src/backend/executor/nodeSetOp.c @@ -21,7 +21,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeSetOp.c,v 1.6 2002/06/20 20:29:28 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeSetOp.c,v 1.7 2002/12/05 15:50:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -44,28 +44,27 @@ * ---------------------------------------------------------------- */ TupleTableSlot * /* return: a tuple or NULL */ -ExecSetOp(SetOp *node) +ExecSetOp(SetOpState *node) { - SetOpState *setopstate; + SetOp *plannode = (SetOp *) node->ps.plan; TupleTableSlot *resultTupleSlot; - Plan *outerPlan; + PlanState *outerPlan; TupleDesc tupDesc; /* * get information from the node */ - setopstate = node->setopstate; - outerPlan = outerPlan((Plan *) node); - resultTupleSlot = setopstate->cstate.cs_ResultTupleSlot; - tupDesc = ExecGetResultType(&setopstate->cstate); + outerPlan = outerPlanState(node); + resultTupleSlot = node->ps.ps_ResultTupleSlot; + tupDesc = ExecGetResultType(&node->ps); /* * If the previously-returned tuple needs to be returned more than * once, keep returning it. */ - if (setopstate->numOutput > 0) + if (node->numOutput > 0) { - setopstate->numOutput--; + node->numOutput--; return resultTupleSlot; } @@ -88,15 +87,15 @@ ExecSetOp(SetOp *node) /* * fetch a tuple from the outer subplan, unless we already did. */ - if (setopstate->cstate.cs_OuterTupleSlot == NULL && - !setopstate->subplan_done) + if (node->ps.ps_OuterTupleSlot == NULL && + !node->subplan_done) { - setopstate->cstate.cs_OuterTupleSlot = - ExecProcNode(outerPlan, (Plan *) node); - if (TupIsNull(setopstate->cstate.cs_OuterTupleSlot)) - setopstate->subplan_done = true; + node->ps.ps_OuterTupleSlot = + ExecProcNode(outerPlan); + if (TupIsNull(node->ps.ps_OuterTupleSlot)) + node->subplan_done = true; } - inputTupleSlot = setopstate->cstate.cs_OuterTupleSlot; + inputTupleSlot = node->ps.ps_OuterTupleSlot; if (TupIsNull(resultTupleSlot)) { @@ -104,18 +103,18 @@ ExecSetOp(SetOp *node) * First of group: save a copy in result slot, and reset * duplicate-counters for new group. */ - if (setopstate->subplan_done) + if (node->subplan_done) return NULL; /* no more tuples */ ExecStoreTuple(heap_copytuple(inputTupleSlot->val), resultTupleSlot, InvalidBuffer, true); /* free copied tuple at * ExecClearTuple */ - setopstate->numLeft = 0; - setopstate->numRight = 0; + node->numLeft = 0; + node->numRight = 0; endOfGroup = false; } - else if (setopstate->subplan_done) + else if (node->subplan_done) { /* * Reached end of input, so finish processing final group @@ -131,9 +130,9 @@ ExecSetOp(SetOp *node) if (execTuplesMatch(inputTupleSlot->val, resultTupleSlot->val, tupDesc, - node->numCols, node->dupColIdx, - setopstate->eqfunctions, - setopstate->tempContext)) + plannode->numCols, plannode->dupColIdx, + node->eqfunctions, + node->tempContext)) endOfGroup = false; else endOfGroup = true; @@ -146,37 +145,37 @@ ExecSetOp(SetOp *node) * Decide how many copies (if any) to emit. This logic is * straight from the SQL92 specification. */ - switch (node->cmd) + switch (plannode->cmd) { case SETOPCMD_INTERSECT: - if (setopstate->numLeft > 0 && setopstate->numRight > 0) - setopstate->numOutput = 1; + if (node->numLeft > 0 && node->numRight > 0) + node->numOutput = 1; else - setopstate->numOutput = 0; + node->numOutput = 0; break; case SETOPCMD_INTERSECT_ALL: - setopstate->numOutput = - (setopstate->numLeft < setopstate->numRight) ? - setopstate->numLeft : setopstate->numRight; + node->numOutput = + (node->numLeft < node->numRight) ? + node->numLeft : node->numRight; break; case SETOPCMD_EXCEPT: - if (setopstate->numLeft > 0 && setopstate->numRight == 0) - setopstate->numOutput = 1; + if (node->numLeft > 0 && node->numRight == 0) + node->numOutput = 1; else - setopstate->numOutput = 0; + node->numOutput = 0; break; case SETOPCMD_EXCEPT_ALL: - setopstate->numOutput = - (setopstate->numLeft < setopstate->numRight) ? - 0 : (setopstate->numLeft - setopstate->numRight); + node->numOutput = + (node->numLeft < node->numRight) ? + 0 : (node->numLeft - node->numRight); break; default: elog(ERROR, "ExecSetOp: bogus command code %d", - (int) node->cmd); + (int) plannode->cmd); break; } /* Fall out of for-loop if we have tuples to emit */ - if (setopstate->numOutput > 0) + if (node->numOutput > 0) break; /* Else flag that we have no current tuple, and loop around */ ExecClearTuple(resultTupleSlot); @@ -191,16 +190,16 @@ ExecSetOp(SetOp *node) bool isNull; flag = DatumGetInt32(heap_getattr(inputTupleSlot->val, - node->flagColIdx, + plannode->flagColIdx, tupDesc, &isNull)); Assert(!isNull); if (flag) - setopstate->numRight++; + node->numRight++; else - setopstate->numLeft++; + node->numLeft++; /* Set flag to fetch a new input tuple, and loop around */ - setopstate->cstate.cs_OuterTupleSlot = NULL; + node->ps.ps_OuterTupleSlot = NULL; } } @@ -208,8 +207,8 @@ ExecSetOp(SetOp *node) * If we fall out of loop, then we need to emit at least one copy of * resultTuple. */ - Assert(setopstate->numOutput > 0); - setopstate->numOutput--; + Assert(node->numOutput > 0); + node->numOutput--; return resultTupleSlot; } @@ -220,23 +219,19 @@ ExecSetOp(SetOp *node) * the node's subplan. * ---------------------------------------------------------------- */ -bool /* return: initialization status */ -ExecInitSetOp(SetOp *node, EState *estate, Plan *parent) +SetOpState * +ExecInitSetOp(SetOp *node, EState *estate) { SetOpState *setopstate; - Plan *outerPlan; - - /* - * assign execution state to node - */ - node->plan.state = estate; /* - * create new SetOpState for node + * create state structure */ setopstate = makeNode(SetOpState); - node->setopstate = setopstate; - setopstate->cstate.cs_OuterTupleSlot = NULL; + setopstate->ps.plan = (Plan *) node; + setopstate->ps.state = estate; + + setopstate->ps.ps_OuterTupleSlot = NULL; setopstate->subplan_done = false; setopstate->numOutput = 0; @@ -259,30 +254,29 @@ ExecInitSetOp(SetOp *node, EState *estate, Plan *parent) /* * Tuple table initialization */ - ExecInitResultTupleSlot(estate, &setopstate->cstate); + ExecInitResultTupleSlot(estate, &setopstate->ps); /* * then initialize outer plan */ - outerPlan = outerPlan((Plan *) node); - ExecInitNode(outerPlan, estate, (Plan *) node); + outerPlanState(setopstate) = ExecInitNode(outerPlan(node), estate); /* * setop nodes do no projections, so initialize projection info for * this node appropriately */ - ExecAssignResultTypeFromOuterPlan((Plan *) node, &setopstate->cstate); - setopstate->cstate.cs_ProjInfo = NULL; + ExecAssignResultTypeFromOuterPlan(&setopstate->ps); + setopstate->ps.ps_ProjInfo = NULL; /* * Precompute fmgr lookup data for inner loop */ setopstate->eqfunctions = - execTuplesMatchPrepare(ExecGetResultType(&setopstate->cstate), + execTuplesMatchPrepare(ExecGetResultType(&setopstate->ps), node->numCols, node->dupColIdx); - return TRUE; + return setopstate; } int @@ -301,34 +295,30 @@ ExecCountSlotsSetOp(SetOp *node) * ---------------------------------------------------------------- */ void -ExecEndSetOp(SetOp *node) +ExecEndSetOp(SetOpState *node) { - SetOpState *setopstate = node->setopstate; - - ExecEndNode(outerPlan((Plan *) node), (Plan *) node); + /* clean up tuple table */ + ExecClearTuple(node->ps.ps_ResultTupleSlot); + node->ps.ps_OuterTupleSlot = NULL; - MemoryContextDelete(setopstate->tempContext); + ExecEndNode(outerPlanState(node)); - /* clean up tuple table */ - ExecClearTuple(setopstate->cstate.cs_ResultTupleSlot); - setopstate->cstate.cs_OuterTupleSlot = NULL; + MemoryContextDelete(node->tempContext); } void -ExecReScanSetOp(SetOp *node, ExprContext *exprCtxt, Plan *parent) +ExecReScanSetOp(SetOpState *node, ExprContext *exprCtxt) { - SetOpState *setopstate = node->setopstate; - - ExecClearTuple(setopstate->cstate.cs_ResultTupleSlot); - setopstate->cstate.cs_OuterTupleSlot = NULL; - setopstate->subplan_done = false; - setopstate->numOutput = 0; + ExecClearTuple(node->ps.ps_ResultTupleSlot); + node->ps.ps_OuterTupleSlot = NULL; + node->subplan_done = false; + node->numOutput = 0; /* * if chgParam of subnode is not null then plan will be re-scanned by * first ExecProcNode. */ - if (((Plan *) node)->lefttree->chgParam == NULL) - ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node); + if (((PlanState *) node)->lefttree->chgParam == NULL) + ExecReScan(((PlanState *) node)->lefttree, exprCtxt); } diff --git a/src/backend/executor/nodeSort.c b/src/backend/executor/nodeSort.c index 05f36427be..e1b4db7a51 100644 --- a/src/backend/executor/nodeSort.c +++ b/src/backend/executor/nodeSort.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeSort.c,v 1.40 2002/11/13 00:39:47 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeSort.c,v 1.41 2002/12/05 15:50:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -88,10 +88,9 @@ ExtractSortKeys(Sort *sortnode, * ---------------------------------------------------------------- */ TupleTableSlot * -ExecSort(Sort *node) +ExecSort(SortState *node) { EState *estate; - SortState *sortstate; ScanDirection dir; Tuplesortstate *tuplesortstate; HeapTuple heapTuple; @@ -104,10 +103,9 @@ ExecSort(Sort *node) SO1_printf("ExecSort: %s\n", "entering routine"); - sortstate = node->sortstate; - estate = node->plan.state; + estate = node->ss.ps.state; dir = estate->es_direction; - tuplesortstate = (Tuplesortstate *) sortstate->tuplesortstate; + tuplesortstate = (Tuplesortstate *) node->tuplesortstate; /* * If first time through, read all tuples from outer plan and pass @@ -115,9 +113,10 @@ ExecSort(Sort *node) * tuplesort. */ - if (!sortstate->sort_Done) + if (!node->sort_Done) { - Plan *outerNode; + Sort *plannode = (Sort *) node->ss.ps.plan; + PlanState *outerNode; TupleDesc tupDesc; Oid *sortOperators; AttrNumber *attNums; @@ -127,8 +126,7 @@ ExecSort(Sort *node) /* * Want to scan subplan in the forward direction while creating - * the sorted data. (Does setting my direction actually affect - * the subplan? I bet this is useless code...) + * the sorted data. */ estate->es_direction = ForwardScanDirection; @@ -138,15 +136,15 @@ ExecSort(Sort *node) SO1_printf("ExecSort: %s\n", "calling tuplesort_begin"); - outerNode = outerPlan((Plan *) node); + outerNode = outerPlanState(node); tupDesc = ExecGetTupType(outerNode); - ExtractSortKeys(node, &sortOperators, &attNums); + ExtractSortKeys(plannode, &sortOperators, &attNums); - tuplesortstate = tuplesort_begin_heap(tupDesc, node->keycount, + tuplesortstate = tuplesort_begin_heap(tupDesc, plannode->keycount, sortOperators, attNums, true /* randomAccess */ ); - sortstate->tuplesortstate = (void *) tuplesortstate; + node->tuplesortstate = (void *) tuplesortstate; pfree(sortOperators); pfree(attNums); @@ -157,7 +155,7 @@ ExecSort(Sort *node) for (;;) { - slot = ExecProcNode(outerNode, (Plan *) node); + slot = ExecProcNode(outerNode); if (TupIsNull(slot)) break; @@ -178,12 +176,12 @@ ExecSort(Sort *node) /* * make sure the tuple descriptor is up to date (is this needed?) */ - ExecAssignResultType(&sortstate->csstate.cstate, tupDesc, false); + ExecAssignResultType(&node->ss.ps, tupDesc, false); /* * finally set the sorted flag to true */ - sortstate->sort_Done = true; + node->sort_Done = true; SO1_printf("ExecSort: %s\n", "sorting done"); } @@ -198,7 +196,7 @@ ExecSort(Sort *node) ScanDirectionIsForward(dir), &should_free); - slot = sortstate->csstate.cstate.cs_ResultTupleSlot; + slot = node->ss.ps.ps_ResultTupleSlot; return ExecStoreTuple(heapTuple, slot, InvalidBuffer, should_free); } @@ -209,29 +207,24 @@ ExecSort(Sort *node) * produced by the planner and initailizes its outer subtree. * ---------------------------------------------------------------- */ -bool -ExecInitSort(Sort *node, EState *estate, Plan *parent) +SortState * +ExecInitSort(Sort *node, EState *estate) { SortState *sortstate; - Plan *outerPlan; SO1_printf("ExecInitSort: %s\n", "initializing sort node"); /* - * assign the node's execution state - */ - node->plan.state = estate; - - /* * create state structure */ sortstate = makeNode(SortState); + sortstate->ss.ps.plan = (Plan *) node; + sortstate->ss.ps.state = estate; + sortstate->sort_Done = false; sortstate->tuplesortstate = NULL; - node->sortstate = sortstate; - /* * Miscellaneous initialization * @@ -246,27 +239,26 @@ ExecInitSort(Sort *node, EState *estate, Plan *parent) * * sort nodes only return scan tuples from their sorted relation. */ - ExecInitResultTupleSlot(estate, &sortstate->csstate.cstate); - ExecInitScanTupleSlot(estate, &sortstate->csstate); + ExecInitResultTupleSlot(estate, &sortstate->ss.ps); + ExecInitScanTupleSlot(estate, &sortstate->ss); /* * initializes child nodes */ - outerPlan = outerPlan((Plan *) node); - ExecInitNode(outerPlan, estate, (Plan *) node); + outerPlanState(sortstate) = ExecInitNode(outerPlan(node), estate); /* * initialize tuple type. no need to initialize projection info * because this node doesn't do projections. */ - ExecAssignResultTypeFromOuterPlan((Plan *) node, &sortstate->csstate.cstate); - ExecAssignScanTypeFromOuterPlan((Plan *) node, &sortstate->csstate); - sortstate->csstate.cstate.cs_ProjInfo = NULL; + ExecAssignResultTypeFromOuterPlan(&sortstate->ss.ps); + ExecAssignScanTypeFromOuterPlan(&sortstate->ss); + sortstate->ss.ps.ps_ProjInfo = NULL; SO1_printf("ExecInitSort: %s\n", "sort node initialized"); - return TRUE; + return sortstate; } int @@ -282,39 +274,27 @@ ExecCountSlotsSort(Sort *node) * ---------------------------------------------------------------- */ void -ExecEndSort(Sort *node) +ExecEndSort(SortState *node) { - SortState *sortstate; - Plan *outerPlan; - - /* - * get info from the sort state - */ SO1_printf("ExecEndSort: %s\n", "shutting down sort node"); - sortstate = node->sortstate; - /* - * shut down the subplan + * clean out the tuple table */ - outerPlan = outerPlan((Plan *) node); - ExecEndNode(outerPlan, (Plan *) node); + ExecClearTuple(node->ss.ss_ScanTupleSlot); /* - * clean out the tuple table + * shut down the subplan */ - ExecClearTuple(sortstate->csstate.css_ScanTupleSlot); + ExecEndNode(outerPlanState(node)); /* * Release tuplesort resources */ - if (sortstate->tuplesortstate != NULL) - tuplesort_end((Tuplesortstate *) sortstate->tuplesortstate); - sortstate->tuplesortstate = NULL; - - pfree(sortstate); - node->sortstate = NULL; + if (node->tuplesortstate != NULL) + tuplesort_end((Tuplesortstate *) node->tuplesortstate); + node->tuplesortstate = NULL; SO1_printf("ExecEndSort: %s\n", "sort node shutdown"); @@ -327,17 +307,15 @@ ExecEndSort(Sort *node) * ---------------------------------------------------------------- */ void -ExecSortMarkPos(Sort *node) +ExecSortMarkPos(SortState *node) { - SortState *sortstate = node->sortstate; - /* * if we haven't sorted yet, just return */ - if (!sortstate->sort_Done) + if (!node->sort_Done) return; - tuplesort_markpos((Tuplesortstate *) sortstate->tuplesortstate); + tuplesort_markpos((Tuplesortstate *) node->tuplesortstate); } /* ---------------------------------------------------------------- @@ -347,36 +325,32 @@ ExecSortMarkPos(Sort *node) * ---------------------------------------------------------------- */ void -ExecSortRestrPos(Sort *node) +ExecSortRestrPos(SortState *node) { - SortState *sortstate = node->sortstate; - /* * if we haven't sorted yet, just return. */ - if (!sortstate->sort_Done) + if (!node->sort_Done) return; /* * restore the scan to the previously marked position */ - tuplesort_restorepos((Tuplesortstate *) sortstate->tuplesortstate); + tuplesort_restorepos((Tuplesortstate *) node->tuplesortstate); } void -ExecReScanSort(Sort *node, ExprContext *exprCtxt, Plan *parent) +ExecReScanSort(SortState *node, ExprContext *exprCtxt) { - SortState *sortstate = node->sortstate; - /* * If we haven't sorted yet, just return. If outerplan' chgParam is * not NULL then it will be re-scanned by ExecProcNode, else - no * reason to re-scan it at all. */ - if (!sortstate->sort_Done) + if (!node->sort_Done) return; - ExecClearTuple(sortstate->csstate.cstate.cs_ResultTupleSlot); + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); /* * If subnode is to be rescanned then we forget previous sort results; @@ -384,12 +358,12 @@ ExecReScanSort(Sort *node, ExprContext *exprCtxt, Plan *parent) * * Otherwise we can just rewind and rescan the sorted output. */ - if (((Plan *) node)->lefttree->chgParam != NULL) + if (((PlanState *) node)->lefttree->chgParam != NULL) { - sortstate->sort_Done = false; - tuplesort_end((Tuplesortstate *) sortstate->tuplesortstate); - sortstate->tuplesortstate = NULL; + node->sort_Done = false; + tuplesort_end((Tuplesortstate *) node->tuplesortstate); + node->tuplesortstate = NULL; } else - tuplesort_rescan((Tuplesortstate *) sortstate->tuplesortstate); + tuplesort_rescan((Tuplesortstate *) node->tuplesortstate); } diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index 73ff6370fb..195634c128 100644 --- a/src/backend/executor/nodeSubplan.c +++ b/src/backend/executor/nodeSubplan.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.34 2002/11/26 03:01:57 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.35 2002/12/05 15:50:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -27,14 +27,15 @@ /* ---------------------------------------------------------------- * ExecSubPlan(node) - * * ---------------------------------------------------------------- */ Datum -ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull) +ExecSubPlan(SubPlanState *node, List *pvar, + ExprContext *econtext, bool *isNull) { - Plan *plan = node->plan; - SubLink *sublink = node->sublink; + PlanState *planstate = node->planstate; + SubPlan *subplan = (SubPlan *) node->ps.plan; + SubLink *sublink = subplan->sublink; SubLinkType subLinkType = sublink->subLinkType; bool useor = sublink->useor; MemoryContext oldcontext; @@ -49,15 +50,15 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull) */ oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory); - if (node->setParam != NIL) + if (subplan->setParam != NIL) elog(ERROR, "ExecSubPlan: can't set parent params from subquery"); /* * Set Params of this plan from parent plan correlation Vars */ - if (node->parParam != NIL) + if (subplan->parParam != NIL) { - foreach(lst, node->parParam) + foreach(lst, subplan->parParam) { ParamExecData *prm; @@ -69,11 +70,12 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull) NULL); pvar = lnext(pvar); } - plan->chgParam = nconc(plan->chgParam, listCopy(node->parParam)); + planstate->chgParam = nconc(planstate->chgParam, + listCopy(subplan->parParam)); } Assert(pvar == NIL); - ExecReScan(plan, NULL, NULL); + ExecReScan(planstate, NULL); /* * For all sublink types except EXPR_SUBLINK, the result is boolean as @@ -96,9 +98,9 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull) result = BoolGetDatum(subLinkType == ALL_SUBLINK); *isNull = false; - for (slot = ExecProcNode(plan, NULL); + for (slot = ExecProcNode(planstate); !TupIsNull(slot); - slot = ExecProcNode(plan, NULL)) + slot = ExecProcNode(planstate)) { HeapTuple tup = slot->val; TupleDesc tdesc = slot->ttc_tupleDescriptor; @@ -283,13 +285,37 @@ ExecSubPlan(SubPlan *node, List *pvar, ExprContext *econtext, bool *isNull) /* ---------------------------------------------------------------- * ExecInitSubPlan - * * ---------------------------------------------------------------- */ -bool -ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent) +SubPlanState * +ExecInitSubPlan(SubPlan *node, EState *estate) { - EState *sp_estate = CreateExecutorState(); + SubPlanState *subplanstate; + EState *sp_estate; + + /* + * Do access checking on the rangetable entries in the subquery. + * Here, we assume the subquery is a SELECT. + */ + ExecCheckRTPerms(node->rtable, CMD_SELECT); + + /* + * create state structure + */ + subplanstate = makeNode(SubPlanState); + subplanstate->ps.plan = (Plan *) node; + subplanstate->ps.state = estate; + + subplanstate->needShutdown = false; + subplanstate->curTuple = NULL; + + /* XXX temporary hack */ + node->pstate = subplanstate; + + /* + * create an EState for the subplan + */ + sp_estate = CreateExecutorState(); sp_estate->es_range_table = node->rtable; sp_estate->es_param_list_info = estate->es_param_list_info; @@ -297,14 +323,14 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent) sp_estate->es_tupleTable = ExecCreateTupleTable(ExecCountSlotsNode(node->plan) + 10); sp_estate->es_snapshot = estate->es_snapshot; + sp_estate->es_instrument = estate->es_instrument; - node->needShutdown = false; - node->curTuple = NULL; - - if (!ExecInitNode(node->plan, sp_estate, parent)) - return false; + /* + * Start up the subplan + */ + subplanstate->planstate = ExecInitNode(node->plan, sp_estate); - node->needShutdown = true; /* now we need to shutdown the subplan */ + subplanstate->needShutdown = true; /* now we need to shutdown the subplan */ /* * If this plan is un-correlated or undirect correlated one and want @@ -318,7 +344,7 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent) { ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]); - prm->execPlan = node; + prm->execPlan = subplanstate; } /* @@ -328,7 +354,7 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent) */ } - return true; + return subplanstate; } /* ---------------------------------------------------------------- @@ -345,10 +371,12 @@ ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent) * ---------------------------------------------------------------- */ void -ExecSetParamPlan(SubPlan *node, ExprContext *econtext) +ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) { - Plan *plan = node->plan; - SubLink *sublink = node->sublink; + PlanState *planstate = node->planstate; + SubPlan *subplan = (SubPlan *) node->ps.plan; + SubLink *sublink = subplan->sublink; + EState *estate = node->ps.state; MemoryContext oldcontext; TupleTableSlot *slot; List *lst; @@ -364,12 +392,12 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext) sublink->subLinkType == ALL_SUBLINK) elog(ERROR, "ExecSetParamPlan: ANY/ALL subselect unsupported"); - if (plan->chgParam != NULL) - ExecReScan(plan, NULL, NULL); + if (planstate->chgParam != NULL) + ExecReScan(planstate, NULL); - for (slot = ExecProcNode(plan, NULL); + for (slot = ExecProcNode(planstate); !TupIsNull(slot); - slot = ExecProcNode(plan, NULL)) + slot = ExecProcNode(planstate)) { HeapTuple tup = slot->val; TupleDesc tdesc = slot->ttc_tupleDescriptor; @@ -377,7 +405,7 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext) if (sublink->subLinkType == EXISTS_SUBLINK) { - ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(node->setParam)]); + ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(subplan->setParam)]); prm->execPlan = NULL; prm->value = BoolGetDatum(true); @@ -404,9 +432,9 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext) heap_freetuple(node->curTuple); node->curTuple = tup; - foreach(lst, node->setParam) + foreach(lst, subplan->setParam) { - ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(lst)]); + ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]); prm->execPlan = NULL; prm->value = heap_getattr(tup, i, tdesc, &(prm->isnull)); @@ -418,7 +446,7 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext) { if (sublink->subLinkType == EXISTS_SUBLINK) { - ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(node->setParam)]); + ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(subplan->setParam)]); prm->execPlan = NULL; prm->value = BoolGetDatum(false); @@ -426,9 +454,9 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext) } else { - foreach(lst, node->setParam) + foreach(lst, subplan->setParam) { - ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(lst)]); + ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]); prm->execPlan = NULL; prm->value = (Datum) 0; @@ -437,9 +465,9 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext) } } - if (plan->extParam == NULL) /* un-correlated ... */ + if (planstate->plan->extParam == NULL) /* un-correlated ... */ { - ExecEndNode(plan, NULL); + ExecEndNode(planstate); node->needShutdown = false; } @@ -451,11 +479,11 @@ ExecSetParamPlan(SubPlan *node, ExprContext *econtext) * ---------------------------------------------------------------- */ void -ExecEndSubPlan(SubPlan *node) +ExecEndSubPlan(SubPlanState *node) { if (node->needShutdown) { - ExecEndNode(node->plan, NULL); + ExecEndNode(node->planstate); node->needShutdown = false; } if (node->curTuple) @@ -466,33 +494,34 @@ ExecEndSubPlan(SubPlan *node) } void -ExecReScanSetParamPlan(SubPlan *node, Plan *parent) +ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent) { - Plan *plan = node->plan; + PlanState *planstate = node->planstate; + SubPlan *subplan = (SubPlan *) node->ps.plan; + EState *estate = node->ps.state; List *lst; - if (node->parParam != NULL) + if (subplan->parParam != NULL) elog(ERROR, "ExecReScanSetParamPlan: direct correlated subquery unsupported, yet"); - if (node->setParam == NULL) + if (subplan->setParam == NULL) elog(ERROR, "ExecReScanSetParamPlan: setParam list is NULL"); - if (plan->extParam == NULL) + if (planstate->plan->extParam == NULL) elog(ERROR, "ExecReScanSetParamPlan: extParam list of plan is NULL"); /* * Don't actual re-scan: ExecSetParamPlan does re-scan if - * node->plan->chgParam is not NULL... ExecReScan (plan, NULL, NULL); + * subplan->plan->chgParam is not NULL... ExecReScan (planstate, NULL); */ /* * Mark this subplan's output parameters as needing recalculation */ - foreach(lst, node->setParam) + foreach(lst, subplan->setParam) { - ParamExecData *prm = &(plan->state->es_param_exec_vals[lfirsti(lst)]); + ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]); prm->execPlan = node; } - parent->chgParam = nconc(parent->chgParam, listCopy(node->setParam)); - + parent->chgParam = nconc(parent->chgParam, listCopy(subplan->setParam)); } diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c index 982dd0236c..ba0ed8635b 100644 --- a/src/backend/executor/nodeSubqueryscan.c +++ b/src/backend/executor/nodeSubqueryscan.c @@ -12,7 +12,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.13 2002/06/20 20:29:28 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.14 2002/12/05 15:50:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -35,7 +35,7 @@ #include "parser/parsetree.h" #include "tcop/pquery.h" -static TupleTableSlot *SubqueryNext(SubqueryScan *node); +static TupleTableSlot *SubqueryNext(SubqueryScanState *node); /* ---------------------------------------------------------------- * Scan Support @@ -48,9 +48,8 @@ static TupleTableSlot *SubqueryNext(SubqueryScan *node); * ---------------------------------------------------------------- */ static TupleTableSlot * -SubqueryNext(SubqueryScan *node) +SubqueryNext(SubqueryScanState *node) { - SubqueryScanState *subquerystate; EState *estate; ScanDirection direction; TupleTableSlot *slot; @@ -58,8 +57,7 @@ SubqueryNext(SubqueryScan *node) /* * get information from the estate and scan state */ - estate = node->scan.plan.state; - subquerystate = (SubqueryScanState *) node->scan.scanstate; + estate = node->ss.ps.state; direction = estate->es_direction; /* @@ -70,11 +68,11 @@ SubqueryNext(SubqueryScan *node) /* * get the next tuple from the sub-query */ - subquerystate->sss_SubEState->es_direction = direction; + node->sss_SubEState->es_direction = direction; - slot = ExecProcNode(node->subplan, (Plan *) node); + slot = ExecProcNode(node->subplan); - subquerystate->csstate.css_ScanTupleSlot = slot; + node->ss.ss_ScanTupleSlot = slot; return slot; } @@ -90,20 +88,20 @@ SubqueryNext(SubqueryScan *node) */ TupleTableSlot * -ExecSubqueryScan(SubqueryScan *node) +ExecSubqueryScan(SubqueryScanState *node) { /* * use SubqueryNext as access method */ - return ExecScan(&node->scan, (ExecScanAccessMtd) SubqueryNext); + return ExecScan(&node->ss, (ExecScanAccessMtd) SubqueryNext); } /* ---------------------------------------------------------------- * ExecInitSubqueryScan * ---------------------------------------------------------------- */ -bool -ExecInitSubqueryScan(SubqueryScan *node, EState *estate, Plan *parent) +SubqueryScanState * +ExecInitSubqueryScan(SubqueryScan *node, EState *estate) { SubqueryScanState *subquerystate; RangeTblEntry *rte; @@ -112,33 +110,39 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, Plan *parent) /* * SubqueryScan should not have any "normal" children. */ - Assert(outerPlan((Plan *) node) == NULL); - Assert(innerPlan((Plan *) node) == NULL); + Assert(outerPlan(node) == NULL); + Assert(innerPlan(node) == NULL); /* - * assign the node's execution state - */ - node->scan.plan.state = estate; - - /* - * create new SubqueryScanState for node + * create state structure */ subquerystate = makeNode(SubqueryScanState); - node->scan.scanstate = (CommonScanState *) subquerystate; + subquerystate->ss.ps.plan = (Plan *) node; + subquerystate->ss.ps.state = estate; /* * Miscellaneous initialization * * create expression context for node */ - ExecAssignExprContext(estate, &subquerystate->csstate.cstate); + ExecAssignExprContext(estate, &subquerystate->ss.ps); + + /* + * initialize child expressions + */ + subquerystate->ss.ps.targetlist = (List *) + ExecInitExpr((Node *) node->scan.plan.targetlist, + (PlanState *) subquerystate); + subquerystate->ss.ps.qual = (List *) + ExecInitExpr((Node *) node->scan.plan.qual, + (PlanState *) subquerystate); #define SUBQUERYSCAN_NSLOTS 1 /* * tuple table initialization */ - ExecInitResultTupleSlot(estate, &subquerystate->csstate.cstate); + ExecInitResultTupleSlot(estate, &subquerystate->ss.ps); /* * initialize subquery @@ -157,20 +161,20 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, Plan *parent) sp_estate->es_tupleTable = ExecCreateTupleTable(ExecCountSlotsNode(node->subplan) + 10); sp_estate->es_snapshot = estate->es_snapshot; + sp_estate->es_instrument = estate->es_instrument; - if (!ExecInitNode(node->subplan, sp_estate, (Plan *) node)) - return false; + subquerystate->subplan = ExecInitNode(node->subplan, sp_estate); - subquerystate->csstate.css_ScanTupleSlot = NULL; - subquerystate->csstate.cstate.cs_TupFromTlist = false; + subquerystate->ss.ss_ScanTupleSlot = NULL; + subquerystate->ss.ps.ps_TupFromTlist = false; /* * initialize tuple type */ - ExecAssignResultTypeFromTL((Plan *) node, &subquerystate->csstate.cstate); - ExecAssignProjectionInfo((Plan *) node, &subquerystate->csstate.cstate); + ExecAssignResultTypeFromTL(&subquerystate->ss.ps); + ExecAssignProjectionInfo(&subquerystate->ss.ps); - return TRUE; + return subquerystate; } int @@ -191,42 +195,31 @@ ExecCountSlotsSubqueryScan(SubqueryScan *node) * ---------------------------------------------------------------- */ void -ExecEndSubqueryScan(SubqueryScan *node) +ExecEndSubqueryScan(SubqueryScanState *node) { - SubqueryScanState *subquerystate; - /* - * get information from node + * Free the projection info and the scan attribute info */ - subquerystate = (SubqueryScanState *) node->scan.scanstate; + ExecFreeProjectionInfo(&node->ss.ps); + ExecFreeExprContext(&node->ss.ps); /* - * Free the projection info and the scan attribute info - * - * Note: we don't ExecFreeResultType(subquerystate) because the rule - * manager depends on the tupType returned by ExecMain(). So for now, - * this is freed at end-transaction time. -cim 6/2/91 + * clean out the upper tuple table */ - ExecFreeProjectionInfo(&subquerystate->csstate.cstate); - ExecFreeExprContext(&subquerystate->csstate.cstate); + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); /* * close down subquery */ - ExecEndNode(node->subplan, (Plan *) node); + ExecEndNode(node->subplan); /* * clean up subquery's tuple table */ - subquerystate->csstate.css_ScanTupleSlot = NULL; - ExecDropTupleTable(subquerystate->sss_SubEState->es_tupleTable, true); + node->ss.ss_ScanTupleSlot = NULL; + ExecDropTupleTable(node->sss_SubEState->es_tupleTable, true); /* XXX we seem to be leaking the sub-EState... */ - - /* - * clean out the upper tuple table - */ - ExecClearTuple(subquerystate->csstate.cstate.cs_ResultTupleSlot); } /* ---------------------------------------------------------------- @@ -236,27 +229,25 @@ ExecEndSubqueryScan(SubqueryScan *node) * ---------------------------------------------------------------- */ void -ExecSubqueryReScan(SubqueryScan *node, ExprContext *exprCtxt, Plan *parent) +ExecSubqueryReScan(SubqueryScanState *node, ExprContext *exprCtxt) { - SubqueryScanState *subquerystate; EState *estate; - subquerystate = (SubqueryScanState *) node->scan.scanstate; - estate = node->scan.plan.state; + estate = node->ss.ps.state; /* * ExecReScan doesn't know about my subplan, so I have to do * changed-parameter signaling myself. */ - if (node->scan.plan.chgParam != NULL) - SetChangedParamList(node->subplan, node->scan.plan.chgParam); + if (node->ss.ps.chgParam != NULL) + SetChangedParamList(node->subplan, node->ss.ps.chgParam); /* * if chgParam of subnode is not null then plan will be re-scanned by * first ExecProcNode. */ if (node->subplan->chgParam == NULL) - ExecReScan(node->subplan, NULL, (Plan *) node); + ExecReScan(node->subplan, NULL); - subquerystate->csstate.css_ScanTupleSlot = NULL; + node->ss.ss_ScanTupleSlot = NULL; } diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c index 0fb7c6df4a..53b3c26d35 100644 --- a/src/backend/executor/nodeTidscan.c +++ b/src/backend/executor/nodeTidscan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.27 2002/11/30 05:21:01 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.28 2002/12/05 15:50:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -30,7 +30,7 @@ #include "parser/parsetree.h" static int TidListCreate(List *, ExprContext *, ItemPointerData[]); -static TupleTableSlot *TidNext(TidScan *node); +static TupleTableSlot *TidNext(TidScanState *node); static int TidListCreate(List *evalList, ExprContext *econtext, ItemPointerData tidList[]) @@ -65,19 +65,17 @@ TidListCreate(List *evalList, ExprContext *econtext, ItemPointerData tidList[]) * ---------------------------------------------------------------- */ static TupleTableSlot * -TidNext(TidScan *node) +TidNext(TidScanState *node) { EState *estate; - CommonScanState *scanstate; - TidScanState *tidstate; ScanDirection direction; Snapshot snapshot; Relation heapRelation; HeapTuple tuple; TupleTableSlot *slot; + Index scanrelid; Buffer buffer = InvalidBuffer; int numTids; - bool bBackward; int tidNumber; ItemPointerData *tidList; @@ -85,15 +83,14 @@ TidNext(TidScan *node) /* * extract necessary information from tid scan node */ - estate = node->scan.plan.state; + estate = node->ss.ps.state; direction = estate->es_direction; snapshot = estate->es_snapshot; - scanstate = node->scan.scanstate; - tidstate = node->tidstate; - heapRelation = scanstate->css_currentRelation; - numTids = tidstate->tss_NumTids; - tidList = tidstate->tss_TidList; - slot = scanstate->css_ScanTupleSlot; + heapRelation = node->ss.ss_currentRelation; + numTids = node->tss_NumTids; + tidList = node->tss_TidList; + slot = node->ss.ss_ScanTupleSlot; + scanrelid = ((TidScan *) node->ss.ps.plan)->scan.scanrelid; /* * Check if we are evaluating PlanQual for tuple of this relation. @@ -102,10 +99,10 @@ TidNext(TidScan *node) * switching in Init/ReScan plan... */ if (estate->es_evTuple != NULL && - estate->es_evTuple[node->scan.scanrelid - 1] != NULL) + estate->es_evTuple[scanrelid - 1] != NULL) { ExecClearTuple(slot); - if (estate->es_evTupleNull[node->scan.scanrelid - 1]) + if (estate->es_evTupleNull[scanrelid - 1]) return slot; /* return empty slot */ /* @@ -113,15 +110,15 @@ TidNext(TidScan *node) * list? In runtime-key case this is not certain, is it? */ - ExecStoreTuple(estate->es_evTuple[node->scan.scanrelid - 1], + ExecStoreTuple(estate->es_evTuple[scanrelid - 1], slot, InvalidBuffer, false); /* Flag for the next call that no more tuples */ - estate->es_evTupleNull[node->scan.scanrelid - 1] = true; + estate->es_evTupleNull[scanrelid - 1] = true; return (slot); } - tuple = &(tidstate->tss_htup); + tuple = &(node->tss_htup); /* * ok, now that we have what we need, fetch an tid tuple. if scanning @@ -131,26 +128,26 @@ TidNext(TidScan *node) bBackward = ScanDirectionIsBackward(direction); if (bBackward) { - tidNumber = numTids - tidstate->tss_TidPtr - 1; + tidNumber = numTids - node->tss_TidPtr - 1; if (tidNumber < 0) { tidNumber = 0; - tidstate->tss_TidPtr = numTids - 1; + node->tss_TidPtr = numTids - 1; } } else { - if ((tidNumber = tidstate->tss_TidPtr) < 0) + if ((tidNumber = node->tss_TidPtr) < 0) { tidNumber = 0; - tidstate->tss_TidPtr = 0; + node->tss_TidPtr = 0; } } while (tidNumber < numTids) { bool slot_is_valid = false; - tuple->t_self = tidList[tidstate->tss_TidPtr]; + tuple->t_self = tidList[node->tss_TidPtr]; if (heap_fetch(heapRelation, snapshot, tuple, &buffer, false, NULL)) { bool prev_matches = false; @@ -181,7 +178,7 @@ TidNext(TidScan *node) * do this by passing the tuple through ExecQual and look for * failure with all previous qualifications. */ - for (prev_tid = 0; prev_tid < tidstate->tss_TidPtr; + for (prev_tid = 0; prev_tid < node->tss_TidPtr; prev_tid++) { if (ItemPointerEquals(&tidList[prev_tid], &tuple->t_self)) @@ -197,9 +194,9 @@ TidNext(TidScan *node) } tidNumber++; if (bBackward) - tidstate->tss_TidPtr--; + node->tss_TidPtr--; else - tidstate->tss_TidPtr++; + node->tss_TidPtr++; if (slot_is_valid) return slot; } @@ -231,12 +228,12 @@ TidNext(TidScan *node) * ---------------------------------------------------------------- */ TupleTableSlot * -ExecTidScan(TidScan *node) +ExecTidScan(TidScanState *node) { /* * use TidNext as access method */ - return ExecScan(&node->scan, (ExecScanAccessMtd) TidNext); + return ExecScan(&node->ss, (ExecScanAccessMtd) TidNext); } /* ---------------------------------------------------------------- @@ -244,42 +241,30 @@ ExecTidScan(TidScan *node) * ---------------------------------------------------------------- */ void -ExecTidReScan(TidScan *node, ExprContext *exprCtxt, Plan *parent) +ExecTidReScan(TidScanState *node, ExprContext *exprCtxt) { EState *estate; - TidScanState *tidstate; ItemPointerData *tidList; + Index scanrelid; - estate = node->scan.plan.state; - tidstate = node->tidstate; - tidList = tidstate->tss_TidList; + estate = node->ss.ps.state; + tidList = node->tss_TidList; + scanrelid = ((TidScan *) node->ss.ps.plan)->scan.scanrelid; /* If we are being passed an outer tuple, save it for runtime key calc */ if (exprCtxt != NULL) - node->scan.scanstate->cstate.cs_ExprContext->ecxt_outertuple = + node->ss.ps.ps_ExprContext->ecxt_outertuple = exprCtxt->ecxt_outertuple; - /* do runtime calc of target TIDs, if needed */ - if (node->needRescan) - tidstate->tss_NumTids = - TidListCreate(node->tideval, - node->scan.scanstate->cstate.cs_ExprContext, - tidList); - /* If this is re-scanning of PlanQual ... */ if (estate->es_evTuple != NULL && - estate->es_evTuple[node->scan.scanrelid - 1] != NULL) + estate->es_evTuple[scanrelid - 1] != NULL) { - estate->es_evTupleNull[node->scan.scanrelid - 1] = false; + estate->es_evTupleNull[scanrelid - 1] = false; return; } - tidstate->tss_TidPtr = -1; - - /* - * perhaps return something meaningful - */ - return; + node->tss_TidPtr = -1; } /* ---------------------------------------------------------------- @@ -290,18 +275,13 @@ ExecTidReScan(TidScan *node, ExprContext *exprCtxt, Plan *parent) * ---------------------------------------------------------------- */ void -ExecEndTidScan(TidScan *node) +ExecEndTidScan(TidScanState *node) { - CommonScanState *scanstate; - TidScanState *tidstate; - /* * extract information from the node */ - scanstate = node->scan.scanstate; - tidstate = node->tidstate; - if (tidstate && tidstate->tss_TidList) - pfree(tidstate->tss_TidList); + if (node && node->tss_TidList) + pfree(node->tss_TidList); /* * Free the projection info and the scan attribute info @@ -310,8 +290,14 @@ ExecEndTidScan(TidScan *node) * depends on the tupType returned by ExecMain(). So for now, this is * freed at end-transaction time. -cim 6/2/91 */ - ExecFreeProjectionInfo(&scanstate->cstate); - ExecFreeExprContext(&scanstate->cstate); + ExecFreeProjectionInfo(&node->ss.ps); + ExecFreeExprContext(&node->ss.ps); + + /* + * clear out tuple table slots + */ + ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + ExecClearTuple(node->ss.ss_ScanTupleSlot); /* * close the heap relation. @@ -320,13 +306,7 @@ ExecEndTidScan(TidScan *node) * ExecInitTidScan. This lock should be held till end of transaction. * (There is a faction that considers this too much locking, however.) */ - heap_close(scanstate->css_currentRelation, NoLock); - - /* - * clear out tuple table slots - */ - ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot); - ExecClearTuple(scanstate->css_ScanTupleSlot); + heap_close(node->ss.ss_currentRelation, NoLock); } /* ---------------------------------------------------------------- @@ -337,12 +317,9 @@ ExecEndTidScan(TidScan *node) * ---------------------------------------------------------------- */ void -ExecTidMarkPos(TidScan *node) +ExecTidMarkPos(TidScanState *node) { - TidScanState *tidstate; - - tidstate = node->tidstate; - tidstate->tss_MarkTidPtr = tidstate->tss_TidPtr; + node->tss_MarkTidPtr = node->tss_TidPtr; } /* ---------------------------------------------------------------- @@ -355,12 +332,9 @@ ExecTidMarkPos(TidScan *node) * ---------------------------------------------------------------- */ void -ExecTidRestrPos(TidScan *node) +ExecTidRestrPos(TidScanState *node) { - TidScanState *tidstate; - - tidstate = node->tidstate; - tidstate->tss_TidPtr = tidstate->tss_MarkTidPtr; + node->tss_TidPtr = node->tss_MarkTidPtr; } /* ---------------------------------------------------------------- @@ -374,11 +348,10 @@ ExecTidRestrPos(TidScan *node) * estate: the execution state initialized in InitPlan. * ---------------------------------------------------------------- */ -bool -ExecInitTidScan(TidScan *node, EState *estate, Plan *parent) +TidScanState * +ExecInitTidScan(TidScan *node, EState *estate) { TidScanState *tidstate; - CommonScanState *scanstate; ItemPointerData *tidList; int numTids; int tidPtr; @@ -390,56 +363,50 @@ ExecInitTidScan(TidScan *node, EState *estate, Plan *parent) List *execParam = NIL; /* - * assign execution state to node + * create state structure */ - node->scan.plan.state = estate; + tidstate = makeNode(TidScanState); + tidstate->ss.ps.plan = (Plan *) node; + tidstate->ss.ps.state = estate; /* - * Part 1) initialize scan state + * Miscellaneous initialization * - * create new CommonScanState for node + * create expression context for node */ - scanstate = makeNode(CommonScanState); - node->scan.scanstate = scanstate; + ExecAssignExprContext(estate, &tidstate->ss.ps); /* - * Miscellaneous initialization - * - * create expression context for node + * initialize child expressions */ - ExecAssignExprContext(estate, &scanstate->cstate); + tidstate->ss.ps.targetlist = (List *) + ExecInitExpr((Node *) node->scan.plan.targetlist, + (PlanState *) tidstate); + tidstate->ss.ps.qual = (List *) + ExecInitExpr((Node *) node->scan.plan.qual, + (PlanState *) tidstate); #define TIDSCAN_NSLOTS 2 /* * tuple table initialization */ - ExecInitResultTupleSlot(estate, &scanstate->cstate); - ExecInitScanTupleSlot(estate, scanstate); + ExecInitResultTupleSlot(estate, &tidstate->ss.ps); + ExecInitScanTupleSlot(estate, &tidstate->ss); /* * initialize projection info. result type comes from scan desc * below.. */ - ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate); - - /* - * Part 2) initialize tid scan state - * - * create new TidScanState for node - */ - tidstate = makeNode(TidScanState); - node->tidstate = tidstate; + ExecAssignProjectionInfo(&tidstate->ss.ps); /* * get the tid node information */ tidList = (ItemPointerData *) palloc(length(node->tideval) * sizeof(ItemPointerData)); - numTids = 0; - if (!node->needRescan) - numTids = TidListCreate(node->tideval, - scanstate->cstate.cs_ExprContext, - tidList); + numTids = TidListCreate(node->tideval, + tidstate->ss.ps.ps_ExprContext, + tidList); tidPtr = -1; CXT1_printf("ExecInitTidScan: context is %d\n", CurrentMemoryContext); @@ -465,25 +432,25 @@ ExecInitTidScan(TidScan *node, EState *estate, Plan *parent) currentRelation = heap_open(reloid, AccessShareLock); - scanstate->css_currentRelation = currentRelation; - scanstate->css_currentScanDesc = NULL; /* no heap scan here */ + tidstate->ss.ss_currentRelation = currentRelation; + tidstate->ss.ss_currentScanDesc = NULL; /* no heap scan here */ /* * get the scan type from the relation descriptor. */ - ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false); - ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate); + ExecAssignScanType(&tidstate->ss, RelationGetDescr(currentRelation), false); + ExecAssignResultTypeFromTL(&tidstate->ss.ps); /* * if there are some PARAM_EXEC in skankeys then force tid rescan on * first scan. */ - ((Plan *) node)->chgParam = execParam; + tidstate->ss.ps.chgParam = execParam; /* * all done. */ - return TRUE; + return tidstate; } int diff --git a/src/backend/executor/nodeUnique.c b/src/backend/executor/nodeUnique.c index b71403de0b..88b08061f9 100644 --- a/src/backend/executor/nodeUnique.c +++ b/src/backend/executor/nodeUnique.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeUnique.c,v 1.34 2002/06/20 20:29:28 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeUnique.c,v 1.35 2002/12/05 15:50:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,7 +21,6 @@ * NOTES * Assumes tuples returned from subplan arrive in * sorted order. - * */ #include "postgres.h" @@ -39,21 +38,20 @@ * ---------------------------------------------------------------- */ TupleTableSlot * /* return: a tuple or NULL */ -ExecUnique(Unique *node) +ExecUnique(UniqueState *node) { - UniqueState *uniquestate; + Unique *plannode = (Unique *) node->ps.plan; TupleTableSlot *resultTupleSlot; TupleTableSlot *slot; - Plan *outerPlan; + PlanState *outerPlan; TupleDesc tupDesc; /* * get information from the node */ - uniquestate = node->uniquestate; - outerPlan = outerPlan((Plan *) node); - resultTupleSlot = uniquestate->cstate.cs_ResultTupleSlot; - tupDesc = ExecGetResultType(&uniquestate->cstate); + outerPlan = outerPlanState(node); + resultTupleSlot = node->ps.ps_ResultTupleSlot; + tupDesc = ExecGetResultType(&node->ps); /* * now loop, returning only non-duplicate tuples. We assume that the @@ -64,14 +62,14 @@ ExecUnique(Unique *node) /* * fetch a tuple from the outer subplan */ - slot = ExecProcNode(outerPlan, (Plan *) node); + slot = ExecProcNode(outerPlan); if (TupIsNull(slot)) return NULL; /* * Always return the first tuple from the subplan. */ - if (uniquestate->priorTuple == NULL) + if (node->priorTuple == NULL) break; /* @@ -79,11 +77,11 @@ ExecUnique(Unique *node) * match. If so then we loop back and fetch another new tuple * from the subplan. */ - if (!execTuplesMatch(slot->val, uniquestate->priorTuple, + if (!execTuplesMatch(slot->val, node->priorTuple, tupDesc, - node->numCols, node->uniqColIdx, - uniquestate->eqfunctions, - uniquestate->tempContext)) + plannode->numCols, plannode->uniqColIdx, + node->eqfunctions, + node->tempContext)) break; } @@ -99,11 +97,11 @@ ExecUnique(Unique *node) * handling in execMain.c). We assume that the caller will no longer * be interested in the current tuple after he next calls us. */ - if (uniquestate->priorTuple != NULL) - heap_freetuple(uniquestate->priorTuple); - uniquestate->priorTuple = heap_copytuple(slot->val); + if (node->priorTuple != NULL) + heap_freetuple(node->priorTuple); + node->priorTuple = heap_copytuple(slot->val); - ExecStoreTuple(uniquestate->priorTuple, + ExecStoreTuple(node->priorTuple, resultTupleSlot, InvalidBuffer, false); /* tuple does not belong to slot */ @@ -118,22 +116,18 @@ ExecUnique(Unique *node) * the node's subplan. * ---------------------------------------------------------------- */ -bool /* return: initialization status */ -ExecInitUnique(Unique *node, EState *estate, Plan *parent) +UniqueState * +ExecInitUnique(Unique *node, EState *estate) { UniqueState *uniquestate; - Plan *outerPlan; /* - * assign execution state to node - */ - node->plan.state = estate; - - /* - * create new UniqueState for node + * create state structure */ uniquestate = makeNode(UniqueState); - node->uniquestate = uniquestate; + uniquestate->ps.plan = (Plan *) node; + uniquestate->ps.state = estate; + uniquestate->priorTuple = NULL; /* @@ -155,30 +149,29 @@ ExecInitUnique(Unique *node, EState *estate, Plan *parent) /* * Tuple table initialization */ - ExecInitResultTupleSlot(estate, &uniquestate->cstate); + ExecInitResultTupleSlot(estate, &uniquestate->ps); /* * then initialize outer plan */ - outerPlan = outerPlan((Plan *) node); - ExecInitNode(outerPlan, estate, (Plan *) node); + outerPlanState(uniquestate) = ExecInitNode(outerPlan(node), estate); /* * unique nodes do no projections, so initialize projection info for * this node appropriately */ - ExecAssignResultTypeFromOuterPlan((Plan *) node, &uniquestate->cstate); - uniquestate->cstate.cs_ProjInfo = NULL; + ExecAssignResultTypeFromOuterPlan(&uniquestate->ps); + uniquestate->ps.ps_ProjInfo = NULL; /* * Precompute fmgr lookup data for inner loop */ uniquestate->eqfunctions = - execTuplesMatchPrepare(ExecGetResultType(&uniquestate->cstate), + execTuplesMatchPrepare(ExecGetResultType(&uniquestate->ps), node->numCols, node->uniqColIdx); - return TRUE; + return uniquestate; } int @@ -197,41 +190,36 @@ ExecCountSlotsUnique(Unique *node) * ---------------------------------------------------------------- */ void -ExecEndUnique(Unique *node) +ExecEndUnique(UniqueState *node) { - UniqueState *uniquestate = node->uniquestate; - - ExecEndNode(outerPlan((Plan *) node), (Plan *) node); - - MemoryContextDelete(uniquestate->tempContext); - /* clean up tuple table */ - ExecClearTuple(uniquestate->cstate.cs_ResultTupleSlot); - if (uniquestate->priorTuple != NULL) + ExecClearTuple(node->ps.ps_ResultTupleSlot); + if (node->priorTuple != NULL) { - heap_freetuple(uniquestate->priorTuple); - uniquestate->priorTuple = NULL; + heap_freetuple(node->priorTuple); + node->priorTuple = NULL; } + + ExecEndNode(outerPlanState(node)); + + MemoryContextDelete(node->tempContext); } void -ExecReScanUnique(Unique *node, ExprContext *exprCtxt, Plan *parent) +ExecReScanUnique(UniqueState *node, ExprContext *exprCtxt) { - UniqueState *uniquestate = node->uniquestate; - - ExecClearTuple(uniquestate->cstate.cs_ResultTupleSlot); - if (uniquestate->priorTuple != NULL) + ExecClearTuple(node->ps.ps_ResultTupleSlot); + if (node->priorTuple != NULL) { - heap_freetuple(uniquestate->priorTuple); - uniquestate->priorTuple = NULL; + heap_freetuple(node->priorTuple); + node->priorTuple = NULL; } /* * if chgParam of subnode is not null then plan will be re-scanned by * first ExecProcNode. */ - if (((Plan *) node)->lefttree->chgParam == NULL) - ExecReScan(((Plan *) node)->lefttree, exprCtxt, (Plan *) node); - + if (((PlanState *) node)->lefttree->chgParam == NULL) + ExecReScan(((PlanState *) node)->lefttree, exprCtxt); } diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index 6e897e423e..147becf6ed 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.78 2002/11/13 00:39:47 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.79 2002/12/05 15:50:34 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -33,7 +33,7 @@ static int _SPI_connected = -1; static int _SPI_curid = -1; static int _SPI_execute(char *src, int tcount, _SPI_plan *plan); -static int _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount); +static int _SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount); static int _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount); @@ -705,9 +705,8 @@ SPI_cursor_open(char *name, void *plan, Datum *Values, char *Nulls) List *ptlist = spiplan->ptlist; Query *queryTree; Plan *planTree; + ParamListInfo paramLI; QueryDesc *queryDesc; - EState *eState; - TupleDesc attinfo; MemoryContext oldcontext; Portal portal; char portalname[64]; @@ -774,28 +773,21 @@ SPI_cursor_open(char *name, void *plan, Datum *Values, char *Nulls) queryTree->into->relname = pstrdup(name); queryTree->isBinary = false; - /* Create the QueryDesc object and the executor state */ - queryDesc = CreateQueryDesc(queryTree, planTree, SPI, NULL); - eState = CreateExecutorState(); - - /* If the plan has parameters, put them into the executor state */ + /* If the plan has parameters, set them up */ if (spiplan->nargs > 0) { - ParamListInfo paramLI; - paramLI = (ParamListInfo) palloc0((spiplan->nargs + 1) * - sizeof(ParamListInfoData)); + sizeof(ParamListInfoData)); - eState->es_param_list_info = paramLI; - for (k = 0; k < spiplan->nargs; paramLI++, k++) + for (k = 0; k < spiplan->nargs; k++) { - paramLI->kind = PARAM_NUM; - paramLI->id = k + 1; - paramLI->isnull = (Nulls && Nulls[k] == 'n'); - if (paramLI->isnull) + paramLI[k].kind = PARAM_NUM; + paramLI[k].id = k + 1; + paramLI[k].isnull = (Nulls && Nulls[k] == 'n'); + if (paramLI[k].isnull) { /* nulls just copy */ - paramLI->value = Values[k]; + paramLI[k].value = Values[k]; } else { @@ -805,20 +797,24 @@ SPI_cursor_open(char *name, void *plan, Datum *Values, char *Nulls) get_typlenbyval(spiplan->argtypes[k], ¶mTypLen, ¶mTypByVal); - paramLI->value = datumCopy(Values[k], - paramTypByVal, paramTypLen); + paramLI[k].value = datumCopy(Values[k], + paramTypByVal, paramTypLen); } } - paramLI->kind = PARAM_INVALID; + paramLI[k].kind = PARAM_INVALID; } else - eState->es_param_list_info = NULL; + paramLI = NULL; + + /* Create the QueryDesc object */ + queryDesc = CreateQueryDesc(queryTree, planTree, SPI, NULL, + paramLI, false); /* Start the executor */ - attinfo = ExecutorStart(queryDesc, eState); + ExecutorStart(queryDesc); - /* Put all the objects into the portal */ - PortalSetQuery(portal, queryDesc, attinfo, eState, PortalCleanup); + /* Arrange to shut down the executor if portal is dropped */ + PortalSetQuery(portal, queryDesc, PortalCleanup); /* Switch back to the callers memory context */ MemoryContextSwitchTo(oldcontext); @@ -1042,7 +1038,6 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan) Plan *planTree; bool canSetResult; QueryDesc *qdesc; - EState *state; planTree = pg_plan_query(queryTree); plan_list = lappend(plan_list, planTree); @@ -1089,9 +1084,9 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan) else if (plan == NULL) { qdesc = CreateQueryDesc(queryTree, planTree, - canSetResult ? SPI : None, NULL); - state = CreateExecutorState(); - res = _SPI_pquery(qdesc, state, canSetResult ? tcount : 0); + canSetResult ? SPI : None, + NULL, NULL, false); + res = _SPI_pquery(qdesc, true, canSetResult ? tcount : 0); if (res < 0) return res; CommandCounterIncrement(); @@ -1099,8 +1094,9 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan) else { qdesc = CreateQueryDesc(queryTree, planTree, - canSetResult ? SPI : None, NULL); - res = _SPI_pquery(qdesc, NULL, 0); + canSetResult ? SPI : None, + NULL, NULL, false); + res = _SPI_pquery(qdesc, false, 0); if (res < 0) return res; } @@ -1152,7 +1148,6 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount) Plan *planTree; bool canSetResult; QueryDesc *qdesc; - EState *state; planTree = lfirst(plan_list); plan_list = lnext(plan_list); @@ -1183,30 +1178,31 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount) } else { - qdesc = CreateQueryDesc(queryTree, planTree, - canSetResult ? SPI : None, NULL); - state = CreateExecutorState(); + ParamListInfo paramLI; + if (nargs > 0) { - ParamListInfo paramLI; int k; paramLI = (ParamListInfo) palloc0((nargs + 1) * sizeof(ParamListInfoData)); - state->es_param_list_info = paramLI; - for (k = 0; k < plan->nargs; paramLI++, k++) + for (k = 0; k < plan->nargs; k++) { - paramLI->kind = PARAM_NUM; - paramLI->id = k + 1; - paramLI->isnull = (Nulls && Nulls[k] == 'n'); - paramLI->value = Values[k]; + paramLI[k].kind = PARAM_NUM; + paramLI[k].id = k + 1; + paramLI[k].isnull = (Nulls && Nulls[k] == 'n'); + paramLI[k].value = Values[k]; } - paramLI->kind = PARAM_INVALID; + paramLI[k].kind = PARAM_INVALID; } else - state->es_param_list_info = NULL; - res = _SPI_pquery(qdesc, state, canSetResult ? tcount : 0); + paramLI = NULL; + + qdesc = CreateQueryDesc(queryTree, planTree, + canSetResult ? SPI : None, + NULL, paramLI, false); + res = _SPI_pquery(qdesc, true, canSetResult ? tcount : 0); if (res < 0) return res; CommandCounterIncrement(); @@ -1218,7 +1214,7 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount) } static int -_SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount) +_SPI_pquery(QueryDesc *queryDesc, bool runit, int tcount) { Query *parseTree = queryDesc->parsetree; int operation = queryDesc->operation; @@ -1262,7 +1258,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount) return SPI_ERROR_OPUNKNOWN; } - if (state == NULL) /* plan preparation, don't execute */ + if (!runit) /* plan preparation, don't execute */ return res; #ifdef SPI_EXECUTOR_STATS @@ -1270,20 +1266,20 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount) ResetUsage(); #endif - ExecutorStart(queryDesc, state); + ExecutorStart(queryDesc); /* * Don't work currently --- need to rearrange callers so that we - * prepare the portal before doing CreateExecutorState() etc. See + * prepare the portal before doing ExecutorStart() etc. See * pquery.c for the correct order of operations. */ if (isRetrieveIntoPortal) elog(FATAL, "SPI_select: retrieve into portal not implemented"); - ExecutorRun(queryDesc, state, ForwardScanDirection, (long) tcount); + ExecutorRun(queryDesc, ForwardScanDirection, (long) tcount); - _SPI_current->processed = state->es_processed; - save_lastoid = state->es_lastoid; + _SPI_current->processed = queryDesc->estate->es_processed; + save_lastoid = queryDesc->estate->es_lastoid; if (operation == CMD_SELECT && queryDesc->dest == SPI) { @@ -1291,7 +1287,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount) elog(FATAL, "SPI_select: # of processed tuples check failed"); } - ExecutorEnd(queryDesc, state); + ExecutorEnd(queryDesc); #ifdef SPI_EXECUTOR_STATS if (ShowExecutorStats) @@ -1342,7 +1338,7 @@ _SPI_cursor_operation(Portal portal, bool forward, int count, oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal)); querydesc = PortalGetQueryDesc(portal); - estate = PortalGetState(portal); + estate = querydesc->estate; /* Save the queries command destination and set it to SPI (for fetch) */ /* or None (for move) */ @@ -1357,7 +1353,7 @@ _SPI_cursor_operation(Portal portal, bool forward, int count, else direction = ForwardScanDirection; - ExecutorRun(querydesc, estate, direction, (long) count); + ExecutorRun(querydesc, direction, (long) count); if (estate->es_processed > 0) portal->atStart = false; /* OK to back up now */ @@ -1371,7 +1367,7 @@ _SPI_cursor_operation(Portal portal, bool forward, int count, else direction = BackwardScanDirection; - ExecutorRun(querydesc, estate, direction, (long) count); + ExecutorRun(querydesc, direction, (long) count); if (estate->es_processed > 0) portal->atEnd = false; /* OK to go forward now */ diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index d11b5ed201..1fe7efd163 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -3,27 +3,28 @@ * copyfuncs.c * Copy functions for Postgres tree nodes. * - * NOTE: a general convention when copying or comparing plan nodes is - * that we ignore the executor state subnode. We do not need to look - * at it because no current uses of copyObject() or equal() need to - * deal with already-executing plan trees. By leaving the state subnodes - * out, we avoid needing to write copy/compare routines for all the - * different executor state node types. + * NOTE: we currently support copying all node types found in parse and + * plan trees. We do not support copying executor state trees; there + * is no need for that, and no point in maintaining all the code that + * would be needed. We also do not support copying Path trees, mainly + * because the circular linkages between RelOptInfo and Path nodes can't + * be handled easily in a simple depth-first traversal. * * * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/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 "optimizer/clauses.h" -#include "optimizer/planmain.h" +#include "nodes/parsenodes.h" +#include "nodes/plannodes.h" +#include "nodes/relation.h" #include "utils/datum.h" @@ -58,15 +59,6 @@ memcpy(newnode->fldname, from->fldname, _size); \ } 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 @@ -119,19 +111,13 @@ CopyPlanFields(Plan *from, Plan *newnode) COPY_SCALAR_FIELD(total_cost); COPY_SCALAR_FIELD(plan_rows); COPY_SCALAR_FIELD(plan_width); - /* execution state is NOT copied */ COPY_NODE_FIELD(targetlist); COPY_NODE_FIELD(qual); COPY_NODE_FIELD(lefttree); COPY_NODE_FIELD(righttree); + COPY_NODE_FIELD(initPlan); COPY_INTLIST_FIELD(extParam); 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); } @@ -170,9 +156,6 @@ _copyResult(Result *from) */ 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; } @@ -266,10 +249,6 @@ _copyIndexScan(IndexScan *from) COPY_NODE_FIELD(indxqualorig); 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; } @@ -289,12 +268,8 @@ _copyTidScan(TidScan *from) /* * copy remainder of node */ - COPY_SCALAR_FIELD(needRescan); 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; } @@ -348,9 +323,6 @@ CopyJoinFields(Join *from, Join *newnode) COPY_SCALAR_FIELD(jointype); 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) */ 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; } @@ -430,9 +399,6 @@ _copyHashJoin(HashJoin *from) */ 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; } @@ -531,12 +497,12 @@ _copyUnique(Unique *from) } /* - * _copySetOp + * _copyHash */ -static SetOp * -_copySetOp(SetOp *from) +static Hash * +_copyHash(Hash *from) { - SetOp *newnode = makeNode(SetOp); + Hash *newnode = makeNode(Hash); /* * copy node superclass fields @@ -546,21 +512,18 @@ _copySetOp(SetOp *from) /* * copy remainder of node */ - COPY_SCALAR_FIELD(cmd); - COPY_SCALAR_FIELD(numCols); - COPY_POINTER_FIELD(dupColIdx, from->numCols * sizeof(AttrNumber)); - COPY_SCALAR_FIELD(flagColIdx); + COPY_NODE_FIELD(hashkeys); return newnode; } /* - * _copyLimit + * _copySetOp */ -static Limit * -_copyLimit(Limit *from) +static SetOp * +_copySetOp(SetOp *from) { - Limit *newnode = makeNode(Limit); + SetOp *newnode = makeNode(SetOp); /* * copy node superclass fields @@ -570,19 +533,21 @@ _copyLimit(Limit *from) /* * copy remainder of node */ - COPY_NODE_FIELD(limitOffset); - COPY_NODE_FIELD(limitCount); + COPY_SCALAR_FIELD(cmd); + COPY_SCALAR_FIELD(numCols); + COPY_POINTER_FIELD(dupColIdx, from->numCols * sizeof(AttrNumber)); + COPY_SCALAR_FIELD(flagColIdx); return newnode; } /* - * _copyHash + * _copyLimit */ -static Hash * -_copyHash(Hash *from) +static Limit * +_copyLimit(Limit *from) { - Hash *newnode = makeNode(Hash); + Limit *newnode = makeNode(Limit); /* * copy node superclass fields @@ -592,9 +557,8 @@ _copyHash(Hash *from) /* * copy remainder of node */ - COPY_NODE_FIELD(hashkeys); - - /* XXX could the hashkeys contain subplans? Not at present... */ + COPY_NODE_FIELD(limitOffset); + COPY_NODE_FIELD(limitCount); return newnode; } @@ -611,10 +575,6 @@ _copySubPlan(SubPlan *from) COPY_INTLIST_FIELD(parParam); COPY_NODE_FIELD(sublink); - /* do not copy execution state */ - newnode->needShutdown = false; - newnode->curTuple = NULL; - return newnode; } @@ -933,314 +893,12 @@ _copyArrayRef(ArrayRef *from) /* **************************************************************** * relation.h copy functions * - * XXX the code to copy RelOptInfo and Path nodes is really completely bogus, - * because it makes no attempt to deal with multiple links from RelOptInfo - * 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. + * We don't support copying RelOptInfo, IndexOptInfo, or Path nodes. + * There are some subsidiary structs that are useful to copy, though. * **************************************************************** */ /* - * _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 */ static PathKeyItem * @@ -1301,21 +959,6 @@ _copyJoinInfo(JoinInfo *from) 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 * **************************************************************** @@ -1737,7 +1380,8 @@ _copyQuery(Query *from) /* * We do not copy the planner internal fields: base_rel_list, * 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; @@ -2683,15 +2327,15 @@ copyObject(void *from) case T_Unique: retval = _copyUnique(from); break; + case T_Hash: + retval = _copyHash(from); + break; case T_SetOp: retval = _copySetOp(from); break; case T_Limit: retval = _copyLimit(from); break; - case T_Hash: - retval = _copyHash(from); - break; case T_SubPlan: retval = _copySubPlan(from); break; @@ -2757,39 +2401,6 @@ copyObject(void *from) /* * 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: retval = _copyPathKeyItem(from); break; @@ -2799,9 +2410,6 @@ copyObject(void *from) case T_JoinInfo: retval = _copyJoinInfo(from); break; - case T_InnerIndexscanInfo: - retval = _copyInnerIndexscanInfo(from); - break; /* * VALUE NODES diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index c5a492db89..f2cae4c14f 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -3,30 +3,30 @@ * equalfuncs.c * Equality functions to compare node trees. * - * NOTE: a general convention when copying or comparing plan nodes is - * that we ignore the executor state subnode. We do not need to look - * at it because no current uses of copyObject() or equal() need to - * deal with already-executing plan trees. By leaving the state subnodes - * out, we avoid needing to write copy/compare routines for all the - * different executor state node types. + * NOTE: we currently support comparing all node types found in parse + * trees. We do not support comparing executor state trees; there + * is no need for that, and no point in maintaining all the code that + * would be needed. We also do not support comparing Path trees, mainly + * because the circular linkages between RelOptInfo and Path nodes can't + * be handled easily in a simple depth-first traversal. * - * Currently, in fact, equal() doesn't know how to compare Plan nodes - * at all, let alone their executor-state subnodes. This will probably - * need to be fixed someday, but presently there is no need to compare - * plan trees. + * Currently, in fact, equal() doesn't know how to compare Plan trees + * either. This might need to be fixed someday. * * * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/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 "nodes/params.h" +#include "nodes/parsenodes.h" #include "nodes/plannodes.h" #include "nodes/relation.h" #include "utils/datum.h" @@ -370,147 +370,6 @@ _equalSubPlan(SubPlan *a, SubPlan *b) */ 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 _equalPathKeyItem(PathKeyItem *a, PathKeyItem *b) { COMPARE_NODE_FIELD(key); @@ -547,16 +406,6 @@ _equalJoinInfo(JoinInfo *a, JoinInfo *b) 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 @@ -1711,39 +1560,6 @@ equal(void *a, void *b) retval = _equalJoinExpr(a, b); 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: retval = _equalPathKeyItem(a, b); break; @@ -1753,9 +1569,6 @@ equal(void *a, void *b) case T_JoinInfo: retval = _equalJoinInfo(a, b); break; - case T_InnerIndexscanInfo: - retval = _equalInnerIndexscanInfo(a, b); - break; case T_List: { diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 3a074339f4..2c254001ee 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -8,13 +8,13 @@ * * * 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 * Every node type that can appear in stored rules' parsetrees *must* * have an output function defined here (as well as an input function * 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. * *------------------------------------------------------------------------- @@ -24,10 +24,8 @@ #include #include "lib/stringinfo.h" -#include "nodes/nodes.h" #include "nodes/parsenodes.h" #include "nodes/plannodes.h" -#include "nodes/primnodes.h" #include "nodes/relation.h" #include "parser/parse.h" #include "utils/datum.h" @@ -385,11 +383,9 @@ _outPlanInfo(StringInfo str, Plan *node) WRITE_NODE_FIELD(qual); WRITE_NODE_FIELD(lefttree); WRITE_NODE_FIELD(righttree); + WRITE_NODE_FIELD(initPlan); WRITE_INTLIST_FIELD(extParam); 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); } @@ -482,7 +478,6 @@ _outTidScan(StringInfo str, TidScan *node) _outScanInfo(str, (Scan *) node); - WRITE_BOOL_FIELD(needRescan); WRITE_NODE_FIELD(tideval); } @@ -930,6 +925,8 @@ _outRangeTblEntry(StringInfo str, RangeTblEntry *node) /* * 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 _outPathInfo(StringInfo str, Path *node) @@ -986,7 +983,6 @@ _outTidPath(StringInfo str, TidPath *node) _outPathInfo(str, (Path *) node); WRITE_NODE_FIELD(tideval); - WRITE_INTLIST_FIELD(unjoined_relids); } static void diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 148bd86b85..0414fdf2f3 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -10,7 +10,7 @@ * * * 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) scan_relid, best_path->tideval); - if (best_path->unjoined_relids) - scan_plan->needRescan = true; - copy_path_costsize(&scan_plan->scan.plan, &best_path->path); return scan_plan; @@ -1302,13 +1299,11 @@ make_seqscan(List *qptlist, Plan *plan = &node->plan; /* cost should be inserted by caller */ - plan->state = (EState *) NULL; plan->targetlist = qptlist; plan->qual = qpqual; plan->lefttree = NULL; plan->righttree = NULL; node->scanrelid = scanrelid; - node->scanstate = (CommonScanState *) NULL; return node; } @@ -1326,7 +1321,6 @@ make_indexscan(List *qptlist, Plan *plan = &node->scan.plan; /* cost should be inserted by caller */ - plan->state = (EState *) NULL; plan->targetlist = qptlist; plan->qual = qpqual; plan->lefttree = NULL; @@ -1336,7 +1330,6 @@ make_indexscan(List *qptlist, node->indxqual = indxqual; node->indxqualorig = indxqualorig; node->indxorderdir = indexscandir; - node->scan.scanstate = (CommonScanState *) NULL; return node; } @@ -1351,16 +1344,12 @@ make_tidscan(List *qptlist, Plan *plan = &node->scan.plan; /* cost should be inserted by caller */ - plan->state = (EState *) NULL; plan->targetlist = qptlist; plan->qual = qpqual; plan->lefttree = NULL; plan->righttree = NULL; node->scan.scanrelid = scanrelid; - node->tideval = copyObject(tideval); /* XXX do we really need a - * copy? */ - node->needRescan = false; - node->scan.scanstate = (CommonScanState *) NULL; + node->tideval = tideval; return node; } @@ -1375,14 +1364,12 @@ make_subqueryscan(List *qptlist, Plan *plan = &node->scan.plan; copy_plan_costsize(plan, subplan); - plan->state = (EState *) NULL; plan->targetlist = qptlist; plan->qual = qpqual; plan->lefttree = NULL; plan->righttree = NULL; node->scan.scanrelid = scanrelid; node->subplan = subplan; - node->scan.scanstate = (CommonScanState *) NULL; return node; } @@ -1396,13 +1383,11 @@ make_functionscan(List *qptlist, Plan *plan = &node->scan.plan; /* cost should be inserted by caller */ - plan->state = (EState *) NULL; plan->targetlist = qptlist; plan->qual = qpqual; plan->lefttree = NULL; plan->righttree = NULL; node->scan.scanrelid = scanrelid; - node->scan.scanstate = (CommonScanState *) NULL; return node; } @@ -1430,7 +1415,6 @@ make_append(List *appendplans, bool isTarget, List *tlist) if (plan->plan_width < subplan->plan_width) plan->plan_width = subplan->plan_width; } - plan->state = (EState *) NULL; plan->targetlist = tlist; plan->qual = NIL; plan->lefttree = NULL; @@ -1453,7 +1437,6 @@ make_nestloop(List *tlist, Plan *plan = &node->join.plan; /* cost should be inserted by caller */ - plan->state = (EState *) NULL; plan->targetlist = tlist; plan->qual = otherclauses; plan->lefttree = lefttree; @@ -1477,7 +1460,6 @@ make_hashjoin(List *tlist, Plan *plan = &node->join.plan; /* cost should be inserted by caller */ - plan->state = (EState *) NULL; plan->targetlist = tlist; plan->qual = otherclauses; plan->lefttree = lefttree; @@ -1502,7 +1484,6 @@ make_hash(List *tlist, List *hashkeys, Plan *lefttree) * input plan; this only affects EXPLAIN display not decisions. */ plan->startup_cost = plan->total_cost; - plan->state = (EState *) NULL; plan->targetlist = tlist; plan->qual = NULL; plan->lefttree = lefttree; @@ -1525,7 +1506,6 @@ make_mergejoin(List *tlist, Plan *plan = &node->join.plan; /* cost should be inserted by caller */ - plan->state = (EState *) NULL; plan->targetlist = tlist; plan->qual = otherclauses; plan->lefttree = lefttree; @@ -1557,7 +1537,6 @@ make_sort(Query *root, List *tlist, Plan *lefttree, int keycount) lefttree->plan_width); plan->startup_cost = sort_path.startup_cost; plan->total_cost = sort_path.total_cost; - plan->state = (EState *) NULL; plan->targetlist = tlist; plan->qual = NIL; plan->lefttree = lefttree; @@ -1646,7 +1625,6 @@ make_material(List *tlist, Plan *lefttree) Plan *plan = &node->plan; /* cost should be inserted by caller */ - plan->state = (EState *) NULL; plan->targetlist = tlist; plan->qual = NIL; plan->lefttree = lefttree; @@ -1690,7 +1668,6 @@ make_agg(Query *root, List *tlist, List *qual, else plan->plan_rows = numGroups; - plan->state = (EState *) NULL; plan->qual = qual; plan->targetlist = tlist; plan->lefttree = lefttree; @@ -1726,7 +1703,6 @@ make_group(Query *root, /* One output tuple per estimated result group */ plan->plan_rows = numGroups; - plan->state = (EState *) NULL; plan->qual = NULL; plan->targetlist = tlist; plan->lefttree = lefttree; @@ -1765,7 +1741,6 @@ make_unique(List *tlist, Plan *lefttree, List *distinctList) * if he has a better idea. */ - plan->state = (EState *) NULL; plan->targetlist = tlist; plan->qual = NIL; plan->lefttree = lefttree; @@ -1824,7 +1799,6 @@ make_setop(SetOpCmd cmd, List *tlist, Plan *lefttree, if (plan->plan_rows < 1) plan->plan_rows = 1; - plan->state = (EState *) NULL; plan->targetlist = tlist; plan->qual = NIL; plan->lefttree = lefttree; @@ -1905,7 +1879,6 @@ make_limit(List *tlist, Plan *lefttree, } } - plan->state = (EState *) NULL; plan->targetlist = tlist; plan->qual = NIL; plan->lefttree = lefttree; @@ -1935,13 +1908,11 @@ make_result(List *tlist, plan->plan_width = 0; /* XXX try to be smarter? */ } - plan->state = (EState *) NULL; plan->targetlist = tlist; plan->qual = NIL; plan->lefttree = subplan; plan->righttree = NULL; node->resconstantqual = resconstantqual; - node->resstate = NULL; return node; } diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index 3db73e87f0..b23843a030 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -9,7 +9,7 @@ * * * 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 } replace_vars_with_subplan_refs_context; 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_uppernode_references(Plan *plan, Index subvarno); static Node *join_references_mutator(Node *node, @@ -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 * 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). - * 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. * @@ -82,12 +81,6 @@ set_plan_references(Plan *plan, List *rtable) 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 */ switch (nodeTag(plan)) @@ -107,6 +100,8 @@ set_plan_references(Plan *plan, List *rtable) case T_TidScan: fix_expr_references(plan, (Node *) plan->targetlist); fix_expr_references(plan, (Node *) plan->qual); + fix_expr_references(plan, + (Node *) ((TidScan *) plan)->tideval); break; case T_SubqueryScan: { @@ -175,9 +170,9 @@ set_plan_references(Plan *plan, List *rtable) * unmodified input tuples). The optimizer is lazy about * creating really valid targetlists for them. Best to just * leave the targetlist alone. In particular, we do not want - * to pull a subplan list for them, since we will likely end - * up with duplicate list entries for subplans that also - * appear in lower levels of the plan tree! + * to process subplans for them, since we will likely end + * up reprocessing subplans that also appear in lower levels + * of the plan tree! */ break; case T_Agg: @@ -206,7 +201,7 @@ set_plan_references(Plan *plan, List *rtable) * Append, like Sort et al, doesn't actually evaluate its * targetlist or quals, and we haven't bothered to give it its * own tlist copy. So, don't fix targetlist/qual. But do - * recurse into subplans. + * recurse into child plans. */ foreach(pl, ((Append *) plan)->appendplans) set_plan_references((Plan *) lfirst(pl), 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 * reference-adjustments bottom-up, then we would fail to match this * 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->righttree, rtable); - foreach(pl, plan->initPlan) - { - SubPlan *sp = (SubPlan *) lfirst(pl); - Assert(IsA(sp, SubPlan)); - set_plan_references(sp->plan, sp->rtable); - } - foreach(pl, plan->subPlan) + foreach(pl, plan->initPlan) { SubPlan *sp = (SubPlan *) lfirst(pl); @@ -249,13 +239,38 @@ set_plan_references(Plan *plan, List *rtable) * Do final cleanup on expressions (targetlists or quals). * * 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 fix_expr_references(Plan *plan, Node *node) { - fix_opids(node); - plan->subPlan = nconc(plan->subPlan, pull_subplans(node)); + /* This tree walk requires no special setup, so away we go... */ + 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); } /* diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index e4bbd29105..a65de72c90 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * 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 @@ #include "catalog/pg_operator.h" #include "catalog/pg_type.h" #include "nodes/makefuncs.h" +#include "nodes/params.h" #include "optimizer/clauses.h" #include "optimizer/cost.h" #include "optimizer/planmain.h" @@ -297,7 +298,7 @@ make_subplan(SubLink *slink) switch (nodeTag(plan)) { case T_SeqScan: - if (plan->initPlan || plan->subPlan) + if (plan->initPlan) use_material = true; else { @@ -453,20 +454,13 @@ convert_sublink_opers(SubLink *slink, List *targetlist, } /* - * finalize_primnode: build lists of subplans and params appearing - * in the given expression tree. NOTE: items are added to lists passed in, - * so caller must initialize lists 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. + * finalize_primnode: build lists of params appearing + * in the given expression tree. NOTE: items are added to list passed in, + * so caller must initialize list to NIL before first call! */ typedef struct finalize_primnode_results { - List *subplans; /* List of subplans found in expr */ List *paramids; /* List of PARAM_EXEC paramids found */ } finalize_primnode_results; @@ -491,8 +485,6 @@ finalize_primnode(Node *node, finalize_primnode_results *results) SubPlan *subplan = (SubPlan *) ((Expr *) node)->oper; List *lst; - /* Add subplan to subplans list */ - results->subplans = lappend(results->subplans, subplan); /* Check extParam list for params to add to paramids */ foreach(lst, subplan->plan->extParam) { @@ -595,18 +587,16 @@ SS_finalize_plan(Plan *plan, List *rtable) if (plan == NULL) return NIL; - results.subplans = NIL; /* initialize lists to NIL */ - results.paramids = NIL; + results.paramids = NIL; /* initialize list to NIL */ /* * When we call finalize_primnode, results.paramids lists are * automatically merged together. But when recursing to self, we have * 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 - * subplans of subplans, though.) + * in subplans as well as at this level. */ - /* Find params and subplans in targetlist and qual */ + /* Find params in targetlist and qual */ finalize_primnode((Node *) plan->targetlist, &results); finalize_primnode((Node *) plan->qual, &results); @@ -624,8 +614,7 @@ SS_finalize_plan(Plan *plan, List *rtable) /* * we need not look at indxqualorig, since it will have the - * same param references as indxqual, and we aren't really - * concerned yet about having a complete subplan list. + * same param references as indxqual. */ break; @@ -704,7 +693,7 @@ SS_finalize_plan(Plan *plan, List *rtable) nodeTag(plan)); } - /* Process left and right subplans, if any */ + /* Process left and right child plans, if any */ results.paramids = set_unioni(results.paramids, SS_finalize_plan(plan->lefttree, rtable)); @@ -712,7 +701,7 @@ SS_finalize_plan(Plan *plan, List *rtable) SS_finalize_plan(plan->righttree, rtable)); - /* Now we have all the paramids and subplans */ + /* Now we have all the paramids */ foreach(lst, results.paramids) { @@ -733,7 +722,6 @@ SS_finalize_plan(Plan *plan, List *rtable) plan->extParam = extParam; plan->locParam = locParam; - plan->subPlan = results.subplans; return results.paramids; } diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index 84896b939f..615d996697 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -8,7 +8,7 @@ * * * 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) pathnode->path.pathtype = T_TidScan; pathnode->path.parent = rel; pathnode->path.pathkeys = NIL; - pathnode->tideval = copyObject(tideval); /* is copy really - * necessary? */ - pathnode->unjoined_relids = NIL; + pathnode->tideval = tideval; cost_tidscan(&pathnode->path, root, rel, tideval); diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c index 0919b03f45..24d4aac8b2 100644 --- a/src/backend/tcop/pquery.c +++ b/src/backend/tcop/pquery.c @@ -8,7 +8,7 @@ * * * 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 @@ #include "utils/ps_status.h" -/* ---------------------------------------------------------------- - * CreateQueryDesc - * ---------------------------------------------------------------- +/* + * CreateQueryDesc */ QueryDesc * CreateQueryDesc(Query *parsetree, Plan *plantree, CommandDest dest, - const char *portalName) + const char *portalName, + ParamListInfo params, + bool doInstrument) { QueryDesc *qd = (QueryDesc *) palloc(sizeof(QueryDesc)); @@ -40,54 +41,15 @@ CreateQueryDesc(Query *parsetree, qd->plantree = plantree; /* plan */ qd->dest = dest; /* output dest */ qd->portalName = portalName; /* name, if dest is a portal */ - qd->tupDesc = NULL; /* until set by ExecutorStart */ - - 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; + qd->params = params; /* parameter values passed into query */ + qd->doInstrument = doInstrument; /* instrumentation wanted? */ - state->es_per_tuple_exprcontext = NULL; + /* null these fields until set by ExecutorStart */ + qd->tupDesc = NULL; + qd->estate = NULL; + qd->planstate = NULL; - /* - * return the executor state structure - */ - return state; + return qd; } /* ---------------- @@ -147,8 +109,6 @@ ProcessQuery(Query *parsetree, Portal portal = NULL; MemoryContext oldContext = NULL; QueryDesc *queryDesc; - EState *state; - TupleDesc attinfo; /* * Check for special-case destinations @@ -193,7 +153,7 @@ ProcessQuery(Query *parsetree, /* * 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. */ } @@ -201,17 +161,12 @@ ProcessQuery(Query *parsetree, /* * Now we can create the QueryDesc object. */ - queryDesc = CreateQueryDesc(parsetree, plan, dest, intoName); - - /* - * create a default executor state. - */ - state = CreateExecutorState(); + queryDesc = CreateQueryDesc(parsetree, plan, dest, intoName, NULL, false); /* * 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 @@ -219,11 +174,8 @@ ProcessQuery(Query *parsetree, */ if (isRetrieveIntoPortal) { - PortalSetQuery(portal, - queryDesc, - attinfo, - state, - PortalCleanup); + /* Arrange to shut down the executor if portal is dropped */ + PortalSetQuery(portal, queryDesc, PortalCleanup); /* Now we can return to caller's memory context. */ MemoryContextSwitchTo(oldContext); @@ -239,7 +191,7 @@ ProcessQuery(Query *parsetree, * Now we get to the important call to ExecutorRun() where we actually * run the plan.. */ - ExecutorRun(queryDesc, state, ForwardScanDirection, 0L); + ExecutorRun(queryDesc, ForwardScanDirection, 0L); /* * Build command completion status string, if caller wants one. @@ -254,20 +206,20 @@ ProcessQuery(Query *parsetree, strcpy(completionTag, "SELECT"); break; case CMD_INSERT: - if (state->es_processed == 1) - lastOid = state->es_lastoid; + if (queryDesc->estate->es_processed == 1) + lastOid = queryDesc->estate->es_lastoid; else lastOid = InvalidOid; snprintf(completionTag, COMPLETION_TAG_BUFSIZE, - "INSERT %u %u", lastOid, state->es_processed); + "INSERT %u %u", lastOid, queryDesc->estate->es_processed); break; case CMD_UPDATE: snprintf(completionTag, COMPLETION_TAG_BUFSIZE, - "UPDATE %u", state->es_processed); + "UPDATE %u", queryDesc->estate->es_processed); break; case CMD_DELETE: snprintf(completionTag, COMPLETION_TAG_BUFSIZE, - "DELETE %u", state->es_processed); + "DELETE %u", queryDesc->estate->es_processed); break; default: strcpy(completionTag, "???"); @@ -278,5 +230,5 @@ ProcessQuery(Query *parsetree, /* * Now, we close down all the scans and free allocated resources. */ - ExecutorEnd(queryDesc, state); + ExecutorEnd(queryDesc); } diff --git a/src/backend/utils/mmgr/portalmem.c b/src/backend/utils/mmgr/portalmem.c index 4805c4481c..eaead7dffc 100644 --- a/src/backend/utils/mmgr/portalmem.c +++ b/src/backend/utils/mmgr/portalmem.c @@ -8,7 +8,7 @@ * * * 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) /* * PortalSetQuery * 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 PortalSetQuery(Portal portal, QueryDesc *queryDesc, - TupleDesc attinfo, - EState *state, void (*cleanup) (Portal portal)) { AssertArg(PortalIsValid(portal)); - AssertArg(IsA((Node *) state, EState)); portal->queryDesc = queryDesc; - portal->attinfo = attinfo; - portal->state = state; portal->atStart = true; /* Allow fetch forward only */ portal->atEnd = false; portal->cleanup = cleanup; @@ -212,8 +201,6 @@ CreatePortal(char *name) /* initialize portal query */ portal->queryDesc = NULL; - portal->attinfo = NULL; - portal->state = NULL; portal->atStart = true; /* disallow fetches until query is set */ portal->atEnd = true; portal->cleanup = NULL; diff --git a/src/include/executor/execdesc.h b/src/include/executor/execdesc.h index 363dabe43b..9a95551d7c 100644 --- a/src/include/executor/execdesc.h +++ b/src/include/executor/execdesc.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 @@ #define EXECDESC_H #include "nodes/parsenodes.h" -#include "nodes/plannodes.h" +#include "nodes/execnodes.h" #include "tcop/dest.h" /* ---------------- * query descriptor: + * * a QueryDesc encapsulates everything that the executor * needs to execute the query * --------------------- */ typedef struct QueryDesc { + /* These fields are provided by CreateQueryDesc */ CmdType operation; /* CMD_SELECT, CMD_UPDATE, etc. */ - Query *parsetree; - Plan *plantree; + Query *parsetree; /* rewritten parsetree */ + Plan *plantree; /* planner's output */ CommandDest dest; /* the destination output of the execution */ 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; /* in pquery.c */ extern QueryDesc *CreateQueryDesc(Query *parsetree, Plan *plantree, - CommandDest dest, const char *portalName); - + CommandDest dest, const char *portalName, + ParamListInfo params, + bool doInstrument); #endif /* EXECDESC_H */ diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h index 33b83bce6f..df3e52d4f0 100644 --- a/src/include/executor/executor.h +++ b/src/include/executor/executor.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 @@ #include "executor/execdesc.h" + /* ---------------- * TupIsNull * @@ -30,9 +31,9 @@ /* * prototypes from functions in execAmi.c */ -extern void ExecReScan(Plan *node, ExprContext *exprCtxt, Plan *parent); -extern void ExecMarkPos(Plan *node); -extern void ExecRestrPos(Plan *node); +extern void ExecReScan(PlanState *node, ExprContext *exprCtxt); +extern void ExecMarkPos(PlanState *node); +extern void ExecRestrPos(PlanState *node); extern bool ExecSupportsMarkRestore(NodeTag plantype); /* @@ -49,10 +50,12 @@ extern HeapTuple ExecRemoveJunk(JunkFilter *junkfilter, TupleTableSlot *slot); /* * prototypes from functions in execMain.c */ -extern TupleDesc ExecutorStart(QueryDesc *queryDesc, EState *estate); -extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc, EState *estate, +extern void ExecutorStart(QueryDesc *queryDesc); +extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc, 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, TupleTableSlot *slot, EState *estate); extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti, @@ -61,11 +64,11 @@ extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti, /* * prototypes from functions in execProcnode.c */ -extern bool ExecInitNode(Plan *node, EState *estate, Plan *parent); -extern TupleTableSlot *ExecProcNode(Plan *node, Plan *parent); +extern PlanState *ExecInitNode(Plan *node, EState *estate); +extern TupleTableSlot *ExecProcNode(PlanState *node); extern int ExecCountSlotsNode(Plan *node); -extern void ExecEndNode(Plan *node, Plan *parent); -extern TupleDesc ExecGetTupType(Plan *node); +extern void ExecEndNode(PlanState *node); +extern TupleDesc ExecGetTupType(PlanState *node); /* * prototypes from functions in execQual.c @@ -89,6 +92,7 @@ extern Datum ExecEvalExpr(Node *expression, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone); extern Datum ExecEvalExprSwitchContext(Node *expression, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone); +extern Node *ExecInitExpr(Node *node, PlanState *parent); extern bool ExecQual(List *qual, ExprContext *econtext, bool resultForNull); extern int ExecTargetListLength(List *targetlist); extern int ExecCleanTargetListLength(List *targetlist); @@ -98,9 +102,9 @@ extern TupleTableSlot *ExecProject(ProjectionInfo *projInfo, /* * 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 @@ -117,14 +121,13 @@ extern TupleTableSlot *ExecClearTuple(TupleTableSlot *slot); extern void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc, bool shouldFree); extern void ExecSetSlotDescriptorIsNew(TupleTableSlot *slot, bool isNew); -extern void ExecInitResultTupleSlot(EState *estate, CommonState *commonstate); -extern void ExecInitScanTupleSlot(EState *estate, - CommonScanState *commonscanstate); +extern void ExecInitResultTupleSlot(EState *estate, PlanState *planstate); +extern void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate); extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate); extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate, TupleDesc tupType); extern TupleDesc ExecTypeFromTL(List *targetList, bool hasoid); -extern void SetChangedParamList(Plan *node, List *newchg); +extern void SetChangedParamList(PlanState *node, List *newchg); typedef struct TupOutputState { @@ -155,21 +158,19 @@ extern void end_tup_output(TupOutputState *tstate); * prototypes from functions in execUtils.c */ extern void ResetTupleCount(void); -extern void ExecAssignExprContext(EState *estate, CommonState *commonstate); -extern void ExecAssignResultType(CommonState *commonstate, +extern void ExecAssignExprContext(EState *estate, PlanState *planstate); +extern void ExecAssignResultType(PlanState *planstate, TupleDesc tupDesc, bool shouldFree); -extern void ExecAssignResultTypeFromOuterPlan(Plan *node, - CommonState *commonstate); -extern void ExecAssignResultTypeFromTL(Plan *node, CommonState *commonstate); -extern TupleDesc ExecGetResultType(CommonState *commonstate); -extern void ExecAssignProjectionInfo(Plan *node, CommonState *commonstate); -extern void ExecFreeProjectionInfo(CommonState *commonstate); -extern void ExecFreeExprContext(CommonState *commonstate); -extern TupleDesc ExecGetScanType(CommonScanState *csstate); -extern void ExecAssignScanType(CommonScanState *csstate, +extern void ExecAssignResultTypeFromOuterPlan(PlanState *planstate); +extern void ExecAssignResultTypeFromTL(PlanState *planstate); +extern TupleDesc ExecGetResultType(PlanState *planstate); +extern void ExecAssignProjectionInfo(PlanState *planstate); +extern void ExecFreeProjectionInfo(PlanState *planstate); +extern void ExecFreeExprContext(PlanState *planstate); +extern TupleDesc ExecGetScanType(ScanState *scanstate); +extern void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc, bool shouldFree); -extern void ExecAssignScanTypeFromOuterPlan(Plan *node, - CommonScanState *csstate); +extern void ExecAssignScanTypeFromOuterPlan(ScanState *scanstate); extern ExprContext *MakeExprContext(TupleTableSlot *slot, MemoryContext queryContext); diff --git a/src/include/executor/nodeAgg.h b/src/include/executor/nodeAgg.h index c912d3c9c0..036d67ccaa 100644 --- a/src/include/executor/nodeAgg.h +++ b/src/include/executor/nodeAgg.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 @@ #define NODEAGG_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 void ExecEndAgg(Agg *node); -extern void ExecReScanAgg(Agg *node, ExprContext *exprCtxt, Plan *parent); +extern AggState *ExecInitAgg(Agg *node, EState *estate); +extern TupleTableSlot *ExecAgg(AggState *node); +extern void ExecEndAgg(AggState *node); +extern void ExecReScanAgg(AggState *node, ExprContext *exprCtxt); extern Datum aggregate_dummy(PG_FUNCTION_ARGS); diff --git a/src/include/executor/nodeAppend.h b/src/include/executor/nodeAppend.h index 4e9255b795..3d18b66d16 100644 --- a/src/include/executor/nodeAppend.h +++ b/src/include/executor/nodeAppend.h @@ -7,19 +7,19 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 #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 TupleTableSlot *ExecProcAppend(Append *node); -extern void ExecEndAppend(Append *node); -extern void ExecReScanAppend(Append *node, ExprContext *exprCtxt, Plan *parent); +extern AppendState *ExecInitAppend(Append *node, EState *estate); +extern TupleTableSlot *ExecProcAppend(AppendState *node); +extern void ExecEndAppend(AppendState *node); +extern void ExecReScanAppend(AppendState *node, ExprContext *exprCtxt); #endif /* NODEAPPEND_H */ diff --git a/src/include/executor/nodeFunctionscan.h b/src/include/executor/nodeFunctionscan.h index 9a59cd217a..893d6b097e 100644 --- a/src/include/executor/nodeFunctionscan.h +++ b/src/include/executor/nodeFunctionscan.h @@ -7,21 +7,21 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 #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 void ExecFunctionMarkPos(FunctionScan *node); -extern void ExecFunctionRestrPos(FunctionScan *node); -extern void ExecFunctionReScan(FunctionScan *node, ExprContext *exprCtxt, Plan *parent); +extern FunctionScanState *ExecInitFunctionScan(FunctionScan *node, EState *estate); +extern TupleTableSlot *ExecFunctionScan(FunctionScanState *node); +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 */ diff --git a/src/include/executor/nodeGroup.h b/src/include/executor/nodeGroup.h index b3c4e5bbd0..211e55b6ca 100644 --- a/src/include/executor/nodeGroup.h +++ b/src/include/executor/nodeGroup.h @@ -7,20 +7,20 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 #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 void ExecEndGroup(Group *node); -extern void ExecReScanGroup(Group *node, ExprContext *exprCtxt, Plan *parent); +extern GroupState *ExecInitGroup(Group *node, EState *estate); +extern TupleTableSlot *ExecGroup(GroupState *node); +extern void ExecEndGroup(GroupState *node); +extern void ExecReScanGroup(GroupState *node, ExprContext *exprCtxt); extern bool execTuplesMatch(HeapTuple tuple1, HeapTuple tuple2, diff --git a/src/include/executor/nodeHash.h b/src/include/executor/nodeHash.h index 654906cd3c..c30073ec8c 100644 --- a/src/include/executor/nodeHash.h +++ b/src/include/executor/nodeHash.h @@ -7,19 +7,21 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 #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 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 void ExecHashTableDestroy(HashJoinTable hashtable); extern void ExecHashTableInsert(HashJoinTable hashtable, @@ -31,7 +33,6 @@ extern int ExecHashGetBucket(HashJoinTable hashtable, extern HeapTuple ExecScanHashBucket(HashJoinState *hjstate, List *hjclauses, ExprContext *econtext); extern void ExecHashTableReset(HashJoinTable hashtable, long ntuples); -extern void ExecReScanHash(Hash *node, ExprContext *exprCtxt, Plan *parent); extern void ExecChooseHashTableSize(double ntuples, int tupwidth, int *virtualbuckets, int *physicalbuckets, diff --git a/src/include/executor/nodeHashjoin.h b/src/include/executor/nodeHashjoin.h index d13a8c9b05..9233c0758a 100644 --- a/src/include/executor/nodeHashjoin.h +++ b/src/include/executor/nodeHashjoin.h @@ -7,20 +7,21 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 #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 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 ExecReScanHashJoin(HashJoin *node, ExprContext *exprCtxt, Plan *parent); #endif /* NODEHASHJOIN_H */ diff --git a/src/include/executor/nodeIndexscan.h b/src/include/executor/nodeIndexscan.h index 26596e5fdd..392807cce0 100644 --- a/src/include/executor/nodeIndexscan.h +++ b/src/include/executor/nodeIndexscan.h @@ -7,22 +7,23 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 #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 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 */ diff --git a/src/include/executor/nodeLimit.h b/src/include/executor/nodeLimit.h index 16fa6072be..5b50335ee4 100644 --- a/src/include/executor/nodeLimit.h +++ b/src/include/executor/nodeLimit.h @@ -7,19 +7,19 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 #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 void ExecEndLimit(Limit *node); -extern void ExecReScanLimit(Limit *node, ExprContext *exprCtxt, Plan *parent); +extern LimitState *ExecInitLimit(Limit *node, EState *estate); +extern TupleTableSlot *ExecLimit(LimitState *node); +extern void ExecEndLimit(LimitState *node); +extern void ExecReScanLimit(LimitState *node, ExprContext *exprCtxt); #endif /* NODELIMIT_H */ diff --git a/src/include/executor/nodeMaterial.h b/src/include/executor/nodeMaterial.h index 818fe7590a..8235bc82c8 100644 --- a/src/include/executor/nodeMaterial.h +++ b/src/include/executor/nodeMaterial.h @@ -7,21 +7,21 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 #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 void ExecEndMaterial(Material *node); -extern void ExecMaterialMarkPos(Material *node); -extern void ExecMaterialRestrPos(Material *node); -extern void ExecMaterialReScan(Material *node, ExprContext *exprCtxt, Plan *parent); +extern MaterialState *ExecInitMaterial(Material *node, EState *estate); +extern TupleTableSlot *ExecMaterial(MaterialState *node); +extern void ExecEndMaterial(MaterialState *node); +extern void ExecMaterialMarkPos(MaterialState *node); +extern void ExecMaterialRestrPos(MaterialState *node); +extern void ExecMaterialReScan(MaterialState *node, ExprContext *exprCtxt); #endif /* NODEMATERIAL_H */ diff --git a/src/include/executor/nodeMergejoin.h b/src/include/executor/nodeMergejoin.h index b7ed7cd75b..1187d6bce2 100644 --- a/src/include/executor/nodeMergejoin.h +++ b/src/include/executor/nodeMergejoin.h @@ -7,19 +7,19 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 #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 void ExecEndMergeJoin(MergeJoin *node); -extern void ExecReScanMergeJoin(MergeJoin *node, ExprContext *exprCtxt, Plan *parent); +extern MergeJoinState *ExecInitMergeJoin(MergeJoin *node, EState *estate); +extern TupleTableSlot *ExecMergeJoin(MergeJoinState *node); +extern void ExecEndMergeJoin(MergeJoinState *node); +extern void ExecReScanMergeJoin(MergeJoinState *node, ExprContext *exprCtxt); -#endif /* NODEMERGEJOIN_H; */ +#endif /* NODEMERGEJOIN_H */ diff --git a/src/include/executor/nodeNestloop.h b/src/include/executor/nodeNestloop.h index e6224753ed..fd48820bbd 100644 --- a/src/include/executor/nodeNestloop.h +++ b/src/include/executor/nodeNestloop.h @@ -7,20 +7,19 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 #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 void ExecEndNestLoop(NestLoop *node); -extern void ExecReScanNestLoop(NestLoop *node, ExprContext *exprCtxt, - Plan *parent); +extern NestLoopState *ExecInitNestLoop(NestLoop *node, EState *estate); +extern TupleTableSlot *ExecNestLoop(NestLoopState *node); +extern void ExecEndNestLoop(NestLoopState *node); +extern void ExecReScanNestLoop(NestLoopState *node, ExprContext *exprCtxt); #endif /* NODENESTLOOP_H */ diff --git a/src/include/executor/nodeResult.h b/src/include/executor/nodeResult.h index 5d90cda001..8a44640830 100644 --- a/src/include/executor/nodeResult.h +++ b/src/include/executor/nodeResult.h @@ -7,19 +7,19 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 #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 void ExecEndResult(Result *node); -extern void ExecReScanResult(Result *node, ExprContext *exprCtxt, Plan *parent); +extern ResultState *ExecInitResult(Result *node, EState *estate); +extern TupleTableSlot *ExecResult(ResultState *node); +extern void ExecEndResult(ResultState *node); +extern void ExecReScanResult(ResultState *node, ExprContext *exprCtxt); #endif /* NODERESULT_H */ diff --git a/src/include/executor/nodeSeqscan.h b/src/include/executor/nodeSeqscan.h index 86d591c88c..683c4ab7dc 100644 --- a/src/include/executor/nodeSeqscan.h +++ b/src/include/executor/nodeSeqscan.h @@ -7,21 +7,21 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 #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 void ExecEndSeqScan(SeqScan *node); -extern void ExecSeqReScan(SeqScan *node, ExprContext *exprCtxt, Plan *parent); -extern void ExecSeqMarkPos(SeqScan *node); -extern void ExecSeqRestrPos(SeqScan *node); +extern SeqScanState *ExecInitSeqScan(SeqScan *node, EState *estate); +extern TupleTableSlot *ExecSeqScan(SeqScanState *node); +extern void ExecEndSeqScan(SeqScanState *node); +extern void ExecSeqMarkPos(SeqScanState *node); +extern void ExecSeqRestrPos(SeqScanState *node); +extern void ExecSeqReScan(SeqScanState *node, ExprContext *exprCtxt); #endif /* NODESEQSCAN_H */ diff --git a/src/include/executor/nodeSetOp.h b/src/include/executor/nodeSetOp.h index eb1b8c2518..73b1e7f5fc 100644 --- a/src/include/executor/nodeSetOp.h +++ b/src/include/executor/nodeSetOp.h @@ -7,19 +7,19 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 #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 void ExecEndSetOp(SetOp *node); -extern void ExecReScanSetOp(SetOp *node, ExprContext *exprCtxt, Plan *parent); +extern SetOpState *ExecInitSetOp(SetOp *node, EState *estate); +extern TupleTableSlot *ExecSetOp(SetOpState *node); +extern void ExecEndSetOp(SetOpState *node); +extern void ExecReScanSetOp(SetOpState *node, ExprContext *exprCtxt); #endif /* NODESETOP_H */ diff --git a/src/include/executor/nodeSort.h b/src/include/executor/nodeSort.h index ca2d1d5fb8..7836b32ab5 100644 --- a/src/include/executor/nodeSort.h +++ b/src/include/executor/nodeSort.h @@ -7,21 +7,21 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 #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 void ExecEndSort(Sort *node); -extern void ExecSortMarkPos(Sort *node); -extern void ExecSortRestrPos(Sort *node); -extern void ExecReScanSort(Sort *node, ExprContext *exprCtxt, Plan *parent); +extern SortState *ExecInitSort(Sort *node, EState *estate); +extern TupleTableSlot *ExecSort(SortState *node); +extern void ExecEndSort(SortState *node); +extern void ExecSortMarkPos(SortState *node); +extern void ExecSortRestrPos(SortState *node); +extern void ExecReScanSort(SortState *node, ExprContext *exprCtxt); #endif /* NODESORT_H */ diff --git a/src/include/executor/nodeSubplan.h b/src/include/executor/nodeSubplan.h index a061a42025..c573cf900d 100644 --- a/src/include/executor/nodeSubplan.h +++ b/src/include/executor/nodeSubplan.h @@ -2,18 +2,26 @@ * * 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 #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); -extern bool ExecInitSubPlan(SubPlan *node, EState *estate, Plan *parent); -extern void ExecReScanSetParamPlan(SubPlan *node, Plan *parent); -extern void ExecSetParamPlan(SubPlan *node, ExprContext *econtext); -extern void ExecEndSubPlan(SubPlan *node); +extern void ExecEndSubPlan(SubPlanState *node); +extern void ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent); + +extern void ExecSetParamPlan(SubPlanState *node, ExprContext *econtext); #endif /* NODESUBPLAN_H */ diff --git a/src/include/executor/nodeSubqueryscan.h b/src/include/executor/nodeSubqueryscan.h index e1a5f01aaf..5c5d5c8843 100644 --- a/src/include/executor/nodeSubqueryscan.h +++ b/src/include/executor/nodeSubqueryscan.h @@ -7,19 +7,19 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 #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 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 */ diff --git a/src/include/executor/nodeTidscan.h b/src/include/executor/nodeTidscan.h index 72e6c3e78f..9aadb592ca 100644 --- a/src/include/executor/nodeTidscan.h +++ b/src/include/executor/nodeTidscan.h @@ -7,22 +7,21 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 #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 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 */ diff --git a/src/include/executor/nodeUnique.h b/src/include/executor/nodeUnique.h index f829b65338..d71997e531 100644 --- a/src/include/executor/nodeUnique.h +++ b/src/include/executor/nodeUnique.h @@ -7,19 +7,19 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 #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 void ExecEndUnique(Unique *node); -extern void ExecReScanUnique(Unique *node, ExprContext *exprCtxt, Plan *parent); +extern UniqueState *ExecInitUnique(Unique *node, EState *estate); +extern TupleTableSlot *ExecUnique(UniqueState *node); +extern void ExecEndUnique(UniqueState *node); +extern void ExecReScanUnique(UniqueState *node, ExprContext *exprCtxt); #endif /* NODEUNIQUE_H */ diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 544510746d..a4f10ef4c0 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 @@ #define EXECNODES_H #include "access/relscan.h" -#include "access/sdir.h" #include "executor/hashjoin.h" #include "executor/tuptable.h" #include "fmgr.h" #include "nodes/params.h" -#include "nodes/primnodes.h" +#include "nodes/plannodes.h" #include "utils/tuplestore.h" @@ -316,6 +315,8 @@ typedef struct EState List *es_rowMark; /* not good place, but there is no other */ 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 * constraint checks and index-value computations. It will be reset @@ -332,98 +333,101 @@ typedef struct EState bool es_useEvalPlan; } 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 - * - * Superclass for all executor node-state object types. + * PlanState node * - * OuterTupleSlot pointer to slot containing current "outer" tuple - * ResultTupleSlot pointer to slot in tuple table for projected tuple - * 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?) + * We never actually instantiate any PlanState nodes; this is just the common + * abstract superclass for all PlanState-type nodes. * ---------------- */ -typedef struct CommonState +typedef struct PlanState { - NodeTag type; /* its first field is NodeTag */ - TupleTableSlot *cs_OuterTupleSlot; - TupleTableSlot *cs_ResultTupleSlot; - ExprContext *cs_ExprContext; - ProjectionInfo *cs_ProjInfo; - bool cs_TupFromTlist; -} CommonState; + NodeTag type; + Plan *plan; /* associated Plan node */ -/* ---------------------------------------------------------------- - * Control Node State Information - * ---------------------------------------------------------------- + EState *state; /* at execution time, state's of + * 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 - * - * done flag which tells us to quit when we - * have already returned a constant tuple. * ---------------- */ typedef struct ResultState { - CommonState cstate; /* its first field is NodeTag */ - bool rs_done; - bool rs_checkqual; + PlanState ps; /* its first field is NodeTag */ + Node *resconstantqual; + bool rs_done; /* are we done? */ + bool rs_checkqual; /* do we need to check the qual? */ } ResultState; /* ---------------- * AppendState information * + * nplans how many plans are in the list * whichplan which plan is being executed (0 .. n-1) * firstplan first plan to execute (usually 0) * lastplan last plan to execute (usually n-1) - * nplans how many plans are in the list - * initialized array of ExecInitNode() results * ---------------- */ 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_firstplan; int as_lastplan; - int as_nplans; - bool *as_initialized; } 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 * that scan the output of an underlying plan node --- in that case, * only ScanTupleSlot is actually useful, and it refers to the tuple @@ -445,27 +449,23 @@ typedef struct AppendState * ScanTupleSlot pointer to slot in tuple table holding scan tuple * ---------------- */ -typedef struct CommonScanState +typedef struct ScanState { - CommonState cstate; /* its first field is NodeTag */ - Relation css_currentRelation; - HeapScanDesc css_currentScanDesc; - TupleTableSlot *css_ScanTupleSlot; -} CommonScanState; + PlanState ps; /* its first field is NodeTag */ + Relation ss_currentRelation; + HeapScanDesc ss_currentScanDesc; + TupleTableSlot *ss_ScanTupleSlot; +} 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. */ +typedef ScanState SeqScanState; /* ---------------- * 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 * IndexPtr current index in use * ScanKeys Skey structures to scan index rels @@ -479,7 +479,9 @@ typedef struct CommonScanState */ typedef struct IndexScanState { - NodeTag type; + ScanState ss; /* its first field is NodeTag */ + List *indxqual; + List *indxqualorig; int iss_NumIndices; int iss_IndexPtr; int iss_MarkIndexPtr; @@ -495,10 +497,6 @@ typedef struct IndexScanState /* ---------------- * 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 * TidPtr current tid in use * TidList evaluated item pointers @@ -506,7 +504,7 @@ typedef struct IndexScanState */ typedef struct TidScanState { - NodeTag type; + ScanState ss; /* its first field is NodeTag */ int tss_NumTids; int tss_TidPtr; int tss_MarkTidPtr; @@ -526,7 +524,8 @@ typedef struct TidScanState */ typedef struct SubqueryScanState { - CommonScanState csstate; /* its first field is NodeTag */ + ScanState ss; /* its first field is NodeTag */ + PlanState *subplan; EState *sss_SubEState; } SubqueryScanState; @@ -538,12 +537,12 @@ typedef struct SubqueryScanState * * tupdesc expected return tuple description * tuplestorestate private state of tuplestore.c - * funcexpr function expression being evaluated + * funcexpr state for function expression being evaluated * ---------------- */ typedef struct FunctionScanState { - CommonScanState csstate; /* its first field is NodeTag */ + ScanState ss; /* its first field is NodeTag */ TupleDesc tupdesc; Tuplestorestate *tuplestorestate; Node *funcexpr; @@ -557,11 +556,15 @@ typedef struct FunctionScanState /* ---------------- * JoinState information * - * Superclass for state items of join nodes. - * Currently this is the same as CommonState. + * Superclass for state nodes of join plans. * ---------------- */ -typedef CommonState JoinState; +typedef struct JoinState +{ + PlanState ps; + JoinType jointype; + List *joinqual; /* JOIN quals (in addition to ps.qual) */ +} JoinState; /* ---------------- * NestLoopState information @@ -573,7 +576,7 @@ typedef CommonState JoinState; */ typedef struct NestLoopState { - JoinState jstate; /* its first field is NodeTag */ + JoinState js; /* its first field is NodeTag */ bool nl_NeedNewOuter; bool nl_MatchedOuter; TupleTableSlot *nl_NullInnerTupleSlot; @@ -596,7 +599,8 @@ typedef struct NestLoopState */ typedef struct MergeJoinState { - JoinState jstate; /* its first field is NodeTag */ + JoinState js; /* its first field is NodeTag */ + List *mergeclauses; List *mj_OuterSkipQual; List *mj_InnerSkipQual; int mj_JoinState; @@ -630,7 +634,8 @@ typedef struct MergeJoinState */ typedef struct HashJoinState { - JoinState jstate; /* its first field is NodeTag */ + JoinState js; /* its first field is NodeTag */ + List *hashclauses; HashJoinTable hj_HashTable; int hj_CurBucketNo; HashJoinTuple hj_CurTuple; @@ -656,23 +661,46 @@ typedef struct HashJoinState * materialize nodes are used to materialize the results * 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 * ---------------- */ typedef struct MaterialState { - CommonScanState csstate; /* its first field is NodeTag */ + ScanState ss; /* its first field is NodeTag */ void *tuplestorestate; } 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; + /* --------------------- - * AggregateState information + * 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; + +/* --------------------- + * 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 * input group during evaluation of an Agg node's output tuple(s). We * create a second ExprContext, tmpcontext, in which to evaluate input @@ -687,7 +715,7 @@ typedef struct AggHashTableData *AggHashTable; 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 */ int numaggs; /* length of list (could be zero!) */ FmgrInfo *eqfunctions; /* per-grouping-field equality fns */ @@ -705,32 +733,6 @@ typedef struct AggState int next_hash_bucket; /* next chain */ } 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 * @@ -744,13 +746,23 @@ typedef struct SortState */ 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 */ HeapTuple priorTuple; /* most recently returned tuple, or NULL */ MemoryContext tempContext; /* short-term context for comparisons */ } UniqueState; /* ---------------- + * HashState information + * ---------------- + */ +typedef struct HashState +{ + PlanState ps; /* its first field is NodeTag */ + HashJoinTable hashtable; /* hash table for the hashjoin */ +} HashState; + +/* ---------------- * SetOpState information * * SetOp nodes are used "on top of" sort nodes to discard @@ -761,7 +773,7 @@ typedef struct UniqueState */ 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 */ bool subplan_done; /* has subplan returned EOF? */ long numLeft; /* number of left-input dups of cur group */ @@ -794,7 +806,9 @@ typedef enum 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 count; /* current COUNT, if any */ bool noCount; /* if true, ignore count */ @@ -803,46 +817,16 @@ typedef struct LimitState TupleTableSlot *subSlot; /* tuple last obtained from subplan */ } LimitState; - -/* ---------------- - * HashState information - * - * hashtable hash table for the hashjoin - * ---------------- +/* --------------------- + * SubPlanState information + * --------------------- */ -typedef struct HashState +typedef struct SubPlanState { - CommonState cstate; /* its first field is NodeTag */ - HashJoinTable hashtable; -} HashState; - -#ifdef NOT_USED -/* ----------------------- - * 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 + PlanState ps; /* its first field is NodeTag */ + PlanState *planstate; /* subselect plan's state tree */ + bool needShutdown; /* TRUE = need to shutdown subplan */ + HeapTuple curTuple; /* copy of most recent tuple from subplan */ +} SubPlanState; #endif /* EXECNODES_H */ diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h index a9cd095f94..cb16a30044 100644 --- a/src/include/nodes/nodes.h +++ b/src/include/nodes/nodes.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 @@ * 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. * - * 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. + * (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 { 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) */ - T_Plan = 10, + T_Plan = 100, T_Result, T_Append, T_Scan, T_SeqScan, T_IndexScan, + T_TidScan, + T_SubqueryScan, + T_FunctionScan, T_Join, T_NestLoop, T_MergeJoin, T_HashJoin, - T_Limit, T_Material, T_Sort, + T_Group, T_Agg, T_Unique, T_Hash, T_SetOp, - T_Group, + T_Limit, 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) */ - T_Resdom = 100, + T_Resdom = 300, T_Fjoin, T_Expr, T_Var, @@ -74,7 +115,7 @@ typedef enum NodeTag /* * TAGS FOR PLANNER NODES (relation.h) */ - T_RelOptInfo = 200, + T_RelOptInfo = 400, T_IndexOptInfo, T_Path, T_IndexPath, @@ -91,47 +132,15 @@ typedef enum NodeTag 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) */ - T_MemoryContext = 400, + T_MemoryContext = 500, T_AllocSetContext, /* * TAGS FOR VALUE NODES (pg_list.h) */ - T_Value = 500, + T_Value = 600, T_List, T_Integer, T_Float, @@ -142,7 +151,7 @@ typedef enum NodeTag /* * TAGS FOR PARSE TREE NODES (parsenodes.h) */ - T_Query = 600, + T_Query = 700, T_InsertStmt, T_DeleteStmt, T_UpdateStmt, @@ -208,7 +217,7 @@ typedef enum NodeTag T_ExecuteStmt, T_DeallocateStmt, - T_A_Expr = 700, + T_A_Expr = 800, T_ColumnRef, T_ParamRef, T_A_Const, @@ -248,7 +257,7 @@ typedef enum NodeTag /* * 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 */ } NodeTag; diff --git a/src/include/nodes/params.h b/src/include/nodes/params.h index ef0e0682be..8f2eff5165 100644 --- a/src/include/nodes/params.h +++ b/src/include/nodes/params.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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; * array of ParamExecData records, which is referenced through * 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 * lazy evaluation of InitPlans: they aren't executed until/unless a * result value is needed.) Otherwise the value is assumed to be valid @@ -98,7 +98,7 @@ typedef ParamListInfoData *ParamListInfo; typedef struct ParamExecData { - void *execPlan; /* should be "SubPlan *" */ + void *execPlan; /* should be "SubPlanState *" */ Datum value; bool isnull; } ParamExecData; diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h index 6a6ac415f9..097f8d93b1 100644 --- a/src/include/nodes/plannodes.h +++ b/src/include/nodes/plannodes.h @@ -7,52 +7,15 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 #define PLANNODES_H -#include "nodes/execnodes.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; - * - * ---------------------------------------------------------------- - */ +#include "access/sdir.h" +#include "nodes/primnodes.h" /* ---------------------------------------------------------------- @@ -62,45 +25,47 @@ /* ---------------- * 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 { 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 * tuples */ Cost total_cost; /* total cost (assuming all tuples * fetched) */ /* - * planner's estimate of result size (note: LIMIT, if any, is not - * considered in setting plan_rows) + * planner's estimate of result size of this plan step */ double plan_rows; /* number of rows plan is expected to emit */ int plan_width; /* average row width in bytes */ /* - * execution state data. Having Plan point to this, rather than the - * other way round, is 100% bogus. + * Common structural data for all Plan types. */ - EState *state; /* at execution time, state's of - * individual nodes point to one EState - * for the whole top-level plan */ - - struct Instrumentation *instrument; /* Optional runtime stats for this - * plan node */ + List *targetlist; /* target list to be computed at this node */ + List *qual; /* implicitly-ANDed qual conditions */ + struct Plan *lefttree; /* input plan tree(s) */ + struct Plan *righttree; + List *initPlan; /* Init Plan nodes (un-correlated expr + * subselects) */ /* - * Common structural data for all Plan types. XXX chgParam is runtime - * data and should be in the EState, not here. + * Information for management of parameter-change-driven rescanning */ - List *targetlist; - List *qual; /* implicitly-ANDed qual conditions */ - struct Plan *lefttree; - struct Plan *righttree; List *extParam; /* indices of _all_ _external_ PARAM_EXEC * for this plan in global * es_param_exec_vals. Params from @@ -108,10 +73,6 @@ typedef struct Plan * included, but their execParam-s are * here!!! */ 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 @@ -134,20 +95,6 @@ typedef struct Plan #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 - * If no outer plan, evaluate a variable-free targetlist. @@ -163,7 +110,6 @@ typedef struct Result { Plan plan; Node *resconstantqual; - ResultState *resstate; } Result; /* ---------------- @@ -182,7 +128,6 @@ typedef struct Append Plan plan; List *appendplans; bool isTarget; - AppendState *appendstate; } Append; /* @@ -194,7 +139,6 @@ typedef struct Scan { Plan plan; Index scanrelid; /* relid is index into the range table */ - CommonScanState *scanstate; } Scan; /* ---------------- @@ -214,7 +158,6 @@ typedef struct IndexScan List *indxqual; List *indxqualorig; ScanDirection indxorderdir; - IndexScanState *indxstate; } IndexScan; /* ---------------- @@ -224,9 +167,7 @@ typedef struct IndexScan typedef struct TidScan { Scan scan; - bool needRescan; List *tideval; - TidScanState *tidstate; } TidScan; /* ---------------- @@ -257,7 +198,6 @@ typedef struct FunctionScan { Scan scan; /* no other fields needed at present */ - /* scan.scanstate actually points at a FunctionScanState node */ } FunctionScan; /* @@ -296,7 +236,6 @@ typedef struct Join typedef struct NestLoop { Join join; - NestLoopState *nlstate; } NestLoop; /* ---------------- @@ -307,7 +246,6 @@ typedef struct MergeJoin { Join join; List *mergeclauses; - MergeJoinState *mergestate; } MergeJoin; /* ---------------- @@ -318,9 +256,40 @@ typedef struct HashJoin { Join join; List *hashclauses; - HashJoinState *hashjoinstate; } 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 * @@ -349,44 +318,8 @@ typedef struct Agg int numCols; /* number of grouping columns */ AttrNumber *grpColIdx; /* their indexes in the target list */ long numGroups; /* estimated number of groups in input */ - AggState *aggstate; } 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 * ---------------- @@ -397,10 +330,19 @@ typedef struct Unique int numCols; /* number of columns to check for * uniqueness */ AttrNumber *uniqColIdx; /* indexes into the target list */ - UniqueState *uniquestate; } Unique; /* ---------------- + * hash build node + * ---------------- + */ +typedef struct Hash +{ + Plan plan; + List *hashkeys; +} Hash; + +/* ---------------- * setop node * ---------------- */ @@ -420,7 +362,6 @@ typedef struct SetOp * duplicate-ness */ AttrNumber *dupColIdx; /* indexes into the target list */ AttrNumber flagColIdx; - SetOpState *setopstate; } SetOp; /* ---------------- @@ -432,44 +373,13 @@ typedef struct Limit Plan plan; Node *limitOffset; /* OFFSET parameter, or NULL if none */ Node *limitCount; /* COUNT parameter, or NULL if none */ - LimitState *limitstate; } 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 + * + * 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 @@ -489,12 +399,7 @@ typedef struct SubPlan * about what to do with subselect's * results */ - /* - * 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 */ + struct SubPlanState *pstate; /* XXX TEMPORARY HACK */ } SubPlan; #endif /* PLANNODES_H */ diff --git a/src/include/nodes/print.h b/src/include/nodes/print.h index 7ebcef4f10..07accf78f3 100644 --- a/src/include/nodes/print.h +++ b/src/include/nodes/print.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 @@ #define PRINT_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 pprint(void *obj); diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index 5f6ad686df..333ca0b695 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 $ * *------------------------------------------------------------------------- */ @@ -377,8 +377,7 @@ typedef struct IndexPath typedef struct TidPath { Path path; - List *tideval; /* qual(s) involving CTID = something */ - Relids unjoined_relids; /* some rels not yet part of my Path */ + List *tideval; /* qual(s) involving CTID = something */ } TidPath; /* diff --git a/src/include/tcop/pquery.h b/src/include/tcop/pquery.h index a29b1857ec..b001424997 100644 --- a/src/include/tcop/pquery.h +++ b/src/include/tcop/pquery.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * 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 @@ extern void ProcessQuery(Query *parsetree, Plan *plan, CommandDest dest, char *completionTag); -extern EState *CreateExecutorState(void); - extern Portal PreparePortal(char *portalName); #endif /* PQUERY_H */ diff --git a/src/include/utils/portal.h b/src/include/utils/portal.h index ba784fee03..40258acc32 100644 --- a/src/include/utils/portal.h +++ b/src/include/utils/portal.h @@ -3,19 +3,16 @@ * portal.h * 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) 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 #define PORTAL_H @@ -30,8 +27,6 @@ typedef struct PortalData char *name; /* Portal's name */ MemoryContext heap; /* subsidiary memory */ 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 atEnd; /* T => fetch forwards is not allowed */ void (*cleanup) (Portal); /* Cleanup routine (optional) */ @@ -47,8 +42,6 @@ typedef struct PortalData * Access macros for Portal ... use these in preference to field access. */ #define PortalGetQueryDesc(portal) ((portal)->queryDesc) -#define PortalGetTupleDesc(portal) ((portal)->attinfo) -#define PortalGetState(portal) ((portal)->state) #define PortalGetHeapMemory(portal) ((portal)->heap) /* @@ -64,7 +57,6 @@ extern Portal CreatePortal(char *name); extern void PortalDrop(Portal portal); extern Portal GetPortalByName(char *name); extern void PortalSetQuery(Portal portal, QueryDesc *queryDesc, - TupleDesc attinfo, EState *state, - void (*cleanup) (Portal portal)); + void (*cleanup) (Portal portal)); #endif /* PORTAL_H */ diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 2bdf24116c..007a3ffbe7 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -3,7 +3,7 @@ * procedural language * * 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. * @@ -3583,7 +3583,6 @@ exec_simple_check_plan(PLpgSQL_expr * expr) if (plan->lefttree != NULL || plan->righttree != NULL || plan->initPlan != NULL || - plan->subPlan != NULL || plan->qual != NULL || ((Result *) plan)->resconstantqual != NULL) return; -- 2.11.0