Phase 3 of read-only-plans project: ExecInitExpr now builds expression

execution state trees, and ExecEvalExpr takes an expression state tree
not an expression plan tree.  The plan tree is now read-only as far as
the executor is concerned.  Next step is to begin actually exploiting
this property.
This commit is contained in:
Tom Lane 2002-12-13 19:46:01 +00:00
parent 77b7a740f9
commit 3a4f7dde16
49 changed files with 993 additions and 815 deletions

View File

@ -25,7 +25,6 @@
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
#include "executor/executor.h"
#include "utils/fcache.h"
#include "utils/sets.h"
#include "utils/syscache.h"
#include "access/tupmacs.h"

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.145 2002/11/14 23:53:27 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.146 2002/12/13 19:45:45 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -31,6 +31,7 @@
#include "catalog/catname.h"
#include "catalog/index.h"
#include "catalog/pg_type.h"
#include "executor/executor.h"
#include "libpq/pqsignal.h"
#include "miscadmin.h"
#include "storage/ipc.h"
@ -1142,6 +1143,8 @@ index_register(Oid heap,
/* predicate will likely be null, but may as well copy it */
newind->il_info->ii_Predicate = (List *)
copyObject(indexInfo->ii_Predicate);
newind->il_info->ii_PredicateState = (List *)
ExecInitExpr((Expr *) newind->il_info->ii_Predicate, NULL);
newind->il_next = ILHead;
ILHead = newind;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.206 2002/12/12 15:49:24 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.207 2002/12/13 19:45:47 tgl Exp $
*
*
* INTERFACE ROUTINES
@ -912,6 +912,7 @@ BuildIndexInfo(Form_pg_index indexStruct)
/*
* If partial index, convert predicate into expression nodetree
* and prepare an execution state nodetree for it
*/
if (VARSIZE(&indexStruct->indpred) > VARHDRSZ)
{
@ -921,10 +922,15 @@ BuildIndexInfo(Form_pg_index indexStruct)
PointerGetDatum(&indexStruct->indpred)));
ii->ii_Predicate = stringToNode(predString);
fix_opfuncids((Node *) ii->ii_Predicate);
ii->ii_PredicateState = (List *)
ExecInitExpr((Expr *) ii->ii_Predicate, NULL);
pfree(predString);
}
else
{
ii->ii_Predicate = NIL;
ii->ii_PredicateState = NIL;
}
/* Other info */
ii->ii_Unique = indexStruct->indisunique;
@ -1483,7 +1489,7 @@ IndexBuildHeapScan(Relation heapRelation,
Datum attdata[INDEX_MAX_KEYS];
char nulls[INDEX_MAX_KEYS];
double reltuples;
List *predicate = indexInfo->ii_Predicate;
List *predicate = indexInfo->ii_PredicateState;
TupleTable tupleTable;
TupleTableSlot *slot;
ExprContext *econtext;

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.185 2002/12/12 15:49:24 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.186 2002/12/13 19:45:48 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -758,7 +758,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
num_defaults;
FmgrInfo *in_functions;
Oid *elements;
Node **constraintexprs;
ExprState **constraintexprs;
bool hasConstraints = false;
int i;
List *cur;
@ -772,7 +772,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
TupleTableSlot *slot;
bool file_has_oids;
int *defmap;
Node **defexprs; /* array of default att expressions */
ExprState **defexprs; /* array of default att expressions */
ExprContext *econtext; /* used for ExecEvalExpr for default atts */
MemoryContext oldcontext = CurrentMemoryContext;
@ -812,8 +812,8 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
elements = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
defmap = (int *) palloc(num_phys_attrs * sizeof(int));
defexprs = (Node **) palloc(num_phys_attrs * sizeof(Node *));
constraintexprs = (Node **) palloc0(num_phys_attrs * sizeof(Node *));
defexprs = (ExprState **) palloc(num_phys_attrs * sizeof(ExprState *));
constraintexprs = (ExprState **) palloc0(num_phys_attrs * sizeof(ExprState *));
for (i = 0; i < num_phys_attrs; i++)
{
@ -837,10 +837,12 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
{
/* attribute is NOT to be copied */
/* use default value if one exists */
defexprs[num_defaults] = build_column_default(rel, i + 1);
if (defexprs[num_defaults] != NULL)
Node *defexpr = build_column_default(rel, i + 1);
if (defexpr != NULL)
{
fix_opfuncids(defexprs[num_defaults]);
fix_opfuncids(defexpr);
defexprs[num_defaults] = ExecInitExpr((Expr *) defexpr, NULL);
defmap[num_defaults] = i;
num_defaults++;
}
@ -872,7 +874,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
if (node != (Node *) prm)
{
fix_opfuncids(node);
constraintexprs[i] = node;
constraintexprs[i] = ExecInitExpr((Expr *) node, NULL);
hasConstraints = true;
}
}
@ -1165,10 +1167,10 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
for (i = 0; i < num_phys_attrs; i++)
{
Node *node = constraintexprs[i];
ExprState *exprstate = constraintexprs[i];
bool isnull;
if (node == NULL)
if (exprstate == NULL)
continue; /* no constraint for this attr */
/* Insert current row's value into the Param value */
@ -1180,7 +1182,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
* to replace the value (consider e.g. a timestamp precision
* restriction).
*/
values[i] = ExecEvalExpr(node, econtext,
values[i] = ExecEvalExpr(exprstate, econtext,
&isnull, NULL);
nulls[i] = isnull ? 'n' : ' ';
}

View File

@ -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.96 2002/12/12 15:49:24 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.97 2002/12/13 19:45:49 tgl Exp $
*
*/
@ -582,26 +582,24 @@ explain_outNode(StringInfo str,
if (plan->initPlan)
{
List *saved_rtable = es->rtable;
List *pslist = planstate->initPlan;
List *lst;
for (i = 0; i < indent; i++)
appendStringInfo(str, " ");
appendStringInfo(str, " InitPlan\n");
foreach(lst, plan->initPlan)
foreach(lst, planstate->initPlan)
{
SubPlanExpr *subplan = (SubPlanExpr *) lfirst(lst);
SubPlanState *subplanstate = (SubPlanState *) lfirst(pslist);
SubPlanExprState *sps = (SubPlanExprState *) lfirst(lst);
SubPlanExpr *sp = (SubPlanExpr *) sps->xprstate.expr;
es->rtable = subplan->rtable;
es->rtable = sp->rtable;
for (i = 0; i < indent; i++)
appendStringInfo(str, " ");
appendStringInfo(str, " -> ");
explain_outNode(str, subplan->plan,
subplanstate->planstate,
explain_outNode(str, sp->plan,
sps->planstate,
NULL,
indent + 4, es);
pslist = lnext(pslist);
}
es->rtable = saved_rtable;
}
@ -689,8 +687,8 @@ explain_outNode(StringInfo str,
appendStringInfo(str, " SubPlan\n");
foreach(lst, planstate->subPlan)
{
SubPlanState *sps = (SubPlanState *) lfirst(lst);
SubPlanExpr *sp = (SubPlanExpr *) sps->ps.plan;
SubPlanExprState *sps = (SubPlanExprState *) lfirst(lst);
SubPlanExpr *sp = (SubPlanExpr *) sps->xprstate.expr;
es->rtable = sp->rtable;
for (i = 0; i < indent; i++)

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.93 2002/12/12 15:49:24 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.94 2002/12/13 19:45:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -24,6 +24,7 @@
#include "catalog/pg_opclass.h"
#include "catalog/pg_proc.h"
#include "commands/defrem.h"
#include "executor/executor.h"
#include "miscadmin.h"
#include "optimizer/clauses.h"
#include "optimizer/planmain.h"
@ -172,6 +173,8 @@ DefineIndex(RangeVar *heapRelation,
*/
indexInfo = makeNode(IndexInfo);
indexInfo->ii_Predicate = cnfPred;
indexInfo->ii_PredicateState = (List *)
ExecInitExpr((Expr *) cnfPred, NULL);
indexInfo->ii_FuncOid = InvalidOid;
indexInfo->ii_Unique = unique;

View File

@ -6,7 +6,7 @@
* Copyright (c) 2002, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/prepare.c,v 1.9 2002/12/05 15:50:30 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/prepare.c,v 1.10 2002/12/13 19:45:51 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -15,6 +15,7 @@
#include "commands/prepare.h"
#include "executor/executor.h"
#include "utils/guc.h"
#include "optimizer/planmain.h"
#include "optimizer/planner.h"
#include "rewrite/rewriteHandler.h"
#include "tcop/pquery.h"
@ -110,17 +111,22 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest)
{
int nargs = length(entry->argtype_list);
int i = 0;
List *exprstates;
ExprContext *econtext = MakeExprContext(NULL, CurrentMemoryContext);
/* Parser should have caught this error, but check */
if (nargs != length(stmt->params))
elog(ERROR, "ExecuteQuery: wrong number of arguments");
fix_opfuncids((Node *) stmt->params);
exprstates = (List *) ExecInitExpr((Expr *) stmt->params, NULL);
paramLI = (ParamListInfo) palloc0((nargs + 1) * sizeof(ParamListInfoData));
foreach(l, stmt->params)
foreach(l, exprstates)
{
Node *n = lfirst(l);
ExprState *n = lfirst(l);
bool isNull;
paramLI[i].value = ExecEvalExprSwitchContext(n,

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.59 2002/12/12 20:35:12 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.60 2002/12/13 19:45:51 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -2718,6 +2718,7 @@ AlterTableAddCheckConstraint(Relation rel, Constraint *constr)
HeapTuple tuple;
RangeTblEntry *rte;
List *qual;
List *qualstate;
Node *expr;
/*
@ -2769,6 +2770,9 @@ AlterTableAddCheckConstraint(Relation rel, Constraint *constr)
qual = makeList1(expr);
/* build execution state for qual */
qualstate = (List *) ExecInitExpr((Expr *) qual, NULL);
/* Make tuple slot to hold tuples */
slot = MakeTupleTableSlot();
ExecSetSlotDescriptor(slot, RelationGetDescr(rel), false);
@ -2783,7 +2787,7 @@ AlterTableAddCheckConstraint(Relation rel, Constraint *constr)
while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
{
ExecStoreTuple(tuple, slot, InvalidBuffer, false);
if (!ExecQual(qual, econtext, true))
if (!ExecQual(qualstate, econtext, true))
{
successful = false;
break;
@ -3820,6 +3824,7 @@ AlterTableCreateToastTable(Oid relOid, bool silent)
indexInfo->ii_KeyAttrNumbers[0] = 1;
indexInfo->ii_KeyAttrNumbers[1] = 2;
indexInfo->ii_Predicate = NIL;
indexInfo->ii_PredicateState = NIL;
indexInfo->ii_FuncOid = InvalidOid;
indexInfo->ii_Unique = true;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.23 2002/12/12 20:35:12 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.24 2002/12/13 19:45:52 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@ -1244,7 +1244,8 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
Form_pg_type typTup;
ExprContext *econtext;
char *ccbin;
Node *expr;
Expr *expr;
ExprState *exprstate;
int counter = 0;
Constraint *constr;
@ -1336,10 +1337,11 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
* Test all values stored in the attributes based on the domain
* the constraint is being added to.
*/
expr = stringToNode(ccbin);
fix_opfuncids(expr);
expr = (Expr *) stringToNode(ccbin);
fix_opfuncids((Node *) expr);
exprstate = ExecInitExpr(expr, NULL);
/* Make an expression context for ExecQual */
/* Make an expression context for ExecEvalExpr */
econtext = MakeExprContext(NULL, CurrentMemoryContext);
rels = get_rels_with_domain(domainoid);
@ -1375,7 +1377,7 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
econtext->domainValue_datum = d;
econtext->domainValue_isNull = isNull;
conResult = ExecEvalExpr(expr, econtext, &isNull, NULL);
conResult = ExecEvalExpr(exprstate, econtext, &isNull, NULL);
if (!isNull && !DatumGetBool(conResult))
elog(ERROR, "AlterDomainAddConstraint: Domain %s constraint %s failed",

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.66 2002/12/05 15:50:30 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.67 2002/12/13 19:45:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -61,17 +61,19 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt)
foreach(lst, node->initPlan)
{
PlanState *splan = ((SubPlanState *) lfirst(lst))->planstate;
SubPlanExprState *sstate = (SubPlanExprState *) lfirst(lst);
PlanState *splan = sstate->planstate;
if (splan->plan->extParam != NIL) /* don't care about child
* locParam */
SetChangedParamList(splan, node->chgParam);
if (splan->chgParam != NIL)
ExecReScanSetParamPlan((SubPlanState *) lfirst(lst), node);
ExecReScanSetParamPlan(sstate, node);
}
foreach(lst, node->subPlan)
{
PlanState *splan = ((SubPlanState *) lfirst(lst))->planstate;
SubPlanExprState *sstate = (SubPlanExprState *) lfirst(lst);
PlanState *splan = sstate->planstate;
if (splan->plan->extParam != NIL)
SetChangedParamList(splan, node->chgParam);

View File

@ -26,7 +26,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.191 2002/12/12 15:49:24 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.192 2002/12/13 19:45:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1543,7 +1543,8 @@ ExecRelCheck(ResultRelInfo *resultRelInfo,
{
qual = (List *) stringToNode(check[i].ccbin);
fix_opfuncids((Node *) qual);
resultRelInfo->ri_ConstraintExprs[i] = qual;
resultRelInfo->ri_ConstraintExprs[i] = (List *)
ExecInitExpr((Expr *) qual, NULL);
}
MemoryContextSwitchTo(oldContext);
}

View File

@ -12,7 +12,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.32 2002/12/12 15:49:24 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.33 2002/12/13 19:45:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -229,23 +229,29 @@ ExecInitNode(Plan *node, EState *estate)
foreach(subp, node->initPlan)
{
SubPlanExpr *subplan = (SubPlanExpr *) lfirst(subp);
SubPlanExprState *sstate;
Assert(IsA(subplan, SubPlanExpr));
subps = lappend(subps, ExecInitSubPlan(subplan, estate));
sstate = ExecInitExprInitPlan(subplan, result);
ExecInitSubPlan(sstate, estate);
subps = lappend(subps, sstate);
}
result->initPlan = subps;
/*
* Initialize any subPlans present in this node. These were found
* by ExecInitExpr during initialization of the PlanState.
* by ExecInitExpr during initialization of the PlanState. Note we
* must do this after initializing initPlans, in case their arguments
* contain subPlans (is that actually possible? perhaps not).
*/
subps = NIL;
foreach(subp, result->subPlan)
{
SubPlanExpr *subplan = (SubPlanExpr *) lfirst(subp);
SubPlanExprState *sstate = (SubPlanExprState *) lfirst(subp);
Assert(IsA(subplan, SubPlanExpr));
subps = lappend(subps, ExecInitSubPlan(subplan, estate));
Assert(IsA(sstate, SubPlanExprState));
ExecInitSubPlan(sstate, estate);
subps = lappend(subps, sstate);
}
result->subPlan = subps;
@ -492,14 +498,11 @@ ExecEndNode(PlanState *node)
if (node == NULL)
return;
if (node->instrument)
InstrEndLoop(node->instrument);
/* Clean up initPlans and subPlans */
foreach(subp, node->initPlan)
ExecEndSubPlan((SubPlanState *) lfirst(subp));
ExecEndSubPlan((SubPlanExprState *) lfirst(subp));
foreach(subp, node->subPlan)
ExecEndSubPlan((SubPlanState *) lfirst(subp));
ExecEndSubPlan((SubPlanExprState *) lfirst(subp));
if (node->chgParam != NIL)
{

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.62 2002/12/12 15:49:28 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.63 2002/12/13 19:45:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -550,6 +550,7 @@ ExecInitNullTupleSlot(EState *estate, TupleDesc tupType)
* ExecTypeFromTL
*
* Generate a tuple descriptor for the result tuple of a targetlist.
* (A parse/plan tlist must be passed, not an ExprState tlist.)
* Note that resjunk columns, if any, are included in the result.
*
* Currently there are about 4 different places where we create

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.91 2002/12/05 15:50:32 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.92 2002/12/13 19:45:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -321,9 +321,9 @@ ExecAssignResultTypeFromTL(PlanState *planstate)
}
/*
* 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.
* ExecTypeFromTL needs the parse-time representation of the tlist, not
* a list of ExprStates. This is good because some plan nodes don't
* bother to set up planstate->targetlist ...
*/
tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid);
ExecAssignResultType(planstate, tupDesc, true);
@ -681,7 +681,7 @@ ExecInsertIndexTuples(TupleTableSlot *slot,
continue;
indexInfo = indexInfoArray[i];
predicate = indexInfo->ii_Predicate;
predicate = indexInfo->ii_PredicateState;
if (predicate != NIL)
{
/* Skip this index-update if the predicate isn't satisfied */

View File

@ -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.99 2002/12/12 15:49:24 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.100 2002/12/13 19:45:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -82,7 +82,8 @@ typedef struct AggStatePerAggData
* thereafter:
*/
/* Link to Aggref node this working state is for */
/* Links to Aggref expr and state nodes this working state is for */
AggrefExprState *aggrefstate;
Aggref *aggref;
/* Oids of transfer functions */
@ -237,7 +238,7 @@ initialize_aggregates(AggState *aggstate,
{
AggStatePerAgg peraggstate = &peragg[aggno];
AggStatePerGroup pergroupstate = &pergroup[aggno];
Aggref *aggref = peraggstate->aggref;
Aggref *aggref = peraggstate->aggref;
/*
* Start a fresh sort operation for each DISTINCT aggregate.
@ -411,11 +412,12 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
{
AggStatePerAgg peraggstate = &aggstate->peragg[aggno];
AggStatePerGroup pergroupstate = &pergroup[aggno];
AggrefExprState *aggrefstate = peraggstate->aggrefstate;
Aggref *aggref = peraggstate->aggref;
Datum newVal;
bool isNull;
newVal = ExecEvalExprSwitchContext((Node *) aggref->target, econtext,
newVal = ExecEvalExprSwitchContext(aggrefstate->target, econtext,
&isNull, NULL);
if (aggref->aggdistinct)
@ -1145,10 +1147,10 @@ ExecInitAgg(Agg *node, EState *estate)
* particular order.
*/
aggstate->ss.ps.targetlist = (List *)
ExecInitExpr((Node *) node->plan.targetlist,
ExecInitExpr((Expr *) node->plan.targetlist,
(PlanState *) aggstate);
aggstate->ss.ps.qual = (List *)
ExecInitExpr((Node *) node->plan.qual,
ExecInitExpr((Expr *) node->plan.qual,
(PlanState *) aggstate);
/*
@ -1227,7 +1229,8 @@ ExecInitAgg(Agg *node, EState *estate)
aggno = -1;
foreach(alist, aggstate->aggs)
{
Aggref *aggref = (Aggref *) lfirst(alist);
AggrefExprState *aggrefstate = (AggrefExprState *) lfirst(alist);
Aggref *aggref = (Aggref *) aggrefstate->xprstate.expr;
AggStatePerAgg peraggstate = &peragg[++aggno];
HeapTuple aggTuple;
Form_pg_aggregate aggform;
@ -1236,10 +1239,11 @@ ExecInitAgg(Agg *node, EState *estate)
finalfn_oid;
Datum textInitVal;
/* Mark Aggref node with its associated index in the result array */
aggref->aggno = aggno;
/* Mark Aggref state node with assigned index in the result array */
aggrefstate->aggno = aggno;
/* Fill in the peraggstate data */
peraggstate->aggrefstate = aggrefstate;
peraggstate->aggref = aggref;
aggTuple = SearchSysCache(AGGFNOID,

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.14 2002/12/05 15:50:33 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.15 2002/12/13 19:45:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -172,10 +172,10 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate)
* initialize child expressions
*/
scanstate->ss.ps.targetlist = (List *)
ExecInitExpr((Node *) node->scan.plan.targetlist,
ExecInitExpr((Expr *) node->scan.plan.targetlist,
(PlanState *) scanstate);
scanstate->ss.ps.qual = (List *)
ExecInitExpr((Node *) node->scan.plan.qual,
ExecInitExpr((Expr *) node->scan.plan.qual,
(PlanState *) scanstate);
/*
@ -241,7 +241,8 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate)
* Other node-specific setup
*/
scanstate->tuplestorestate = NULL;
scanstate->funcexpr = rte->funcexpr;
scanstate->funcexpr = ExecInitExpr((Expr *) rte->funcexpr,
(PlanState *) scanstate);
scanstate->ss.ps.ps_TupFromTlist = false;

View File

@ -15,7 +15,7 @@
* locate group boundaries.
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.51 2002/12/05 15:50:33 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.52 2002/12/13 19:45:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -168,10 +168,10 @@ ExecInitGroup(Group *node, EState *estate)
* initialize child expressions
*/
grpstate->ss.ps.targetlist = (List *)
ExecInitExpr((Node *) node->plan.targetlist,
ExecInitExpr((Expr *) node->plan.targetlist,
(PlanState *) grpstate);
grpstate->ss.ps.qual = (List *)
ExecInitExpr((Node *) node->plan.qual,
ExecInitExpr((Expr *) node->plan.qual,
(PlanState *) grpstate);
/*

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeHash.c,v 1.69 2002/12/05 15:50:33 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/nodeHash.c,v 1.70 2002/12/13 19:45:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -76,7 +76,7 @@ ExecHash(HashState *node)
/*
* set expression context
*/
hashkeys = ((Hash *) node->ps.plan)->hashkeys;
hashkeys = node->hashkeys;
econtext = node->ps.ps_ExprContext;
/*
@ -138,10 +138,10 @@ ExecInitHash(Hash *node, EState *estate)
* initialize child expressions
*/
hashstate->ps.targetlist = (List *)
ExecInitExpr((Node *) node->plan.targetlist,
ExecInitExpr((Expr *) node->plan.targetlist,
(PlanState *) hashstate);
hashstate->ps.qual = (List *)
ExecInitExpr((Node *) node->plan.qual,
ExecInitExpr((Expr *) node->plan.qual,
(PlanState *) hashstate);
/*
@ -554,7 +554,8 @@ ExecHashGetBucket(HashJoinTable hashtable,
/*
* Get the join attribute value of the tuple
*/
keyval = ExecEvalExpr(lfirst(hk), econtext, &isNull, NULL);
keyval = ExecEvalExpr((ExprState *) lfirst(hk),
econtext, &isNull, NULL);
/*
* Compute the hash function

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.43 2002/12/05 15:50:33 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.44 2002/12/13 19:45:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -169,7 +169,7 @@ ExecHashJoin(HashJoinState *node)
* for this tuple from the hash table
*/
node->hj_CurBucketNo = ExecHashGetBucket(hashtable, econtext,
outerkeys);
outerkeys);
node->hj_CurTuple = NULL;
/*
@ -302,6 +302,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate)
HashJoinState *hjstate;
Plan *outerNode;
Hash *hashNode;
List *hclauses;
List *hcl;
/*
@ -322,17 +323,17 @@ ExecInitHashJoin(HashJoin *node, EState *estate)
* initialize child expressions
*/
hjstate->js.ps.targetlist = (List *)
ExecInitExpr((Node *) node->join.plan.targetlist,
ExecInitExpr((Expr *) node->join.plan.targetlist,
(PlanState *) hjstate);
hjstate->js.ps.qual = (List *)
ExecInitExpr((Node *) node->join.plan.qual,
ExecInitExpr((Expr *) node->join.plan.qual,
(PlanState *) hjstate);
hjstate->js.jointype = node->join.jointype;
hjstate->js.joinqual = (List *)
ExecInitExpr((Node *) node->join.joinqual,
ExecInitExpr((Expr *) node->join.joinqual,
(PlanState *) hjstate);
hjstate->hashclauses = (List *)
ExecInitExpr((Node *) node->hashclauses,
ExecInitExpr((Expr *) node->hashclauses,
(PlanState *) hjstate);
/*
@ -402,15 +403,23 @@ ExecInitHashJoin(HashJoin *node, EState *estate)
/*
* The planner already made a list of the inner hashkeys for us,
* but we also need a list of the outer hashkeys.
* but we also need a list of the outer hashkeys. Each list of
* exprs must then be prepared for execution.
*/
hjstate->hj_InnerHashKeys = hashNode->hashkeys;
hjstate->hj_OuterHashKeys = NIL;
hjstate->hj_InnerHashKeys = (List *)
ExecInitExpr((Expr *) hashNode->hashkeys,
innerPlanState(hjstate));
((HashState *) innerPlanState(hjstate))->hashkeys =
hjstate->hj_InnerHashKeys;
hclauses = NIL;
foreach(hcl, node->hashclauses)
{
hjstate->hj_OuterHashKeys = lappend(hjstate->hj_OuterHashKeys,
get_leftop(lfirst(hcl)));
hclauses = lappend(hclauses, get_leftop(lfirst(hcl)));
}
hjstate->hj_OuterHashKeys = (List *)
ExecInitExpr((Expr *) hclauses,
(PlanState *) hjstate);
hjstate->js.ps.ps_OuterTupleSlot = NULL;
hjstate->js.ps.ps_TupFromTlist = false;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.73 2002/12/12 15:49:24 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.74 2002/12/13 19:45:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -283,7 +283,7 @@ ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt)
int numIndices;
IndexScanDescPtr scanDescs;
ScanKey *scanKeys;
int **runtimeKeyInfo;
ExprState ***runtimeKeyInfo;
int *numScanKeys;
Index scanrelid;
int i;
@ -328,29 +328,18 @@ ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt)
*/
if (runtimeKeyInfo)
{
List *indxqual;
indxqual = node->indxqual;
for (i = 0; i < numIndices; i++)
{
List *qual = lfirst(indxqual);
int n_keys;
ScanKey scan_keys;
int *run_keys;
List *listscan;
ExprState **run_keys;
indxqual = lnext(indxqual);
n_keys = numScanKeys[i];
scan_keys = scanKeys[i];
run_keys = runtimeKeyInfo[i];
listscan = qual;
for (j = 0; j < n_keys; j++)
{
Expr *clause = lfirst(listscan);
listscan = lnext(listscan);
/*
* If we have a run-time key, then extract the run-time
* expression and evaluate it with respect to the current
@ -364,17 +353,12 @@ ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt)
* is wrong, we could copy the result into our context
* explicitly, but I think that's not necessary...
*/
if (run_keys[j] != NO_OP)
if (run_keys[j] != NULL)
{
Node *scanexpr;
Datum scanvalue;
bool isNull;
scanexpr = (run_keys[j] == RIGHT_OP) ?
(Node *) get_rightop(clause) :
(Node *) get_leftop(clause);
scanvalue = ExecEvalExprSwitchContext(scanexpr,
scanvalue = ExecEvalExprSwitchContext(run_keys[j],
econtext,
&isNull,
NULL);
@ -424,7 +408,7 @@ ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt)
void
ExecEndIndexScan(IndexScanState *node)
{
int **runtimeKeyInfo;
ExprState ***runtimeKeyInfo;
ScanKey *scanKeys;
int *numScanKeys;
int numIndices;
@ -585,7 +569,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
int *numScanKeys;
RelationPtr indexDescs;
IndexScanDescPtr scanDescs;
int **runtimeKeyInfo;
ExprState ***runtimeKeyInfo;
bool have_runtime_keys;
RangeTblEntry *rtentry;
Index relid;
@ -610,16 +594,16 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
* initialize child expressions
*/
indexstate->ss.ps.targetlist = (List *)
ExecInitExpr((Node *) node->scan.plan.targetlist,
ExecInitExpr((Expr *) node->scan.plan.targetlist,
(PlanState *) indexstate);
indexstate->ss.ps.qual = (List *)
ExecInitExpr((Node *) node->scan.plan.qual,
ExecInitExpr((Expr *) node->scan.plan.qual,
(PlanState *) indexstate);
indexstate->indxqual = (List *)
ExecInitExpr((Node *) node->indxqual,
ExecInitExpr((Expr *) node->indxqual,
(PlanState *) indexstate);
indexstate->indxqualorig = (List *)
ExecInitExpr((Node *) node->indxqualorig,
ExecInitExpr((Expr *) node->indxqualorig,
(PlanState *) indexstate);
#define INDEXSCAN_NSLOTS 2
@ -672,7 +656,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
* initialize space for runtime key info (may not be needed)
*/
have_runtime_keys = false;
runtimeKeyInfo = (int **) palloc(numIndices * sizeof(int *));
runtimeKeyInfo = (ExprState ***) palloc0(numIndices * sizeof(ExprState **));
/*
* build the index scan keys from the index qualification
@ -684,15 +668,15 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
List *qual;
int n_keys;
ScanKey scan_keys;
int *run_keys;
ExprState **run_keys;
qual = lfirst(indxqual);
indxqual = lnext(indxqual);
n_keys = length(qual);
scan_keys = (n_keys <= 0) ? (ScanKey) NULL :
(ScanKey) palloc(n_keys * sizeof(ScanKeyData));
run_keys = (n_keys <= 0) ? (int *) NULL :
(int *) palloc(n_keys * sizeof(int));
run_keys = (n_keys <= 0) ? (ExprState **) NULL :
(ExprState **) palloc(n_keys * sizeof(ExprState *));
CXT1_printf("ExecInitIndexScan: context is %d\n", CurrentMemoryContext);
@ -704,8 +688,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
for (j = 0; j < n_keys; j++)
{
OpExpr *clause; /* one clause of index qual */
Node *leftop; /* expr on lhs of operator */
Node *rightop; /* expr on rhs ... */
Expr *leftop; /* expr on lhs of operator */
Expr *rightop; /* expr on rhs ... */
bits16 flags = 0;
int scanvar; /* which var identifies varattno */
@ -740,9 +724,9 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
* which case we need to recalculate the index scan key at run
* time.
*
* Hence, we set have_runtime_keys to true and then set the
* appropriate flag in run_keys to LEFT_OP or RIGHT_OP. The
* corresponding scan keys are recomputed at run time.
* Hence, we set have_runtime_keys to true and place the
* appropriate subexpression in run_keys. The corresponding
* scan key values are recomputed at run time.
*
* XXX Although this code *thinks* it can handle an indexqual
* with the indexkey on either side, in fact it cannot.
@ -760,19 +744,20 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
*/
scanvar = NO_OP;
run_keys[j] = NO_OP;
run_keys[j] = NULL;
/*
* determine information in leftop
*/
leftop = (Node *) get_leftop((Expr *) clause);
leftop = (Expr *) get_leftop((Expr *) clause);
if (leftop && IsA(leftop, RelabelType))
leftop = (Node *) ((RelabelType *) leftop)->arg;
leftop = ((RelabelType *) leftop)->arg;
Assert(leftop != NULL);
if (IsA(leftop, Var) &&var_is_rel((Var *) leftop))
if (IsA(leftop, Var) &&
var_is_rel((Var *) leftop))
{
/*
* if the leftop is a "rel-var", then it means that it is
@ -792,32 +777,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
if (((Const *) leftop)->constisnull)
flags |= SK_ISNULL;
}
else if (IsA(leftop, Param))
{
bool isnull;
/*
* if the leftop is a Param node then it means it
* identifies the value to place in our scan key.
*/
/* Life was so easy before ... subselects */
if (((Param *) leftop)->paramkind == PARAM_EXEC)
{
/* treat Param as runtime key */
have_runtime_keys = true;
run_keys[j] = LEFT_OP;
}
else
{
/* treat Param like a constant */
scanvalue = ExecEvalParam((Param *) leftop,
indexstate->ss.ps.ps_ExprContext,
&isnull);
if (isnull)
flags |= SK_ISNULL;
}
}
else
{
/*
@ -826,20 +785,21 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
* key.
*/
have_runtime_keys = true;
run_keys[j] = LEFT_OP;
run_keys[j] = ExecInitExpr(leftop, (PlanState *) indexstate);
}
/*
* now determine information in rightop
*/
rightop = (Node *) get_rightop((Expr *) clause);
rightop = (Expr *) get_rightop((Expr *) clause);
if (rightop && IsA(rightop, RelabelType))
rightop = (Node *) ((RelabelType *) rightop)->arg;
rightop = ((RelabelType *) rightop)->arg;
Assert(rightop != NULL);
if (IsA(rightop, Var) &&var_is_rel((Var *) rightop))
if (IsA(rightop, Var) &&
var_is_rel((Var *) rightop))
{
/*
* here we make sure only one op identifies the
@ -867,32 +827,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
if (((Const *) rightop)->constisnull)
flags |= SK_ISNULL;
}
else if (IsA(rightop, Param))
{
bool isnull;
/*
* if the rightop is a Param node then it means it
* identifies the value to place in our scan key.
*/
/* Life was so easy before ... subselects */
if (((Param *) rightop)->paramkind == PARAM_EXEC)
{
/* treat Param as runtime key */
have_runtime_keys = true;
run_keys[j] = RIGHT_OP;
}
else
{
/* treat Param like a constant */
scanvalue = ExecEvalParam((Param *) rightop,
indexstate->ss.ps.ps_ExprContext,
&isnull);
if (isnull)
flags |= SK_ISNULL;
}
}
else
{
/*
@ -901,7 +835,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate)
* key.
*/
have_runtime_keys = true;
run_keys[j] = RIGHT_OP;
run_keys[j] = ExecInitExpr(rightop, (PlanState *) indexstate);
}
/*

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeLimit.c,v 1.12 2002/12/05 15:50:33 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/nodeLimit.c,v 1.13 2002/12/13 19:45:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -301,9 +301,9 @@ ExecInitLimit(Limit *node, EState *estate)
/*
* initialize child expressions
*/
limitstate->limitOffset = ExecInitExpr(node->limitOffset,
limitstate->limitOffset = ExecInitExpr((Expr *) node->limitOffset,
(PlanState *) limitstate);
limitstate->limitCount = ExecInitExpr(node->limitCount,
limitstate->limitCount = ExecInitExpr((Expr *) node->limitCount,
(PlanState *) limitstate);
#define LIMIT_NSLOTS 1

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.53 2002/12/12 15:49:25 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.54 2002/12/13 19:45:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -101,23 +101,26 @@ static bool MergeCompare(List *eqQual, List *compareQual, ExprContext *econtext)
* ----------------------------------------------------------------
*/
static void
MJFormSkipQuals(List *qualList, List **ltQuals, List **gtQuals)
MJFormSkipQuals(List *qualList, List **ltQuals, List **gtQuals,
PlanState *parent)
{
List *ltcdr,
List *ltexprs,
*gtexprs,
*ltcdr,
*gtcdr;
/*
* Make modifiable copies of the qualList.
*/
*ltQuals = (List *) copyObject((Node *) qualList);
*gtQuals = (List *) copyObject((Node *) qualList);
ltexprs = (List *) copyObject((Node *) qualList);
gtexprs = (List *) copyObject((Node *) qualList);
/*
* Scan both lists in parallel, so that we can update the operators
* with the minimum number of syscache searches.
*/
ltcdr = *ltQuals;
foreach(gtcdr, *gtQuals)
ltcdr = ltexprs;
foreach(gtcdr, gtexprs)
{
OpExpr *ltop = (OpExpr *) lfirst(ltcdr);
OpExpr *gtop = (OpExpr *) lfirst(gtcdr);
@ -137,11 +140,15 @@ MJFormSkipQuals(List *qualList, List **ltQuals, List **gtQuals)
&gtop->opno,
&ltop->opfuncid,
&gtop->opfuncid);
ltop->op_fcache = NULL;
gtop->op_fcache = NULL;
ltcdr = lnext(ltcdr);
}
/*
* Prepare both lists for execution.
*/
*ltQuals = (List *) ExecInitExpr((Expr *) ltexprs, parent);
*gtQuals = (List *) ExecInitExpr((Expr *) gtexprs, parent);
}
/* ----------------------------------------------------------------
@ -193,8 +200,10 @@ MergeCompare(List *eqQual, List *compareQual, ExprContext *econtext)
*
* A NULL result is considered false.
*/
const_value = ExecEvalExpr((Node *) lfirst(clause), econtext,
&isNull, NULL);
const_value = ExecEvalExpr((ExprState *) lfirst(clause),
econtext,
&isNull,
NULL);
if (DatumGetBool(const_value) && !isNull)
{
@ -208,7 +217,7 @@ MergeCompare(List *eqQual, List *compareQual, ExprContext *econtext)
* key1 = key2 so we move on to the next pair of keys.
*-----------
*/
const_value = ExecEvalExpr((Node *) lfirst(eqclause),
const_value = ExecEvalExpr((ExprState *) lfirst(eqclause),
econtext,
&isNull,
NULL);
@ -1409,17 +1418,17 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate)
* initialize child expressions
*/
mergestate->js.ps.targetlist = (List *)
ExecInitExpr((Node *) node->join.plan.targetlist,
ExecInitExpr((Expr *) node->join.plan.targetlist,
(PlanState *) mergestate);
mergestate->js.ps.qual = (List *)
ExecInitExpr((Node *) node->join.plan.qual,
ExecInitExpr((Expr *) node->join.plan.qual,
(PlanState *) mergestate);
mergestate->js.jointype = node->join.jointype;
mergestate->js.joinqual = (List *)
ExecInitExpr((Node *) node->join.joinqual,
ExecInitExpr((Expr *) node->join.joinqual,
(PlanState *) mergestate);
mergestate->mergeclauses = (List *)
ExecInitExpr((Node *) node->mergeclauses,
ExecInitExpr((Expr *) node->mergeclauses,
(PlanState *) mergestate);
/*
@ -1492,7 +1501,8 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate)
*/
MJFormSkipQuals(node->mergeclauses,
&mergestate->mj_OuterSkipQual,
&mergestate->mj_InnerSkipQual);
&mergestate->mj_InnerSkipQual,
(PlanState *) mergestate);
MJ_printf("\nExecInitMergeJoin: OuterSkipQual is ");
MJ_nodeDisplay(mergestate->mj_OuterSkipQual);

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeNestloop.c,v 1.27 2002/12/05 15:50:33 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/nodeNestloop.c,v 1.28 2002/12/13 19:45:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -286,14 +286,14 @@ ExecInitNestLoop(NestLoop *node, EState *estate)
* initialize child expressions
*/
nlstate->js.ps.targetlist = (List *)
ExecInitExpr((Node *) node->join.plan.targetlist,
ExecInitExpr((Expr *) node->join.plan.targetlist,
(PlanState *) nlstate);
nlstate->js.ps.qual = (List *)
ExecInitExpr((Node *) node->join.plan.qual,
ExecInitExpr((Expr *) node->join.plan.qual,
(PlanState *) nlstate);
nlstate->js.jointype = node->join.jointype;
nlstate->js.joinqual = (List *)
ExecInitExpr((Node *) node->join.joinqual,
ExecInitExpr((Expr *) node->join.joinqual,
(PlanState *) nlstate);
/*

View File

@ -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.22 2002/12/05 15:50:33 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/nodeResult.c,v 1.23 2002/12/13 19:45:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -205,12 +205,12 @@ ExecInitResult(Result *node, EState *estate)
* initialize child expressions
*/
resstate->ps.targetlist = (List *)
ExecInitExpr((Node *) node->plan.targetlist,
ExecInitExpr((Expr *) node->plan.targetlist,
(PlanState *) resstate);
resstate->ps.qual = (List *)
ExecInitExpr((Node *) node->plan.qual,
ExecInitExpr((Expr *) node->plan.qual,
(PlanState *) resstate);
resstate->resconstantqual = ExecInitExpr(node->resconstantqual,
resstate->resconstantqual = ExecInitExpr((Expr *) node->resconstantqual,
(PlanState *) resstate);
/*

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.39 2002/12/05 15:50:33 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.40 2002/12/13 19:45:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -207,10 +207,10 @@ ExecInitSeqScan(SeqScan *node, EState *estate)
* initialize child expressions
*/
scanstate->ps.targetlist = (List *)
ExecInitExpr((Node *) node->plan.targetlist,
ExecInitExpr((Expr *) node->plan.targetlist,
(PlanState *) scanstate);
scanstate->ps.qual = (List *)
ExecInitExpr((Node *) node->plan.qual,
ExecInitExpr((Expr *) node->plan.qual,
(PlanState *) scanstate);
#define SEQSCAN_NSLOTS 2

View File

@ -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.36 2002/12/12 15:49:27 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.37 2002/12/13 19:45:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -30,11 +30,12 @@
* ----------------------------------------------------------------
*/
Datum
ExecSubPlan(SubPlanState *node, List *pvar,
ExprContext *econtext, bool *isNull)
ExecSubPlan(SubPlanExprState *node,
ExprContext *econtext,
bool *isNull)
{
PlanState *planstate = node->planstate;
SubPlanExpr *subplan = (SubPlanExpr *) node->ps.plan;
SubPlanExpr *subplan = (SubPlanExpr *) node->xprstate.expr;
SubLink *sublink = subplan->sublink;
SubLinkType subLinkType = sublink->subLinkType;
bool useor = sublink->useor;
@ -42,6 +43,7 @@ ExecSubPlan(SubPlanState *node, List *pvar,
TupleTableSlot *slot;
Datum result;
bool found = false; /* TRUE if got at least one subplan tuple */
List *pvar;
List *lst;
/*
@ -56,6 +58,7 @@ ExecSubPlan(SubPlanState *node, List *pvar,
/*
* Set Params of this plan from parent plan correlation Vars
*/
pvar = node->args;
if (subplan->parParam != NIL)
{
foreach(lst, subplan->parParam)
@ -64,7 +67,7 @@ ExecSubPlan(SubPlanState *node, List *pvar,
prm = &(econtext->ecxt_param_exec_vals[lfirsti(lst)]);
Assert(pvar != NIL);
prm->value = ExecEvalExprSwitchContext((Node *) lfirst(pvar),
prm->value = ExecEvalExprSwitchContext((ExprState *) lfirst(pvar),
econtext,
&(prm->isnull),
NULL);
@ -149,9 +152,10 @@ ExecSubPlan(SubPlanState *node, List *pvar,
* For ALL, ANY, and MULTIEXPR sublinks, iterate over combining
* operators for columns of tuple.
*/
foreach(lst, sublink->oper)
foreach(lst, node->oper)
{
OpExpr *expr = (OpExpr *) lfirst(lst);
ExprState *exprstate = (ExprState *) lfirst(lst);
OpExpr *expr = (OpExpr *) exprstate->expr;
Param *prm = lsecond(expr->args);
ParamExecData *prmdata;
Datum expresult;
@ -194,7 +198,7 @@ ExecSubPlan(SubPlanState *node, List *pvar,
/*
* Now we can eval the combining operator for this column.
*/
expresult = ExecEvalExprSwitchContext((Node *) expr, econtext,
expresult = ExecEvalExprSwitchContext(exprstate, econtext,
&expnull, NULL);
/*
@ -287,64 +291,57 @@ ExecSubPlan(SubPlanState *node, List *pvar,
* ExecInitSubPlan
* ----------------------------------------------------------------
*/
SubPlanState *
ExecInitSubPlan(SubPlanExpr *node, EState *estate)
void
ExecInitSubPlan(SubPlanExprState *sstate, EState *estate)
{
SubPlanState *subplanstate;
SubPlanExpr *expr = (SubPlanExpr *) sstate->xprstate.expr;
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);
ExecCheckRTPerms(expr->rtable, CMD_SELECT);
/*
* create state structure
* initialize state
*/
subplanstate = makeNode(SubPlanState);
subplanstate->ps.plan = (Plan *) node;
subplanstate->ps.state = estate;
subplanstate->needShutdown = false;
subplanstate->curTuple = NULL;
/* XXX temporary hack */
node->pstate = subplanstate;
sstate->needShutdown = false;
sstate->curTuple = NULL;
/*
* create an EState for the subplan
*/
sp_estate = CreateExecutorState();
sp_estate->es_range_table = node->rtable;
sp_estate->es_range_table = expr->rtable;
sp_estate->es_param_list_info = estate->es_param_list_info;
sp_estate->es_param_exec_vals = estate->es_param_exec_vals;
sp_estate->es_tupleTable =
ExecCreateTupleTable(ExecCountSlotsNode(node->plan) + 10);
ExecCreateTupleTable(ExecCountSlotsNode(expr->plan) + 10);
sp_estate->es_snapshot = estate->es_snapshot;
sp_estate->es_instrument = estate->es_instrument;
/*
* Start up the subplan
*/
subplanstate->planstate = ExecInitNode(node->plan, sp_estate);
sstate->planstate = ExecInitNode(expr->plan, sp_estate);
subplanstate->needShutdown = true; /* now we need to shutdown the subplan */
sstate->needShutdown = true; /* now we need to shutdown the subplan */
/*
* If this plan is un-correlated or undirect correlated one and want
* to set params for parent plan then prepare parameters.
*/
if (node->setParam != NIL)
if (expr->setParam != NIL)
{
List *lst;
foreach(lst, node->setParam)
foreach(lst, expr->setParam)
{
ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
prm->execPlan = subplanstate;
prm->execPlan = sstate;
}
/*
@ -353,8 +350,6 @@ ExecInitSubPlan(SubPlanExpr *node, EState *estate)
* it, for others - it doesn't matter...
*/
}
return subplanstate;
}
/* ----------------------------------------------------------------
@ -371,12 +366,11 @@ ExecInitSubPlan(SubPlanExpr *node, EState *estate)
* ----------------------------------------------------------------
*/
void
ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
ExecSetParamPlan(SubPlanExprState *node, ExprContext *econtext)
{
PlanState *planstate = node->planstate;
SubPlanExpr *subplan = (SubPlanExpr *) node->ps.plan;
SubLink *sublink = subplan->sublink;
EState *estate = node->ps.state;
SubPlanExpr *subplan = (SubPlanExpr *) node->xprstate.expr;
SubLinkType subLinkType = subplan->sublink->subLinkType;
MemoryContext oldcontext;
TupleTableSlot *slot;
List *lst;
@ -388,8 +382,8 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
*/
oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
if (sublink->subLinkType == ANY_SUBLINK ||
sublink->subLinkType == ALL_SUBLINK)
if (subLinkType == ANY_SUBLINK ||
subLinkType == ALL_SUBLINK)
elog(ERROR, "ExecSetParamPlan: ANY/ALL subselect unsupported");
if (planstate->chgParam != NULL)
@ -403,9 +397,9 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
TupleDesc tdesc = slot->ttc_tupleDescriptor;
int i = 1;
if (sublink->subLinkType == EXISTS_SUBLINK)
if (subLinkType == EXISTS_SUBLINK)
{
ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(subplan->setParam)]);
ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(subplan->setParam)]);
prm->execPlan = NULL;
prm->value = BoolGetDatum(true);
@ -415,8 +409,8 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
}
if (found &&
(sublink->subLinkType == EXPR_SUBLINK ||
sublink->subLinkType == MULTIEXPR_SUBLINK))
(subLinkType == EXPR_SUBLINK ||
subLinkType == MULTIEXPR_SUBLINK))
elog(ERROR, "More than one tuple returned by a subselect used as an expression.");
found = true;
@ -434,7 +428,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
foreach(lst, subplan->setParam)
{
ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(lst)]);
prm->execPlan = NULL;
prm->value = heap_getattr(tup, i, tdesc, &(prm->isnull));
@ -444,9 +438,9 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
if (!found)
{
if (sublink->subLinkType == EXISTS_SUBLINK)
if (subLinkType == EXISTS_SUBLINK)
{
ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(subplan->setParam)]);
ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(subplan->setParam)]);
prm->execPlan = NULL;
prm->value = BoolGetDatum(false);
@ -456,7 +450,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
{
foreach(lst, subplan->setParam)
{
ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]);
ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(lst)]);
prm->execPlan = NULL;
prm->value = (Datum) 0;
@ -479,7 +473,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
* ----------------------------------------------------------------
*/
void
ExecEndSubPlan(SubPlanState *node)
ExecEndSubPlan(SubPlanExprState *node)
{
if (node->needShutdown)
{
@ -494,11 +488,11 @@ ExecEndSubPlan(SubPlanState *node)
}
void
ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent)
ExecReScanSetParamPlan(SubPlanExprState *node, PlanState *parent)
{
PlanState *planstate = node->planstate;
SubPlanExpr *subplan = (SubPlanExpr *) node->ps.plan;
EState *estate = node->ps.state;
SubPlanExpr *subplan = (SubPlanExpr *) node->xprstate.expr;
EState *estate = parent->state;
List *lst;
if (subplan->parParam != NULL)
@ -509,8 +503,7 @@ ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent)
elog(ERROR, "ExecReScanSetParamPlan: extParam list of plan is NULL");
/*
* Don't actual re-scan: ExecSetParamPlan does re-scan if
* subplan->plan->chgParam is not NULL... ExecReScan (planstate, NULL);
* Don't actually re-scan: ExecSetParamPlan does it if needed.
*/
/*

View File

@ -12,7 +12,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.14 2002/12/05 15:50:33 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.15 2002/12/13 19:45:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -131,10 +131,10 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate)
* initialize child expressions
*/
subquerystate->ss.ps.targetlist = (List *)
ExecInitExpr((Node *) node->scan.plan.targetlist,
ExecInitExpr((Expr *) node->scan.plan.targetlist,
(PlanState *) subquerystate);
subquerystate->ss.ps.qual = (List *)
ExecInitExpr((Node *) node->scan.plan.qual,
ExecInitExpr((Expr *) node->scan.plan.qual,
(PlanState *) subquerystate);
#define SUBQUERYSCAN_NSLOTS 1

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.28 2002/12/05 15:50:34 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.29 2002/12/13 19:45:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -380,10 +380,10 @@ ExecInitTidScan(TidScan *node, EState *estate)
* initialize child expressions
*/
tidstate->ss.ps.targetlist = (List *)
ExecInitExpr((Node *) node->scan.plan.targetlist,
ExecInitExpr((Expr *) node->scan.plan.targetlist,
(PlanState *) tidstate);
tidstate->ss.ps.qual = (List *)
ExecInitExpr((Node *) node->scan.plan.qual,
ExecInitExpr((Expr *) node->scan.plan.qual,
(PlanState *) tidstate);
#define TIDSCAN_NSLOTS 2
@ -404,7 +404,10 @@ ExecInitTidScan(TidScan *node, EState *estate)
* get the tid node information
*/
tidList = (ItemPointerData *) palloc(length(node->tideval) * sizeof(ItemPointerData));
numTids = TidListCreate(node->tideval,
tidstate->tss_tideval = (List *)
ExecInitExpr((Expr *) node->tideval,
(PlanState *) tidstate);
numTids = TidListCreate(tidstate->tss_tideval,
tidstate->ss.ps.ps_ExprContext,
tidList);
tidPtr = -1;

View File

@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.231 2002/12/12 20:35:12 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.232 2002/12/13 19:45:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -710,7 +710,6 @@ _copyAggref(Aggref *from)
COPY_NODE_FIELD(target);
COPY_SCALAR_FIELD(aggstar);
COPY_SCALAR_FIELD(aggdistinct);
COPY_SCALAR_FIELD(aggno); /* will go away soon */
return newnode;
}
@ -750,9 +749,6 @@ _copyFuncExpr(FuncExpr *from)
COPY_SCALAR_FIELD(funcformat);
COPY_NODE_FIELD(args);
/* Do not copy the run-time state, if any */
newnode->func_fcache = NULL;
return newnode;
}
@ -770,9 +766,6 @@ _copyOpExpr(OpExpr *from)
COPY_SCALAR_FIELD(opretset);
COPY_NODE_FIELD(args);
/* Do not copy the run-time state, if any */
newnode->op_fcache = NULL;
return newnode;
}
@ -790,9 +783,6 @@ _copyDistinctExpr(DistinctExpr *from)
COPY_SCALAR_FIELD(opretset);
COPY_NODE_FIELD(args);
/* Do not copy the run-time state, if any */
newnode->op_fcache = NULL;
return newnode;
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/nodeFuncs.c,v 1.20 2002/12/12 15:49:28 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/nodeFuncs.c,v 1.21 2002/12/13 19:45:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -88,5 +88,4 @@ set_opfuncid(OpExpr *opexpr)
{
if (opexpr->opfuncid == InvalidOid)
opexpr->opfuncid = get_opcode(opexpr->opno);
opexpr->op_fcache = NULL; /* XXX will go away soon */
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.188 2002/12/12 20:35:12 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.189 2002/12/13 19:45:56 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
@ -214,8 +214,6 @@ _outDatum(StringInfo str, Datum value, int typlen, bool typbyval)
/*
* print the basic stuff of all nodes that inherit from Plan
*
* NOTE: we deliberately omit the execution state (EState)
*/
static void
_outPlanInfo(StringInfo str, Plan *node)

View File

@ -8,12 +8,13 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.142 2002/12/12 20:35:12 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.143 2002/12/13 19:45:56 tgl Exp $
*
* NOTES
* Path and Plan nodes do not have any readfuncs support, because we
* never have occasion to read them in. (There was once code here that
* claimed to read them, but it was broken as well as unused.)
* claimed to read them, but it was broken as well as unused.) We
* never read executor state trees, either.
*
*-------------------------------------------------------------------------
*/
@ -439,8 +440,6 @@ _readFuncExpr(void)
READ_ENUM_FIELD(funcformat, CoercionForm);
READ_NODE_FIELD(args);
local_node->func_fcache = NULL;
READ_DONE();
}
@ -468,8 +467,6 @@ _readOpExpr(void)
READ_BOOL_FIELD(opretset);
READ_NODE_FIELD(args);
local_node->op_fcache = NULL;
READ_DONE();
}
@ -497,8 +494,6 @@ _readDistinctExpr(void)
READ_BOOL_FIELD(opretset);
READ_NODE_FIELD(args);
local_node->op_fcache = NULL;
READ_DONE();
}

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.127 2002/12/12 15:49:28 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.128 2002/12/13 19:45:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1124,6 +1124,7 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
clause_strategy,
test_strategy;
Expr *test_expr;
ExprState *test_exprstate;
Datum test_result;
bool isNull;
Relation relation;
@ -1274,9 +1275,10 @@ pred_test_simple_clause(Expr *predicate, Node *clause)
(Expr *) clause_const,
(Expr *) pred_const);
set_opfuncid((OpExpr *) test_expr);
test_exprstate = ExecInitExpr(test_expr, NULL);
econtext = MakeExprContext(NULL, TransactionCommandContext);
test_result = ExecEvalExprSwitchContext((Node *) test_expr, econtext,
econtext = MakeExprContext(NULL, CurrentMemoryContext);
test_result = ExecEvalExprSwitchContext(test_exprstate, econtext,
&isNull, NULL);
FreeExprContext(econtext);

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.117 2002/12/12 20:35:12 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.118 2002/12/13 19:45:56 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@ -1315,7 +1315,18 @@ eval_const_expressions_mutator(Node *node, List *active_fns)
simple = simplify_function(expr->opfuncid, args,
false, active_fns);
if (simple) /* successfully simplified it */
return (Node *) simple;
{
/*
* Since the underlying operator is "=", must negate its
* result
*/
Const *csimple = (Const *) simple;
Assert(IsA(csimple, Const));
csimple->constvalue =
BoolGetDatum(!DatumGetBool(csimple->constvalue));
return (Node *) csimple;
}
}
/*
@ -1672,6 +1683,7 @@ evaluate_function(Oid funcid, List *args, HeapTuple func_tuple)
bool has_nonconst_input = false;
bool has_null_input = false;
FuncExpr *newexpr;
ExprState *newexprstate;
ExprContext *econtext;
Datum const_val;
bool const_is_null;
@ -1738,7 +1750,9 @@ evaluate_function(Oid funcid, List *args, HeapTuple func_tuple)
*/
econtext = MakeExprContext(NULL, CurrentMemoryContext);
const_val = ExecEvalExprSwitchContext((Node *) newexpr, econtext,
newexprstate = ExecInitExpr((Expr *) newexpr, NULL);
const_val = ExecEvalExprSwitchContext(newexprstate, econtext,
&const_is_null, NULL);
/* Must copy result out of sub-context used by expression eval */
@ -1746,7 +1760,6 @@ evaluate_function(Oid funcid, List *args, HeapTuple func_tuple)
const_val = datumCopy(const_val, resultTypByVal, resultTypLen);
FreeExprContext(econtext);
pfree(newexpr);
/*
* Make the constant result node.

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.256 2002/12/12 20:35:12 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.257 2002/12/13 19:45:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -23,7 +23,6 @@
#include "commands/prepare.h"
#include "nodes/makefuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/planmain.h"
#include "parser/analyze.h"
#include "parser/gramparse.h"
#include "parser/parsetree.h"
@ -2424,8 +2423,6 @@ transformExecuteStmt(ParseState *pstate, ExecuteStmt *stmt)
format_type_be(given_type_id),
format_type_be(expected_type_id));
fix_opfuncids(expr);
lfirst(l) = expr;
paramtypes = lnext(paramtypes);

View File

@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.54 2002/09/04 20:31:29 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/Attic/sets.c,v 1.55 2002/12/13 19:45:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -24,7 +24,6 @@
#include "catalog/pg_namespace.h"
#include "catalog/pg_proc.h"
#include "executor/executor.h"
#include "utils/fcache.h"
#include "utils/fmgroids.h"
#include "utils/sets.h"
#include "utils/syscache.h"
@ -143,7 +142,7 @@ Datum
seteval(PG_FUNCTION_ARGS)
{
Oid funcoid = PG_GETARG_OID(0);
FunctionCachePtr fcache;
FuncExprState *fcache;
Datum result;
bool isNull;
ExprDoneCond isDone;
@ -152,10 +151,27 @@ seteval(PG_FUNCTION_ARGS)
* If this is the first call, we need to set up the fcache for the
* target set's function.
*/
fcache = (FunctionCachePtr) fcinfo->flinfo->fn_extra;
fcache = (FuncExprState *) fcinfo->flinfo->fn_extra;
if (fcache == NULL)
{
fcache = init_fcache(funcoid, 0, fcinfo->flinfo->fn_mcxt);
MemoryContext oldcontext;
FuncExpr *func;
oldcontext = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt);
func = makeNode(FuncExpr);
func->funcid = funcoid;
func->funcresulttype = InvalidOid; /* nothing will look at this */
func->funcretset = true;
func->funcformat = COERCE_EXPLICIT_CALL;
func->args = NIL; /* there are no arguments */
fcache = (FuncExprState *) ExecInitExpr((Expr *) func, NULL);
MemoryContextSwitchTo(oldcontext);
init_fcache(funcoid, fcache, fcinfo->flinfo->fn_mcxt);
fcinfo->flinfo->fn_extra = (void *) fcache;
}
@ -169,22 +185,10 @@ seteval(PG_FUNCTION_ARGS)
isDone = ExprSingleResult;
result = ExecMakeFunctionResult(fcache,
NIL,
NULL, /* no econtext, see above */
&isNull,
&isDone);
/*
* If we're done with the results of this set function, get rid of its
* func cache so that we will start from the top next time. (Can you
* say "memory leak"? This feature is a crock anyway...)
*/
if (isDone != ExprMultipleResult)
{
pfree(fcache);
fcinfo->flinfo->fn_extra = NULL;
}
/*
* Return isNull/isDone status.
*/

View File

@ -4,7 +4,7 @@
# Makefile for utils/cache
#
# IDENTIFICATION
# $Header: /cvsroot/pgsql/src/backend/utils/cache/Makefile,v 1.16 2002/03/31 06:26:31 tgl Exp $
# $Header: /cvsroot/pgsql/src/backend/utils/cache/Makefile,v 1.17 2002/12/13 19:45:56 tgl Exp $
#
#-------------------------------------------------------------------------
@ -12,8 +12,7 @@ subdir = src/backend/utils/cache
top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global
OBJS = catcache.o inval.o relcache.o syscache.o lsyscache.o \
fcache.o
OBJS = catcache.o inval.o relcache.o syscache.o lsyscache.o
all: SUBSYS.o

View File

@ -1,53 +0,0 @@
/*-------------------------------------------------------------------------
*
* fcache.c
* Code for the 'function cache' used in Oper and Func nodes.
*
*
* 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/utils/cache/Attic/fcache.c,v 1.45 2002/06/20 20:29:39 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "miscadmin.h"
#include "utils/acl.h"
#include "utils/fcache.h"
#include "utils/lsyscache.h"
/*
* Build a 'FunctionCache' struct given the PG_PROC oid.
*/
FunctionCachePtr
init_fcache(Oid foid, int nargs, MemoryContext fcacheCxt)
{
FunctionCachePtr retval;
AclResult aclresult;
/* Check permission to call function */
aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE);
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, get_func_name(foid));
/* Safety check (should never fail, as parser should check sooner) */
if (nargs > FUNC_MAX_ARGS)
elog(ERROR, "init_fcache: too many arguments");
/* Create fcache entry in the desired context */
retval = (FunctionCachePtr) MemoryContextAlloc(fcacheCxt,
sizeof(FunctionCache));
MemSet(retval, 0, sizeof(FunctionCache));
/* Set up the primary fmgr lookup information */
fmgr_info_cxt(foid, &(retval->func), fcacheCxt);
/* Initialize additional info */
retval->setArgsValid = false;
return retval;
}

View File

@ -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.81 2002/12/05 15:50:36 tgl Exp $
* $Id: executor.h,v 1.82 2002/12/13 19:45:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -73,26 +73,27 @@ extern TupleDesc ExecGetTupType(PlanState *node);
/*
* prototypes from functions in execQual.c
*/
extern Datum ExecEvalParam(Param *expression, ExprContext *econtext,
bool *isNull);
extern Datum GetAttributeByNum(TupleTableSlot *slot, AttrNumber attrno,
bool *isNull);
extern Datum GetAttributeByName(TupleTableSlot *slot, char *attname,
bool *isNull);
extern Datum ExecMakeFunctionResult(FunctionCachePtr fcache,
List *arguments,
extern void init_fcache(Oid foid, FuncExprState *fcache,
MemoryContext fcacheCxt);
extern Datum ExecMakeFunctionResult(FuncExprState *fcache,
ExprContext *econtext,
bool *isNull,
ExprDoneCond *isDone);
extern Tuplestorestate *ExecMakeTableFunctionResult(Node *funcexpr,
extern Tuplestorestate *ExecMakeTableFunctionResult(ExprState *funcexpr,
ExprContext *econtext,
TupleDesc expectedDesc,
TupleDesc *returnDesc);
extern Datum ExecEvalExpr(Node *expression, ExprContext *econtext,
extern Datum ExecEvalExpr(ExprState *expression, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
extern Datum ExecEvalExprSwitchContext(Node *expression, ExprContext *econtext,
extern Datum ExecEvalExprSwitchContext(ExprState *expression, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
extern Node *ExecInitExpr(Node *node, PlanState *parent);
extern ExprState *ExecInitExpr(Expr *node, PlanState *parent);
extern SubPlanExprState *ExecInitExprInitPlan(SubPlanExpr *node,
PlanState *parent);
extern bool ExecQual(List *qual, ExprContext *econtext, bool resultForNull);
extern int ExecTargetListLength(List *targetlist);
extern int ExecCleanTargetListLength(List *targetlist);

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: nodeSubplan.h,v 1.13 2002/12/12 15:49:40 tgl Exp $
* $Id: nodeSubplan.h,v 1.14 2002/12/13 19:45:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -16,12 +16,13 @@
#include "nodes/execnodes.h"
extern SubPlanState *ExecInitSubPlan(SubPlanExpr *node, EState *estate);
extern Datum ExecSubPlan(SubPlanState *node, List *pvar, ExprContext *econtext,
bool *isNull);
extern void ExecEndSubPlan(SubPlanState *node);
extern void ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent);
extern void ExecInitSubPlan(SubPlanExprState *sstate, EState *estate);
extern Datum ExecSubPlan(SubPlanExprState *node,
ExprContext *econtext,
bool *isNull);
extern void ExecEndSubPlan(SubPlanExprState *node);
extern void ExecReScanSetParamPlan(SubPlanExprState *node, PlanState *parent);
extern void ExecSetParamPlan(SubPlanState *node, ExprContext *econtext);
extern void ExecSetParamPlan(SubPlanExprState *node, ExprContext *econtext);
#endif /* NODESUBPLAN_H */

View File

@ -2,7 +2,7 @@
*
* spi.h
*
* $Id: spi.h,v 1.33 2001/11/08 20:37:52 momjian Exp $
* $Id: spi.h,v 1.34 2002/12/13 19:45:56 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -30,7 +30,6 @@
#include "tcop/utility.h"
#include "tcop/dest.h"
#include "nodes/params.h"
#include "utils/fcache.h"
#include "utils/datum.h"
#include "utils/syscache.h"
#include "utils/builtins.h"

View File

@ -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.83 2002/12/12 20:35:13 tgl Exp $
* $Id: execnodes.h,v 1.84 2002/12/13 19:45:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -36,6 +36,7 @@
* (ie, number of attrs from underlying relation)
* KeyAttrNumbers underlying-rel attribute numbers used as keys
* Predicate partial-index predicate, or NIL if none
* PredicateState exec state for predicate, or NIL if none
* FuncOid OID of function, or InvalidOid if not f. index
* FuncInfo fmgr lookup data for function, if FuncOid valid
* Unique is it a unique index?
@ -47,7 +48,8 @@ typedef struct IndexInfo
int ii_NumIndexAttrs;
int ii_NumKeyAttrs;
AttrNumber ii_KeyAttrNumbers[INDEX_MAX_KEYS];
List *ii_Predicate;
List *ii_Predicate; /* list of Expr */
List *ii_PredicateState; /* list of ExprState */
Oid ii_FuncOid;
FmgrInfo ii_FuncInfo;
bool ii_Unique;
@ -254,7 +256,7 @@ typedef struct JunkFilter
* IndexRelationInfo array of key/attr info for indices
* TrigDesc triggers to be fired, if any
* TrigFunctions cached lookup info for trigger functions
* ConstraintExprs array of constraint-checking expressions
* ConstraintExprs array of constraint-checking expr states
* junkFilter for removing junk attributes from tuples
* ----------------
*/
@ -332,7 +334,178 @@ typedef struct EState
/* ----------------------------------------------------------------
* Executor State Information
* Expression State Trees
*
* Each executable expression tree has a parallel ExprState tree.
*
* Unlike PlanState, there is not an exact one-for-one correspondence between
* ExprState node types and Expr node types. Many Expr node types have no
* need for node-type-specific run-time state, and so they can use plain
* ExprState or GenericExprState as their associated ExprState node type.
* ----------------------------------------------------------------
*/
/* ----------------
* ExprState node
*
* ExprState is the common superclass for all ExprState-type nodes.
*
* It can also be instantiated directly for leaf Expr nodes that need no
* local run-time state (such as Var, Const, or Param).
* ----------------
*/
typedef struct ExprState
{
NodeTag type;
Expr *expr; /* associated Expr node */
} ExprState;
/* ----------------
* GenericExprState node
*
* This is used for Expr node types that need no local run-time state,
* but have one child Expr node.
* ----------------
*/
typedef struct GenericExprState
{
ExprState xprstate;
ExprState *arg; /* state of my child node */
} GenericExprState;
/* ----------------
* AggrefExprState node
* ----------------
*/
typedef struct AggrefExprState
{
ExprState xprstate;
ExprState *target; /* state of my child node */
int aggno; /* ID number for agg within its plan node */
} AggrefExprState;
/* ----------------
* ArrayRefExprState node
* ----------------
*/
typedef struct ArrayRefExprState
{
ExprState xprstate;
List *refupperindexpr; /* states for child nodes */
List *reflowerindexpr;
ExprState *refexpr;
ExprState *refassgnexpr;
} ArrayRefExprState;
/* ----------------
* FuncExprState node
*
* Although named for FuncExpr, this is also used for OpExpr and DistinctExpr
* nodes; be careful to check what xprstate.expr is actually pointing at!
* ----------------
*/
typedef struct FuncExprState
{
ExprState xprstate;
List *args; /* states of argument expressions */
/*
* Function manager's lookup info for the target function. If func.fn_oid
* is InvalidOid, we haven't initialized it yet.
*/
FmgrInfo func;
/*
* We also need to store argument values across calls when evaluating a
* function-returning-set.
*
* setArgsValid is true when we are evaluating a set-valued function
* and we are in the middle of a call series; we want to pass the same
* argument values to the function again (and again, until it returns
* ExprEndResult).
*/
bool setArgsValid;
/*
* Flag to remember whether we found a set-valued argument to the
* function. This causes the function result to be a set as well.
* Valid only when setArgsValid is true.
*/
bool setHasSetArg; /* some argument returns a set */
/*
* Current argument data for a set-valued function; contains valid
* data only if setArgsValid is true.
*/
FunctionCallInfoData setArgs;
} FuncExprState;
/* ----------------
* BoolExprState node
* ----------------
*/
typedef struct BoolExprState
{
ExprState xprstate;
List *args; /* states of argument expression(s) */
} BoolExprState;
/* ----------------
* SubPlanExprState node
*
* Note: there is no separate ExprState node for the SubLink. All it would
* need is the oper field, which we can just as easily put here.
* ----------------
*/
typedef struct SubPlanExprState
{
ExprState xprstate;
struct PlanState *planstate; /* subselect plan's state tree */
bool needShutdown; /* TRUE = need to shutdown subplan */
HeapTuple curTuple; /* copy of most recent tuple from subplan */
List *args; /* states of argument expression(s) */
List *oper; /* states for executable combining exprs */
} SubPlanExprState;
/* ----------------
* CaseExprState node
* ----------------
*/
typedef struct CaseExprState
{
ExprState xprstate;
List *args; /* the arguments (list of WHEN clauses) */
ExprState *defresult; /* the default result (ELSE clause) */
} CaseExprState;
/* ----------------
* CaseWhenState node
* ----------------
*/
typedef struct CaseWhenState
{
ExprState xprstate;
ExprState *expr; /* condition expression */
ExprState *result; /* substitution result */
} CaseWhenState;
/* ----------------
* ConstraintTestState node
* ----------------
*/
typedef struct ConstraintTestState
{
ExprState xprstate;
ExprState *arg; /* input expression */
ExprState *check_expr; /* for CHECK test, a boolean expression */
} ConstraintTestState;
/* ----------------------------------------------------------------
* Executor State Trees
*
* An executing query has a PlanState tree paralleling the Plan tree
* that describes the plan.
* ----------------------------------------------------------------
*/
@ -365,9 +538,9 @@ typedef struct PlanState
List *qual; /* implicitly-ANDed qual conditions */
struct PlanState *lefttree; /* input plan tree(s) */
struct PlanState *righttree;
List *initPlan; /* Init SubPlanState nodes (un-correlated
List *initPlan; /* Init SubPlanExprState nodes (un-correlated
* expr subselects) */
List *subPlan; /* SubPlanState nodes in my expressions */
List *subPlan; /* SubPlanExprState nodes in my expressions */
/*
* State for management of parameter-change-driven rescanning
@ -403,7 +576,7 @@ typedef struct PlanState
typedef struct ResultState
{
PlanState ps; /* its first field is NodeTag */
Node *resconstantqual;
ExprState *resconstantqual;
bool rs_done; /* are we done? */
bool rs_checkqual; /* do we need to check the qual? */
} ResultState;
@ -467,7 +640,8 @@ typedef ScanState SeqScanState;
* IndexPtr current index in use
* ScanKeys Skey structures to scan index rels
* NumScanKeys array of no of keys in each Skey struct
* RuntimeKeyInfo array of array of flags for Skeys evaled at runtime
* RuntimeKeyInfo array of array of exprstates for Skeys
* that will be evaluated at runtime
* RuntimeContext expr context for evaling runtime Skeys
* RuntimeKeysReady true if runtime Skeys have been computed
* RelationDescs ptr to array of relation descriptors
@ -484,7 +658,7 @@ typedef struct IndexScanState
int iss_MarkIndexPtr;
ScanKey *iss_ScanKeys;
int *iss_NumScanKeys;
int **iss_RuntimeKeyInfo;
ExprState ***iss_RuntimeKeyInfo;
ExprContext *iss_RuntimeContext;
bool iss_RuntimeKeysReady;
RelationPtr iss_RelationDescs;
@ -502,6 +676,7 @@ typedef struct IndexScanState
typedef struct TidScanState
{
ScanState ss; /* its first field is NodeTag */
List *tss_tideval; /* list of ExprState nodes */
int tss_NumTids;
int tss_TidPtr;
int tss_MarkTidPtr;
@ -542,7 +717,7 @@ typedef struct FunctionScanState
ScanState ss; /* its first field is NodeTag */
TupleDesc tupdesc;
Tuplestorestate *tuplestorestate;
Node *funcexpr;
ExprState *funcexpr;
} FunctionScanState;
/* ----------------------------------------------------------------
@ -597,9 +772,9 @@ typedef struct NestLoopState
typedef struct MergeJoinState
{
JoinState js; /* its first field is NodeTag */
List *mergeclauses;
List *mj_OuterSkipQual;
List *mj_InnerSkipQual;
List *mergeclauses; /* list of ExprState nodes */
List *mj_OuterSkipQual; /* list of ExprState nodes */
List *mj_InnerSkipQual; /* list of ExprState nodes */
int mj_JoinState;
bool mj_MatchedOuter;
bool mj_MatchedInner;
@ -632,12 +807,12 @@ typedef struct MergeJoinState
typedef struct HashJoinState
{
JoinState js; /* its first field is NodeTag */
List *hashclauses;
List *hashclauses; /* list of ExprState nodes */
HashJoinTable hj_HashTable;
int hj_CurBucketNo;
HashJoinTuple hj_CurTuple;
List *hj_OuterHashKeys;
List *hj_InnerHashKeys;
List *hj_OuterHashKeys; /* list of ExprState nodes */
List *hj_InnerHashKeys; /* list of ExprState nodes */
TupleTableSlot *hj_OuterTupleSlot;
TupleTableSlot *hj_HashTupleSlot;
TupleTableSlot *hj_NullInnerTupleSlot;
@ -757,6 +932,8 @@ typedef struct HashState
{
PlanState ps; /* its first field is NodeTag */
HashJoinTable hashtable; /* hash table for the hashjoin */
List *hashkeys; /* list of ExprState nodes */
/* hashkeys is same as parent's hj_InnerHashKeys */
} HashState;
/* ----------------
@ -804,8 +981,8 @@ typedef enum
typedef struct LimitState
{
PlanState ps; /* its first field is NodeTag */
Node *limitOffset; /* OFFSET parameter, or NULL if none */
Node *limitCount; /* COUNT parameter, or NULL if none */
ExprState *limitOffset; /* OFFSET parameter, or NULL if none */
ExprState *limitCount; /* COUNT parameter, or NULL if none */
long offset; /* current OFFSET value */
long count; /* current COUNT, if any */
bool noCount; /* if true, ignore count */
@ -814,16 +991,4 @@ typedef struct LimitState
TupleTableSlot *subSlot; /* tuple last obtained from subplan */
} LimitState;
/* ---------------------
* SubPlanState information
* ---------------------
*/
typedef struct SubPlanState
{
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 */

View File

@ -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.131 2002/12/12 20:35:14 tgl Exp $
* $Id: nodes.h,v 1.132 2002/12/13 19:46:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -31,12 +31,12 @@ typedef enum NodeTag
* TAGS FOR EXECUTOR NODES (execnodes.h)
*/
T_IndexInfo = 10,
T_ResultRelInfo,
T_TupleTableSlot,
T_ExprContext,
T_ProjectionInfo,
T_JunkFilter,
T_ResultRelInfo,
T_EState,
T_TupleTableSlot,
/*
* TAGS FOR PLAN NODES (plannodes.h)
@ -89,7 +89,6 @@ typedef enum NodeTag
T_HashState,
T_SetOpState,
T_LimitState,
T_SubPlanState,
/*
* TAGS FOR PRIMITIVE NODES (primnodes.h)
@ -122,10 +121,27 @@ typedef enum NodeTag
T_JoinExpr,
T_FromExpr,
/*
* TAGS FOR EXPRESSION STATE NODES (execnodes.h)
*
* These correspond (not always one-for-one) to primitive nodes
* derived from Expr.
*/
T_ExprState = 400,
T_GenericExprState,
T_AggrefExprState,
T_ArrayRefExprState,
T_FuncExprState,
T_BoolExprState,
T_SubPlanExprState,
T_CaseExprState,
T_CaseWhenState,
T_ConstraintTestState,
/*
* TAGS FOR PLANNER NODES (relation.h)
*/
T_RelOptInfo = 400,
T_RelOptInfo = 500,
T_IndexOptInfo,
T_Path,
T_IndexPath,
@ -144,13 +160,13 @@ typedef enum NodeTag
/*
* TAGS FOR MEMORY NODES (memnodes.h)
*/
T_MemoryContext = 500,
T_MemoryContext = 600,
T_AllocSetContext,
/*
* TAGS FOR VALUE NODES (pg_list.h)
*/
T_Value = 600,
T_Value = 650,
T_List,
T_Integer,
T_Float,

View File

@ -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.19 2002/12/05 15:50:39 tgl Exp $
* $Id: params.h,v 1.20 2002/12/13 19:46:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -88,8 +88,8 @@ 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 SubPlanState node that needs to
* be executed to produce the value. (This is done so that we can have
* If execPlan is not NULL, it points to a SubPlanExprState 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
* when needed.
@ -98,7 +98,7 @@ typedef ParamListInfoData *ParamListInfo;
typedef struct ParamExecData
{
void *execPlan; /* should be "SubPlanState *" */
void *execPlan; /* should be "SubPlanExprState *" */
Datum value;
bool isnull;
} ParamExecData;

View File

@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: primnodes.h,v 1.73 2002/12/12 20:35:16 tgl Exp $
* $Id: primnodes.h,v 1.74 2002/12/13 19:46:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -20,9 +20,6 @@
#include "access/attnum.h"
#include "nodes/pg_list.h"
/* FunctionCache is declared in utils/fcache.h */
typedef struct FunctionCache *FunctionCachePtr;
/* ----------------------------------------------------------------
* node definitions
@ -221,9 +218,6 @@ typedef struct Aggref
Expr *target; /* expression we are aggregating on */
bool aggstar; /* TRUE if argument was really '*' */
bool aggdistinct; /* TRUE if it's agg(DISTINCT ...) */
/* XXX this should move to AggrefExprState: */
int aggno; /* workspace for executor (see nodeAgg.c) */
} Aggref;
/* ----------------
@ -307,8 +301,6 @@ typedef struct FuncExpr
bool funcretset; /* true if function returns set */
CoercionForm funcformat; /* how to display this function call */
List *args; /* arguments to the function */
FunctionCachePtr func_fcache; /* XXX runtime state, or NULL */
} FuncExpr;
/*
@ -328,8 +320,6 @@ typedef struct OpExpr
Oid opresulttype; /* PG_TYPE OID of result value */
bool opretset; /* true if operator returns set */
List *args; /* arguments to the operator (1 or 2) */
FunctionCachePtr op_fcache; /* XXX runtime state, else NULL */
} OpExpr;
/*
@ -463,8 +453,6 @@ typedef struct SubPlanExpr
SubLink *sublink; /* SubLink node from parser; holds info
* about what to do with subselect's
* results */
struct SubPlanState *pstate; /* XXX TEMPORARY HACK */
} SubPlanExpr;
/* ----------------

View File

@ -1,70 +0,0 @@
/*-------------------------------------------------------------------------
*
* fcache.h
* Declarations for function cache records.
*
* The first time any Oper or Func node is evaluated, we compute a cache
* record for the function being invoked, and save a pointer to the cache
* record in the Oper or Func node. This saves repeated lookup of info
* about the function.
*
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: fcache.h,v 1.23 2002/06/20 20:29:52 momjian Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef FCACHE_H
#define FCACHE_H
#include "fmgr.h"
#include "nodes/execnodes.h"
/*
* A FunctionCache record is built for all functions regardless of language.
*
* We store the fmgr lookup info to avoid recomputing it on each call.
*
* We also need to store argument values across calls when evaluating a
* function-returning-set. This is pretty ugly (and not re-entrant);
* current-evaluation info should be somewhere in the econtext, not in
* the querytree. As it stands, a function-returning-set can't safely be
* recursive, at least not if it's in plpgsql which will try to re-use
* the querytree at multiple execution nesting levels. FIXME someday.
*/
typedef struct FunctionCache
{
/*
* Function manager's lookup info for the target function.
*/
FmgrInfo func;
/*
* setArgsValid is true when we are evaluating a set-valued function
* and we are in the middle of a call series; we want to pass the same
* argument values to the function again (and again, until it returns
* ExprEndResult).
*/
bool setArgsValid;
/*
* Flag to remember whether we found a set-valued argument to the
* function. This causes the function result to be a set as well.
* Valid only when setArgsValid is true.
*/
bool setHasSetArg; /* some argument returns a set */
/*
* Current argument data for a set-valued function; contains valid
* data only if setArgsValid is true.
*/
FunctionCallInfoData setArgs;
} FunctionCache;
extern FunctionCachePtr init_fcache(Oid foid, int nargs,
MemoryContext fcacheCxt);
#endif /* FCACHE_H */

View File

@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.73 2002/12/12 15:49:42 tgl Exp $
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.74 2002/12/13 19:46:01 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@ -1981,6 +1981,7 @@ exec_prepare_plan(PLpgSQL_execstate * estate,
PLpgSQL_recfield *recfield;
int i;
int fno;
_SPI_plan *spi_plan;
void *plan;
Oid *argtypes;
@ -2030,7 +2031,8 @@ exec_prepare_plan(PLpgSQL_execstate * estate,
if (plan == NULL)
elog(ERROR, "SPI_prepare() failed on \"%s\"", expr->query);
expr->plan = SPI_saveplan(plan);
expr->plan_argtypes = ((_SPI_plan *) expr->plan)->argtypes;
spi_plan = (_SPI_plan *) expr->plan;
expr->plan_argtypes = spi_plan->argtypes;
expr->plan_simple_expr = NULL;
exec_simple_check_plan(expr);
@ -3642,6 +3644,7 @@ exec_simple_check_plan(PLpgSQL_expr * expr)
_SPI_plan *spi_plan = (_SPI_plan *) expr->plan;
Plan *plan;
TargetEntry *tle;
MemoryContext oldcontext;
expr->plan_simple_expr = NULL;
@ -3688,10 +3691,13 @@ exec_simple_check_plan(PLpgSQL_expr * expr)
return;
/*
* Yes - this is a simple expression. Remember the expression and the
* return type
* Yes - this is a simple expression. Prepare to execute it, and
* stash away the result type. Put the expression state tree in the
* plan context so it will have appropriate lifespan.
*/
expr->plan_simple_expr = (Node *) tle->expr;
oldcontext = MemoryContextSwitchTo(spi_plan->plancxt);
expr->plan_simple_expr = ExecInitExpr(tle->expr, NULL);
MemoryContextSwitchTo(oldcontext);
expr->plan_simple_type = exprType((Node *) tle->expr);
}

View File

@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.29 2002/11/10 00:35:58 momjian Exp $
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/plpgsql.h,v 1.30 2002/12/13 19:46:01 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@ -165,7 +165,7 @@ typedef struct
int exprno;
char *query;
void *plan;
Node *plan_simple_expr;
ExprState *plan_simple_expr;
Oid plan_simple_type;
Oid *plan_argtypes;
int nparams;