#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"
* 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 $
*
*-------------------------------------------------------------------------
*/
#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"
/* 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;
*
*
* 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
/*
* If partial index, convert predicate into expression nodetree
+ * and prepare an execution state nodetree for it
*/
if (VARSIZE(&indexStruct->indpred) > VARHDRSZ)
{
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;
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;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
num_defaults;
FmgrInfo *in_functions;
Oid *elements;
- Node **constraintexprs;
+ ExprState **constraintexprs;
bool hasConstraints = false;
int i;
List *cur;
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;
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++)
{
{
/* 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++;
}
if (node != (Node *) prm)
{
fix_opfuncids(node);
- constraintexprs[i] = node;
+ constraintexprs[i] = ExecInitExpr((Expr *) node, NULL);
hasConstraints = true;
}
}
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 */
* 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' : ' ';
}
* 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 $
*
*/
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;
}
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++)
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#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"
*/
indexInfo = makeNode(IndexInfo);
indexInfo->ii_Predicate = cnfPred;
+ indexInfo->ii_PredicateState = (List *)
+ ExecInitExpr((Expr *) cnfPred, NULL);
indexInfo->ii_FuncOid = InvalidOid;
indexInfo->ii_Unique = unique;
* 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 $
*
*-------------------------------------------------------------------------
*/
#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"
{
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,
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
HeapTuple tuple;
RangeTblEntry *rte;
List *qual;
+ List *qualstate;
Node *expr;
/*
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);
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;
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;
*
*
* 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
Form_pg_type typTup;
ExprContext *econtext;
char *ccbin;
- Node *expr;
+ Expr *expr;
+ ExprState *exprstate;
int counter = 0;
Constraint *constr;
* 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);
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",
* 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 $
*
*-------------------------------------------------------------------------
*/
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);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
{
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);
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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;
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)
{
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.118 2002/12/12 20:35:12 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.119 2002/12/13 19:45:52 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "executor/nodeSubplan.h"
#include "miscadmin.h"
#include "parser/parse_expr.h"
+#include "utils/acl.h"
#include "utils/array.h"
#include "utils/builtins.h"
-#include "utils/fcache.h"
#include "utils/lsyscache.h"
/* static function decls */
-static Datum ExecEvalAggref(Aggref *aggref, ExprContext *econtext,
- bool *isNull);
-static Datum ExecEvalArrayRef(ArrayRef *arrayRef, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
+static Datum ExecEvalAggref(AggrefExprState *aggref,
+ ExprContext *econtext,
+ bool *isNull);
+static Datum ExecEvalArrayRef(ArrayRefExprState *astate,
+ ExprContext *econtext,
+ bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull);
-static Datum ExecEvalOper(OpExpr *op, ExprContext *econtext,
+static Datum ExecEvalParam(Param *expression, ExprContext *econtext,
+ bool *isNull);
+static Datum ExecEvalFunc(FuncExprState *fcache, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalDistinct(DistinctExpr *op, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalFunc(FuncExpr *func, ExprContext *econtext,
+static Datum ExecEvalOper(FuncExprState *fcache, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
+static Datum ExecEvalDistinct(FuncExprState *fcache, ExprContext *econtext,
+ bool *isNull, ExprDoneCond *isDone);
static ExprDoneCond ExecEvalFuncArgs(FunctionCallInfo fcinfo,
List *argList, ExprContext *econtext);
-static Datum ExecEvalNot(BoolExpr *notclause, ExprContext *econtext,
+static Datum ExecEvalNot(BoolExprState *notclause, ExprContext *econtext,
bool *isNull);
-static Datum ExecEvalOr(BoolExpr *orExpr, ExprContext *econtext,
+static Datum ExecEvalOr(BoolExprState *orExpr, ExprContext *econtext,
bool *isNull);
-static Datum ExecEvalAnd(BoolExpr *andExpr, ExprContext *econtext,
+static Datum ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext,
bool *isNull);
-static Datum ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
+static Datum ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalNullTest(NullTest *ntest, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalBooleanTest(BooleanTest *btest, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalConstraintTest(ConstraintTest *constraint,
+static Datum ExecEvalNullTest(GenericExprState *nstate,
+ ExprContext *econtext,
+ bool *isNull, ExprDoneCond *isDone);
+static Datum ExecEvalBooleanTest(GenericExprState *bstate,
+ ExprContext *econtext,
+ bool *isNull, ExprDoneCond *isDone);
+static Datum ExecEvalConstraintTest(ConstraintTestState *cstate,
ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalConstraintTestValue(ConstraintTestValue *conVal,
ExprContext *econtext, bool *isNull);
+static Datum ExecEvalFieldSelect(GenericExprState *fstate,
+ ExprContext *econtext,
+ bool *isNull, ExprDoneCond *isDone);
/*----------
*----------
*/
static Datum
-ExecEvalArrayRef(ArrayRef *arrayRef,
+ExecEvalArrayRef(ArrayRefExprState *astate,
ExprContext *econtext,
bool *isNull,
ExprDoneCond *isDone)
{
+ ArrayRef *arrayRef = (ArrayRef *) astate->xprstate.expr;
ArrayType *array_source;
ArrayType *resultArray;
bool isAssignment = (arrayRef->refassgnexpr != NULL);
if (arrayRef->refexpr != NULL)
{
array_source = (ArrayType *)
- DatumGetPointer(ExecEvalExpr((Node *) arrayRef->refexpr,
+ DatumGetPointer(ExecEvalExpr(astate->refexpr,
econtext,
isNull,
isDone));
array_source = NULL;
}
- foreach(elt, arrayRef->refupperindexpr)
+ foreach(elt, astate->refupperindexpr)
{
if (i >= MAXDIM)
elog(ERROR, "ExecEvalArrayRef: can only handle %d dimensions",
MAXDIM);
- upper.indx[i++] = DatumGetInt32(ExecEvalExpr((Node *) lfirst(elt),
+ upper.indx[i++] = DatumGetInt32(ExecEvalExpr((ExprState *) lfirst(elt),
econtext,
isNull,
NULL));
}
}
- if (arrayRef->reflowerindexpr != NIL)
+ if (astate->reflowerindexpr != NIL)
{
- foreach(elt, arrayRef->reflowerindexpr)
+ foreach(elt, astate->reflowerindexpr)
{
if (j >= MAXDIM)
elog(ERROR, "ExecEvalArrayRef: can only handle %d dimensions",
MAXDIM);
- lower.indx[j++] = DatumGetInt32(ExecEvalExpr((Node *) lfirst(elt),
+ lower.indx[j++] = DatumGetInt32(ExecEvalExpr((ExprState *) lfirst(elt),
econtext,
isNull,
NULL));
if (isAssignment)
{
- Datum sourceData = ExecEvalExpr((Node *) arrayRef->refassgnexpr,
+ Datum sourceData = ExecEvalExpr(astate->refassgnexpr,
econtext,
isNull,
NULL);
* ----------------------------------------------------------------
*/
static Datum
-ExecEvalAggref(Aggref *aggref, ExprContext *econtext, bool *isNull)
+ExecEvalAggref(AggrefExprState *aggref, ExprContext *econtext, bool *isNull)
{
if (econtext->ecxt_aggvalues == NULL) /* safety check */
elog(ERROR, "ExecEvalAggref: no aggregates in this expression context");
* (in which case we could return NULL)? -cim 10/13/89
* ----------------------------------------------------------------
*/
-Datum
+static Datum
ExecEvalParam(Param *expression, ExprContext *econtext, bool *isNull)
{
int thisParamKind = expression->paramkind;
}
/*
+ * init_fcache - initialize a FuncExprState node during first use
+ */
+void
+init_fcache(Oid foid, FuncExprState *fcache, MemoryContext fcacheCxt)
+{
+ 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 (length(fcache->args) > FUNC_MAX_ARGS)
+ elog(ERROR, "init_fcache: too many arguments");
+
+ /* Set up the primary fmgr lookup information */
+ fmgr_info_cxt(foid, &(fcache->func), fcacheCxt);
+
+ /* Initialize additional info */
+ fcache->setArgsValid = false;
+}
+
+/*
* Evaluate arguments for a function.
*/
static ExprDoneCond
{
ExprDoneCond thisArgIsDone;
- fcinfo->arg[i] = ExecEvalExpr((Node *) lfirst(arg),
+ fcinfo->arg[i] = ExecEvalExpr((ExprState *) lfirst(arg),
econtext,
&fcinfo->argnull[i],
&thisArgIsDone);
* Evaluate the arguments to a function and then the function itself.
*/
Datum
-ExecMakeFunctionResult(FunctionCachePtr fcache,
- List *arguments,
+ExecMakeFunctionResult(FuncExprState *fcache,
ExprContext *econtext,
bool *isNull,
ExprDoneCond *isDone)
{
+ List *arguments = fcache->args;
Datum result;
FunctionCallInfoData fcinfo;
ReturnSetInfo rsinfo; /* for functions returning sets */
* object. (If function returns an empty set, we just return NULL instead.)
*/
Tuplestorestate *
-ExecMakeTableFunctionResult(Node *funcexpr,
+ExecMakeTableFunctionResult(ExprState *funcexpr,
ExprContext *econtext,
TupleDesc expectedDesc,
TupleDesc *returnDesc)
bool returnsTuple = false;
/*
- * Normally the passed expression tree will be a FuncExpr, since the
+ * Normally the passed expression tree will be a FuncExprState, since the
* grammar only allows a function call at the top level of a table
* function reference. However, if the function doesn't return set then
* the planner might have replaced the function call via constant-folding
* we don't get a chance to pass a special ReturnSetInfo to any functions
* buried in the expression.
*/
- if (funcexpr && IsA(funcexpr, FuncExpr))
+ if (funcexpr && IsA(funcexpr, FuncExprState) &&
+ IsA(funcexpr->expr, FuncExpr))
{
- FuncExpr *func = (FuncExpr *) funcexpr;
- List *argList;
- FunctionCachePtr fcache;
+ FuncExprState *fcache = (FuncExprState *) funcexpr;
ExprDoneCond argDone;
/*
*/
direct_function_call = true;
- funcrettype = func->funcresulttype;
- argList = func->args;
-
/*
- * get the fcache from the FuncExpr node. If it is NULL, then
- * initialize it
+ * Initialize function cache if first time through
*/
- fcache = func->func_fcache;
- if (fcache == NULL)
+ if (fcache->func.fn_oid == InvalidOid)
{
- fcache = init_fcache(func->funcid, length(argList),
- econtext->ecxt_per_query_memory);
- func->func_fcache = fcache;
+ FuncExpr *func = (FuncExpr *) fcache->xprstate.expr;
+
+ init_fcache(func->funcid, fcache, econtext->ecxt_per_query_memory);
}
/*
*/
MemSet(&fcinfo, 0, sizeof(fcinfo));
fcinfo.flinfo = &(fcache->func);
- argDone = ExecEvalFuncArgs(&fcinfo, argList, econtext);
+ argDone = ExecEvalFuncArgs(&fcinfo, fcache->args, econtext);
/* We don't allow sets in the arguments of the table function */
if (argDone != ExprSingleResult)
elog(ERROR, "Set-valued function called in context that cannot accept a set");
{
/* Treat funcexpr as a generic expression */
direct_function_call = false;
- funcrettype = exprType(funcexpr);
}
+ funcrettype = exprType((Node *) funcexpr->expr);
+
/*
* Prepare a resultinfo node for communication. We always do this
* even if not expecting a set result, so that we can pass
/* ----------------------------------------------------------------
- * ExecEvalOper
* ExecEvalFunc
+ * ExecEvalOper
* ExecEvalDistinct
*
* Evaluate the functional result of a list of arguments by calling the
*/
/* ----------------------------------------------------------------
- * ExecEvalOper
+ * ExecEvalFunc
* ----------------------------------------------------------------
*/
static Datum
-ExecEvalOper(OpExpr *op,
+ExecEvalFunc(FuncExprState *fcache,
ExprContext *econtext,
bool *isNull,
ExprDoneCond *isDone)
{
- List *argList;
- FunctionCachePtr fcache;
-
/*
- * we extract the oid of the function associated with the op and then
- * pass the work onto ExecMakeFunctionResult which evaluates the
- * arguments and returns the result of calling the function on the
- * evaluated arguments.
+ * Initialize function cache if first time through
*/
- argList = op->args;
-
- /*
- * get the fcache from the OpExpr node. If it is NULL, then initialize
- * it
- */
- fcache = op->op_fcache;
- if (fcache == NULL)
+ if (fcache->func.fn_oid == InvalidOid)
{
- fcache = init_fcache(op->opfuncid, length(argList),
- econtext->ecxt_per_query_memory);
- op->op_fcache = fcache;
+ FuncExpr *func = (FuncExpr *) fcache->xprstate.expr;
+
+ init_fcache(func->funcid, fcache, econtext->ecxt_per_query_memory);
}
- return ExecMakeFunctionResult(fcache, argList, econtext,
- isNull, isDone);
+ return ExecMakeFunctionResult(fcache, econtext, isNull, isDone);
}
/* ----------------------------------------------------------------
- * ExecEvalFunc
+ * ExecEvalOper
* ----------------------------------------------------------------
*/
-
static Datum
-ExecEvalFunc(FuncExpr *func,
+ExecEvalOper(FuncExprState *fcache,
ExprContext *econtext,
bool *isNull,
ExprDoneCond *isDone)
{
- List *argList;
- FunctionCachePtr fcache;
-
/*
- * we extract the oid of the function associated with the func node
- * and then pass the work onto ExecMakeFunctionResult which evaluates
- * the arguments and returns the result of calling the function on the
- * evaluated arguments.
- *
- * this is nearly identical to the ExecEvalOper code.
+ * Initialize function cache if first time through
*/
- argList = func->args;
-
- /*
- * get the fcache from the FuncExpr node. If it is NULL, then initialize
- * it
- */
- fcache = func->func_fcache;
- if (fcache == NULL)
+ if (fcache->func.fn_oid == InvalidOid)
{
- fcache = init_fcache(func->funcid, length(argList),
- econtext->ecxt_per_query_memory);
- func->func_fcache = fcache;
+ OpExpr *op = (OpExpr *) fcache->xprstate.expr;
+
+ init_fcache(op->opfuncid, fcache, econtext->ecxt_per_query_memory);
}
- return ExecMakeFunctionResult(fcache, argList, econtext,
- isNull, isDone);
+ return ExecMakeFunctionResult(fcache, econtext, isNull, isDone);
}
/* ----------------------------------------------------------------
* ----------------------------------------------------------------
*/
static Datum
-ExecEvalDistinct(DistinctExpr *op,
+ExecEvalDistinct(FuncExprState *fcache,
ExprContext *econtext,
bool *isNull,
ExprDoneCond *isDone)
{
Datum result;
- FunctionCachePtr fcache;
FunctionCallInfoData fcinfo;
ExprDoneCond argDone;
List *argList;
/*
- * extract info from op
+ * Initialize function cache if first time through
*/
- argList = op->args;
+ if (fcache->func.fn_oid == InvalidOid)
+ {
+ DistinctExpr *op = (DistinctExpr *) fcache->xprstate.expr;
+
+ init_fcache(op->opfuncid, fcache, econtext->ecxt_per_query_memory);
+ Assert(!fcache->func.fn_retset);
+ }
/*
- * get the fcache from the DistinctExpr node. If it is NULL, then
- * initialize it
+ * extract info from fcache
*/
- fcache = op->op_fcache;
- if (fcache == NULL)
- {
- fcache = init_fcache(op->opfuncid, length(argList),
- econtext->ecxt_per_query_memory);
- op->op_fcache = fcache;
- }
- Assert(!fcache->func.fn_retset);
+ argList = fcache->args;
/* Need to prep callinfo structure */
MemSet(&fcinfo, 0, sizeof(fcinfo));
* ----------------------------------------------------------------
*/
static Datum
-ExecEvalNot(BoolExpr *notclause, ExprContext *econtext, bool *isNull)
+ExecEvalNot(BoolExprState *notclause, ExprContext *econtext, bool *isNull)
{
- Node *clause;
+ ExprState *clause;
Datum expr_value;
clause = lfirst(notclause->args);
* ----------------------------------------------------------------
*/
static Datum
-ExecEvalOr(BoolExpr *orExpr, ExprContext *econtext, bool *isNull)
+ExecEvalOr(BoolExprState *orExpr, ExprContext *econtext, bool *isNull)
{
List *clauses;
List *clause;
*/
foreach(clause, clauses)
{
- clause_value = ExecEvalExpr((Node *) lfirst(clause),
+ clause_value = ExecEvalExpr((ExprState *) lfirst(clause),
econtext, isNull, NULL);
/*
* ----------------------------------------------------------------
*/
static Datum
-ExecEvalAnd(BoolExpr *andExpr, ExprContext *econtext, bool *isNull)
+ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext, bool *isNull)
{
List *clauses;
List *clause;
*/
foreach(clause, clauses)
{
- clause_value = ExecEvalExpr((Node *) lfirst(clause),
+ clause_value = ExecEvalExpr((ExprState *) lfirst(clause),
econtext, isNull, NULL);
/*
* ----------------------------------------------------------------
*/
static Datum
-ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext,
+ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone)
{
List *clauses;
*/
foreach(clause, clauses)
{
- CaseWhen *wclause = lfirst(clause);
+ CaseWhenState *wclause = lfirst(clause);
- clause_value = ExecEvalExpr((Node *) wclause->expr,
+ clause_value = ExecEvalExpr(wclause->expr,
econtext,
isNull,
NULL);
*/
if (DatumGetBool(clause_value) && !*isNull)
{
- return ExecEvalExpr((Node *) wclause->result,
+ return ExecEvalExpr(wclause->result,
econtext,
isNull,
isDone);
if (caseExpr->defresult)
{
- return ExecEvalExpr((Node *) caseExpr->defresult,
+ return ExecEvalExpr(caseExpr->defresult,
econtext,
isNull,
isDone);
* ----------------------------------------------------------------
*/
static Datum
-ExecEvalNullTest(NullTest *ntest,
+ExecEvalNullTest(GenericExprState *nstate,
ExprContext *econtext,
bool *isNull,
ExprDoneCond *isDone)
{
+ NullTest *ntest = (NullTest *) nstate->xprstate.expr;
Datum result;
- result = ExecEvalExpr((Node *) ntest->arg, econtext, isNull, isDone);
+ result = ExecEvalExpr(nstate->arg, econtext, isNull, isDone);
+
+ if (isDone && *isDone == ExprEndResult)
+ return result; /* nothing to check */
+
switch (ntest->nulltesttype)
{
case IS_NULL:
* ----------------------------------------------------------------
*/
static Datum
-ExecEvalBooleanTest(BooleanTest *btest,
+ExecEvalBooleanTest(GenericExprState *bstate,
ExprContext *econtext,
bool *isNull,
ExprDoneCond *isDone)
{
+ BooleanTest *btest = (BooleanTest *) bstate->xprstate.expr;
Datum result;
- result = ExecEvalExpr((Node *) btest->arg, econtext, isNull, isDone);
+ result = ExecEvalExpr(bstate->arg, econtext, isNull, isDone);
+
+ if (isDone && *isDone == ExprEndResult)
+ return result; /* nothing to check */
+
switch (btest->booltesttype)
{
case IS_TRUE:
* datum) otherwise throw an error.
*/
static Datum
-ExecEvalConstraintTest(ConstraintTest *constraint, ExprContext *econtext,
+ExecEvalConstraintTest(ConstraintTestState *cstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone)
{
+ ConstraintTest *constraint = (ConstraintTest *) cstate->xprstate.expr;
Datum result;
- result = ExecEvalExpr((Node *) constraint->arg, econtext, isNull, isDone);
+ result = ExecEvalExpr(cstate->arg, econtext, isNull, isDone);
if (isDone && *isDone == ExprEndResult)
return result; /* nothing to check */
econtext->domainValue_datum = result;
econtext->domainValue_isNull = *isNull;
- conResult = ExecEvalExpr((Node *) constraint->check_expr,
+ conResult = ExecEvalExpr(cstate->check_expr,
econtext, &conIsNull, NULL);
if (!conIsNull &&
* ----------------------------------------------------------------
*/
static Datum
-ExecEvalFieldSelect(FieldSelect *fselect,
+ExecEvalFieldSelect(GenericExprState *fstate,
ExprContext *econtext,
bool *isNull,
ExprDoneCond *isDone)
{
+ FieldSelect *fselect = (FieldSelect *) fstate->xprstate.expr;
Datum result;
TupleTableSlot *resSlot;
- result = ExecEvalExpr((Node *) fselect->arg, econtext, isNull, isDone);
+ result = ExecEvalExpr(fstate->arg, econtext, isNull, isDone);
+
+ /* this test covers the isDone exception too: */
if (*isNull)
return result;
+
resSlot = (TupleTableSlot *) DatumGetPointer(result);
Assert(resSlot != NULL && IsA(resSlot, TupleTableSlot));
result = heap_getattr(resSlot->val,
* Recursively evaluate a targetlist or qualification expression.
*
* Inputs:
- * expression: the expression tree to evaluate
+ * expression: the expression state tree to evaluate
* econtext: evaluation context information
*
* Outputs:
* ----------------------------------------------------------------
*/
Datum
-ExecEvalExpr(Node *expression,
+ExecEvalExpr(ExprState *expression,
ExprContext *econtext,
bool *isNull,
ExprDoneCond *isDone)
{
Datum retDatum;
+ Expr *expr;
/* Set default values for result flags: non-null, not a set result */
*isNull = false;
* here we dispatch the work to the appropriate type of function given
* the type of our expression.
*/
- switch (nodeTag(expression))
+ expr = expression->expr;
+ switch (nodeTag(expr))
{
case T_Var:
- retDatum = ExecEvalVar((Var *) expression, econtext, isNull);
+ retDatum = ExecEvalVar((Var *) expr, econtext, isNull);
break;
case T_Const:
{
- Const *con = (Const *) expression;
+ Const *con = (Const *) expr;
retDatum = con->constvalue;
*isNull = con->constisnull;
break;
}
case T_Param:
- retDatum = ExecEvalParam((Param *) expression, econtext, isNull);
+ retDatum = ExecEvalParam((Param *) expr, econtext, isNull);
break;
case T_Aggref:
- retDatum = ExecEvalAggref((Aggref *) expression, econtext, isNull);
+ retDatum = ExecEvalAggref((AggrefExprState *) expression,
+ econtext,
+ isNull);
break;
case T_ArrayRef:
- retDatum = ExecEvalArrayRef((ArrayRef *) expression,
+ retDatum = ExecEvalArrayRef((ArrayRefExprState *) expression,
econtext,
isNull,
isDone);
break;
case T_FuncExpr:
- retDatum = ExecEvalFunc((FuncExpr *) expression, econtext,
+ retDatum = ExecEvalFunc((FuncExprState *) expression, econtext,
isNull, isDone);
break;
case T_OpExpr:
- retDatum = ExecEvalOper((OpExpr *) expression, econtext,
+ retDatum = ExecEvalOper((FuncExprState *) expression, econtext,
isNull, isDone);
break;
case T_DistinctExpr:
- retDatum = ExecEvalDistinct((DistinctExpr *) expression, econtext,
+ retDatum = ExecEvalDistinct((FuncExprState *) expression, econtext,
isNull, isDone);
break;
case T_BoolExpr:
{
- BoolExpr *expr = (BoolExpr *) expression;
+ BoolExprState *state = (BoolExprState *) expression;
- switch (expr->boolop)
+ switch (((BoolExpr *) expr)->boolop)
{
case AND_EXPR:
- retDatum = ExecEvalAnd(expr, econtext, isNull);
+ retDatum = ExecEvalAnd(state, econtext, isNull);
break;
case OR_EXPR:
- retDatum = ExecEvalOr(expr, econtext, isNull);
+ retDatum = ExecEvalOr(state, econtext, isNull);
break;
case NOT_EXPR:
- retDatum = ExecEvalNot(expr, econtext, isNull);
+ retDatum = ExecEvalNot(state, econtext, isNull);
break;
default:
elog(ERROR, "ExecEvalExpr: unknown boolop %d",
- expr->boolop);
+ ((BoolExpr *) expr)->boolop);
retDatum = 0; /* keep compiler quiet */
break;
}
break;
}
case T_SubPlanExpr:
- /* XXX temporary hack to find exec state node */
- retDatum = ExecSubPlan(((SubPlanExpr *) expression)->pstate,
- ((SubPlanExpr *) expression)->args,
+ retDatum = ExecSubPlan((SubPlanExprState *) expression,
econtext,
isNull);
break;
case T_FieldSelect:
- retDatum = ExecEvalFieldSelect((FieldSelect *) expression,
+ retDatum = ExecEvalFieldSelect((GenericExprState *) expression,
econtext,
isNull,
isDone);
break;
case T_RelabelType:
- retDatum = ExecEvalExpr((Node *) ((RelabelType *) expression)->arg,
+ retDatum = ExecEvalExpr(((GenericExprState *) expression)->arg,
econtext,
isNull,
isDone);
break;
case T_CaseExpr:
- retDatum = ExecEvalCase((CaseExpr *) expression,
+ retDatum = ExecEvalCase((CaseExprState *) expression,
econtext,
isNull,
isDone);
break;
case T_NullTest:
- retDatum = ExecEvalNullTest((NullTest *) expression,
+ retDatum = ExecEvalNullTest((GenericExprState *) expression,
econtext,
isNull,
isDone);
break;
case T_BooleanTest:
- retDatum = ExecEvalBooleanTest((BooleanTest *) expression,
+ retDatum = ExecEvalBooleanTest((GenericExprState *) expression,
econtext,
isNull,
isDone);
break;
case T_ConstraintTest:
- retDatum = ExecEvalConstraintTest((ConstraintTest *) expression,
+ retDatum = ExecEvalConstraintTest((ConstraintTestState *) expression,
econtext,
isNull,
isDone);
break;
case T_ConstraintTestValue:
- retDatum = ExecEvalConstraintTestValue((ConstraintTestValue *) expression,
+ retDatum = ExecEvalConstraintTestValue((ConstraintTestValue *) expr,
econtext,
isNull);
break;
* Same as above, but get into the right allocation context explicitly.
*/
Datum
-ExecEvalExprSwitchContext(Node *expression,
+ExecEvalExprSwitchContext(ExprState *expression,
ExprContext *econtext,
bool *isNull,
ExprDoneCond *isDone)
/*
* ExecInitExpr: prepare an expression tree for execution
*
+ * This function builds and returns an ExprState tree paralleling the given
+ * Expr node tree. The ExprState tree can then be handed to ExecEvalExpr
+ * for execution. Because the Expr tree itself is read-only as far as
+ * ExecInitExpr and ExecEvalExpr are concerned, several different executions
+ * of the same plan tree can occur concurrently.
+ *
+ * This must be called in a memory context that will last as long as repeated
+ * executions of the expression are needed. Typically the context will be
+ * the same as the per-query context of the associated ExprContext.
+ *
+ * Any Aggref and SubplanExpr nodes found in the tree are added to the lists
+ * of such nodes held by the parent PlanState. Otherwise, we do very little
+ * initialization here other than building the state-node tree. Any nontrivial
+ * work associated with initializing runtime info for a node should happen
+ * during the first actual evaluation of that node. (This policy lets us
+ * avoid work if the node is never actually evaluated.)
+ *
+ * Note: there is no ExecEndExpr function; we assume that any resource
+ * cleanup needed will be handled by just releasing the memory context
+ * in which the state tree is built. Functions that require additional
+ * cleanup work can register a shutdown callback in the ExprContext.
+ *
* '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 SubPlanExpr nodes.
+ * with a plan. (If so, it can't have aggs or subplans.)
*/
-Node *
-ExecInitExpr(Node *node, PlanState *parent)
+ExprState *
+ExecInitExpr(Expr *node, PlanState *parent)
{
- List *temp;
+ ExprState *state;
if (node == NULL)
return NULL;
switch (nodeTag(node))
{
case T_Var:
- break;
case T_Const:
- break;
case T_Param:
+ case T_ConstraintTestValue:
+ /* No special setup needed for these node types */
+ state = (ExprState *) makeNode(ExprState);
break;
case T_Aggref:
- if (parent && IsA(parent, AggState))
{
- AggState *aggstate = (AggState *) parent;
- int naggs;
+ Aggref *aggref = (Aggref *) node;
+ AggrefExprState *astate = makeNode(AggrefExprState);
- aggstate->aggs = lcons(node, aggstate->aggs);
- naggs = ++aggstate->numaggs;
+ if (parent && IsA(parent, AggState))
+ {
+ AggState *aggstate = (AggState *) parent;
+ int naggs;
- ExecInitExpr((Node *) ((Aggref *) node)->target, parent);
+ aggstate->aggs = lcons(astate, aggstate->aggs);
+ naggs = ++aggstate->numaggs;
- /*
- * 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");
+ astate->target = ExecInitExpr(aggref->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");
+ state = (ExprState *) astate;
}
- 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((Node *) aref->refexpr, parent);
- ExecInitExpr((Node *) aref->refassgnexpr, parent);
+ ArrayRefExprState *astate = makeNode(ArrayRefExprState);
+
+ astate->refupperindexpr = (List *)
+ ExecInitExpr((Expr *) aref->refupperindexpr, parent);
+ astate->reflowerindexpr = (List *)
+ ExecInitExpr((Expr *) aref->reflowerindexpr, parent);
+ astate->refexpr = ExecInitExpr(aref->refexpr, parent);
+ astate->refassgnexpr = ExecInitExpr(aref->refassgnexpr,
+ parent);
+ state = (ExprState *) astate;
}
break;
case T_FuncExpr:
{
FuncExpr *funcexpr = (FuncExpr *) node;
+ FuncExprState *fstate = makeNode(FuncExprState);
- ExecInitExpr((Node *) funcexpr->args, parent);
+ fstate->args = (List *)
+ ExecInitExpr((Expr *) funcexpr->args, parent);
+ fstate->func.fn_oid = InvalidOid; /* not initialized */
+ state = (ExprState *) fstate;
}
break;
case T_OpExpr:
{
OpExpr *opexpr = (OpExpr *) node;
+ FuncExprState *fstate = makeNode(FuncExprState);
- ExecInitExpr((Node *) opexpr->args, parent);
+ fstate->args = (List *)
+ ExecInitExpr((Expr *) opexpr->args, parent);
+ fstate->func.fn_oid = InvalidOid; /* not initialized */
+ state = (ExprState *) fstate;
}
break;
case T_DistinctExpr:
{
DistinctExpr *distinctexpr = (DistinctExpr *) node;
+ FuncExprState *fstate = makeNode(FuncExprState);
- ExecInitExpr((Node *) distinctexpr->args, parent);
+ fstate->args = (List *)
+ ExecInitExpr((Expr *) distinctexpr->args, parent);
+ fstate->func.fn_oid = InvalidOid; /* not initialized */
+ state = (ExprState *) fstate;
}
break;
case T_BoolExpr:
{
BoolExpr *boolexpr = (BoolExpr *) node;
+ BoolExprState *bstate = makeNode(BoolExprState);
- ExecInitExpr((Node *) boolexpr->args, parent);
+ bstate->args = (List *)
+ ExecInitExpr((Expr *) boolexpr->args, parent);
+ state = (ExprState *) bstate;
}
break;
case T_SubPlanExpr:
{
+ /* Keep this in sync with ExecInitExprInitPlan, below */
SubPlanExpr *subplanexpr = (SubPlanExpr *) node;
SubLink *sublink = subplanexpr->sublink;
+ SubPlanExprState *sstate = makeNode(SubPlanExprState);
Assert(IsA(sublink, SubLink));
if (!parent)
elog(ERROR, "ExecInitExpr: SubPlanExpr not expected here");
/*
- * Here we just add the SubPlanExpr nodes to
- * parent->subPlan. Later they will be expanded
- * to SubPlanState nodes.
+ * Here we just add the SubPlanExprState nodes to
+ * parent->subPlan. The subplans will be initialized later.
*/
- parent->subPlan = lcons(subplanexpr, parent->subPlan);
+ parent->subPlan = lcons(sstate, parent->subPlan);
+ sstate->planstate = NULL;
+
+ sstate->args = (List *)
+ ExecInitExpr((Expr *) subplanexpr->args, parent);
- /* Must recurse into oper list too */
if (sublink->lefthand)
elog(ERROR, "ExecInitExpr: sublink has not been transformed");
- ExecInitExpr((Node *) sublink->oper, parent);
+ sstate->oper = (List *)
+ ExecInitExpr((Expr *) sublink->oper, parent);
- ExecInitExpr((Node *) subplanexpr->args, parent);
+ state = (ExprState *) sstate;
}
break;
case T_FieldSelect:
- ExecInitExpr((Node *) ((FieldSelect *) node)->arg, parent);
+ {
+ FieldSelect *fselect = (FieldSelect *) node;
+ GenericExprState *gstate = makeNode(GenericExprState);
+
+ gstate->arg = ExecInitExpr(fselect->arg, parent);
+ state = (ExprState *) gstate;
+ }
break;
case T_RelabelType:
- ExecInitExpr((Node *) ((RelabelType *) node)->arg, parent);
+ {
+ RelabelType *relabel = (RelabelType *) node;
+ GenericExprState *gstate = makeNode(GenericExprState);
+
+ gstate->arg = ExecInitExpr(relabel->arg, parent);
+ state = (ExprState *) gstate;
+ }
break;
case T_CaseExpr:
{
CaseExpr *caseexpr = (CaseExpr *) node;
+ CaseExprState *cstate = makeNode(CaseExprState);
+ List *outlist = NIL;
+ List *inlist;
- foreach(temp, caseexpr->args)
+ foreach(inlist, caseexpr->args)
{
- CaseWhen *when = (CaseWhen *) lfirst(temp);
+ CaseWhen *when = (CaseWhen *) lfirst(inlist);
+ CaseWhenState *wstate = makeNode(CaseWhenState);
Assert(IsA(when, CaseWhen));
- ExecInitExpr((Node *) when->expr, parent);
- ExecInitExpr((Node *) when->result, parent);
+ wstate->xprstate.expr = (Expr *) when;
+ wstate->expr = ExecInitExpr(when->expr, parent);
+ wstate->result = ExecInitExpr(when->result, parent);
+ outlist = lappend(outlist, wstate);
}
- /* caseexpr->arg should be null, but we'll check it anyway */
- ExecInitExpr((Node *) caseexpr->arg, parent);
- ExecInitExpr((Node *) caseexpr->defresult, parent);
+ cstate->args = outlist;
+ /* caseexpr->arg should be null by now */
+ Assert(caseexpr->arg == NULL);
+ cstate->defresult = ExecInitExpr(caseexpr->defresult, parent);
+ state = (ExprState *) cstate;
}
break;
case T_NullTest:
- ExecInitExpr((Node *) ((NullTest *) node)->arg, parent);
+ {
+ NullTest *ntest = (NullTest *) node;
+ GenericExprState *gstate = makeNode(GenericExprState);
+
+ gstate->arg = ExecInitExpr(ntest->arg, parent);
+ state = (ExprState *) gstate;
+ }
break;
case T_BooleanTest:
- ExecInitExpr((Node *) ((BooleanTest *) node)->arg, parent);
+ {
+ BooleanTest *btest = (BooleanTest *) node;
+ GenericExprState *gstate = makeNode(GenericExprState);
+
+ gstate->arg = ExecInitExpr(btest->arg, parent);
+ state = (ExprState *) gstate;
+ }
break;
case T_ConstraintTest:
- ExecInitExpr((Node *) ((ConstraintTest *) node)->arg, parent);
- ExecInitExpr((Node *) ((ConstraintTest *) node)->check_expr, parent);
- break;
- case T_ConstraintTestValue:
+ {
+ ConstraintTest *ctest = (ConstraintTest *) node;
+ ConstraintTestState *cstate = makeNode(ConstraintTestState);
+
+ cstate->arg = ExecInitExpr(ctest->arg, parent);
+ cstate->check_expr = ExecInitExpr(ctest->check_expr, parent);
+ state = (ExprState *) cstate;
+ }
break;
case T_TargetEntry:
- ExecInitExpr((Node *) ((TargetEntry *) node)->expr, parent);
+ {
+ TargetEntry *tle = (TargetEntry *) node;
+ GenericExprState *gstate = makeNode(GenericExprState);
+
+ gstate->arg = ExecInitExpr(tle->expr, parent);
+ state = (ExprState *) gstate;
+ }
break;
case T_List:
- foreach(temp, (List *) node)
{
- ExecInitExpr((Node *) lfirst(temp), parent);
+ List *outlist = NIL;
+ List *inlist;
+
+ foreach(inlist, (List *) node)
+ {
+ outlist = lappend(outlist,
+ ExecInitExpr((Expr *) lfirst(inlist),
+ parent));
+ }
+ /* Don't fall through to the "common" code below */
+ return (ExprState *) outlist;
}
- break;
default:
elog(ERROR, "ExecInitExpr: unknown expression type %d",
nodeTag(node));
+ state = NULL; /* keep compiler quiet */
break;
}
- return node;
+ /* Common code for all state-node types */
+ state->expr = node;
+
+ return state;
+}
+
+/*
+ * ExecInitExprInitPlan --- initialize a subplan expr that's being handled
+ * as an InitPlan. This is identical to ExecInitExpr's handling of a regular
+ * subplan expr, except we do NOT want to add the node to the parent's
+ * subplan list.
+ */
+SubPlanExprState *
+ExecInitExprInitPlan(SubPlanExpr *node, PlanState *parent)
+{
+ SubLink *sublink = node->sublink;
+ SubPlanExprState *sstate = makeNode(SubPlanExprState);
+
+ Assert(IsA(sublink, SubLink));
+ if (!parent)
+ elog(ERROR, "ExecInitExpr: SubPlanExpr not expected here");
+
+ /* The subplan's state will be initialized later */
+ sstate->planstate = NULL;
+
+ sstate->args = (List *) ExecInitExpr((Expr *) node->args, parent);
+
+ if (sublink->lefthand)
+ elog(ERROR, "ExecInitExpr: sublink has not been transformed");
+
+ sstate->oper = (List *) ExecInitExpr((Expr *) sublink->oper, parent);
+
+ sstate->xprstate.expr = (Expr *) node;
+
+ return sstate;
}
foreach(qlist, qual)
{
- Node *clause = (Node *) lfirst(qlist);
+ ExprState *clause = (ExprState *) lfirst(qlist);
Datum expr_value;
bool isNull;
{
TargetEntry *curTle = (TargetEntry *) lfirst(tl);
+ Assert(IsA(curTle, TargetEntry));
if (!curTle->resdom->resjunk)
len++;
}
char *nulls;
ExprDoneCond *itemIsDone;
List *tl;
- TargetEntry *tle;
- AttrNumber resind;
HeapTuple newTuple;
bool isNull;
bool haveDoneSets;
foreach(tl, targetlist)
{
- tle = lfirst(tl);
-
- resind = tle->resdom->resno - 1;
+ GenericExprState *gstate = (GenericExprState *) lfirst(tl);
+ TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
+ AttrNumber resind = tle->resdom->resno - 1;
- values[resind] = ExecEvalExpr((Node *) tle->expr,
+ values[resind] = ExecEvalExpr(gstate->arg,
econtext,
&isNull,
&itemIsDone[resind]);
*/
foreach(tl, targetlist)
{
- tle = lfirst(tl);
+ GenericExprState *gstate = (GenericExprState *) lfirst(tl);
+ TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
+ AttrNumber resind = tle->resdom->resno - 1;
- if (tle->resdom != NULL)
+ if (itemIsDone[resind] == ExprEndResult)
{
- resind = tle->resdom->resno - 1;
+ values[resind] = ExecEvalExpr(gstate->arg,
+ econtext,
+ &isNull,
+ &itemIsDone[resind]);
+ nulls[resind] = isNull ? 'n' : ' ';
if (itemIsDone[resind] == ExprEndResult)
{
- values[resind] = ExecEvalExpr((Node *) tle->expr,
- econtext,
- &isNull,
- &itemIsDone[resind]);
- nulls[resind] = isNull ? 'n' : ' ';
-
- if (itemIsDone[resind] == ExprEndResult)
- {
- /*
- * Oh dear, this item is returning an empty
- * set. Guess we can't make a tuple after all.
- */
- *isDone = ExprEndResult;
- break;
- }
+ /*
+ * Oh dear, this item is returning an empty
+ * set. Guess we can't make a tuple after all.
+ */
+ *isDone = ExprEndResult;
+ break;
}
}
}
* If we cannot make a tuple because some sets are empty, we
* still have to cycle the nonempty sets to completion, else
* resources will not be released from subplans etc.
+ *
+ * XXX is that still necessary?
*/
if (*isDone == ExprEndResult)
{
foreach(tl, targetlist)
{
- tle = lfirst(tl);
+ GenericExprState *gstate = (GenericExprState *) lfirst(tl);
+ TargetEntry *tle = (TargetEntry *) gstate->xprstate.expr;
+ AttrNumber resind = tle->resdom->resno - 1;
- if (tle->resdom != NULL)
+ while (itemIsDone[resind] == ExprMultipleResult)
{
- resind = tle->resdom->resno - 1;
-
- while (itemIsDone[resind] == ExprMultipleResult)
- {
- (void) ExecEvalExpr((Node *) tle->expr,
- econtext,
- &isNull,
- &itemIsDone[resind]);
- }
+ (void) ExecEvalExpr(gstate->arg,
+ econtext,
+ &isNull,
+ &itemIsDone[resind]);
}
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
}
/*
- * 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);
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 */
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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 */
{
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.
{
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)
* 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);
/*
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;
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,
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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);
/*
* 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;
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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);
/*
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/*
* set expression context
*/
- hashkeys = ((Hash *) node->ps.plan)->hashkeys;
+ hashkeys = node->hashkeys;
econtext = node->ps.ps_ExprContext;
/*
* 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);
/*
/*
* 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
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* for this tuple from the hash table
*/
node->hj_CurBucketNo = ExecHashGetBucket(hashtable, econtext,
- outerkeys);
+ outerkeys);
node->hj_CurTuple = NULL;
/*
HashJoinState *hjstate;
Plan *outerNode;
Hash *hashNode;
+ List *hclauses;
List *hcl;
/*
* 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);
/*
/*
* 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;
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
int numIndices;
IndexScanDescPtr scanDescs;
ScanKey *scanKeys;
- int **runtimeKeyInfo;
+ ExprState ***runtimeKeyInfo;
int *numScanKeys;
Index scanrelid;
int i;
*/
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
* 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);
void
ExecEndIndexScan(IndexScanState *node)
{
- int **runtimeKeyInfo;
+ ExprState ***runtimeKeyInfo;
ScanKey *scanKeys;
int *numScanKeys;
int numIndices;
int *numScanKeys;
RelationPtr indexDescs;
IndexScanDescPtr scanDescs;
- int **runtimeKeyInfo;
+ ExprState ***runtimeKeyInfo;
bool have_runtime_keys;
RangeTblEntry *rtentry;
Index relid;
* 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
* 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
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);
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 */
* 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.
*/
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
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
{
/*
* 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
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
{
/*
* key.
*/
have_runtime_keys = true;
- run_keys[j] = RIGHT_OP;
+ run_keys[j] = ExecInitExpr(rightop, (PlanState *) indexstate);
}
/*
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
/*
* 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
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* ----------------------------------------------------------------
*/
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);
>op->opno,
<op->opfuncid,
>op->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);
}
/* ----------------------------------------------------------------
*
* 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)
{
* 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);
* 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);
/*
*/
MJFormSkipQuals(node->mergeclauses,
&mergestate->mj_OuterSkipQual,
- &mergestate->mj_InnerSkipQual);
+ &mergestate->mj_InnerSkipQual,
+ (PlanState *) mergestate);
MJ_printf("\nExecInitMergeJoin: OuterSkipQual is ");
MJ_nodeDisplay(mergestate->mj_OuterSkipQual);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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);
/*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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);
/*
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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
* 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 $
*
*-------------------------------------------------------------------------
*/
* ----------------------------------------------------------------
*/
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;
TupleTableSlot *slot;
Datum result;
bool found = false; /* TRUE if got at least one subplan tuple */
+ List *pvar;
List *lst;
/*
/*
* Set Params of this plan from parent plan correlation Vars
*/
+ pvar = node->args;
if (subplan->parParam != NIL)
{
foreach(lst, subplan->parParam)
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);
* 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;
/*
* Now we can eval the combining operator for this column.
*/
- expresult = ExecEvalExprSwitchContext((Node *) expr, econtext,
+ expresult = ExecEvalExprSwitchContext(exprstate, econtext,
&expnull, NULL);
/*
* 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;
}
/*
* it, for others - it doesn't matter...
*/
}
-
- return subplanstate;
}
/* ----------------------------------------------------------------
* ----------------------------------------------------------------
*/
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;
*/
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)
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);
}
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;
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));
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);
{
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;
* ----------------------------------------------------------------
*/
void
-ExecEndSubPlan(SubPlanState *node)
+ExecEndSubPlan(SubPlanExprState *node)
{
if (node->needShutdown)
{
}
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)
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.
*/
/*
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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
* 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;
* 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 $
*
*-------------------------------------------------------------------------
*/
COPY_NODE_FIELD(target);
COPY_SCALAR_FIELD(aggstar);
COPY_SCALAR_FIELD(aggdistinct);
- COPY_SCALAR_FIELD(aggno); /* will go away soon */
return newnode;
}
COPY_SCALAR_FIELD(funcformat);
COPY_NODE_FIELD(args);
- /* Do not copy the run-time state, if any */
- newnode->func_fcache = NULL;
-
return newnode;
}
COPY_SCALAR_FIELD(opretset);
COPY_NODE_FIELD(args);
- /* Do not copy the run-time state, if any */
- newnode->op_fcache = NULL;
-
return newnode;
}
COPY_SCALAR_FIELD(opretset);
COPY_NODE_FIELD(args);
- /* Do not copy the run-time state, if any */
- newnode->op_fcache = NULL;
-
return newnode;
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
{
if (opexpr->opfuncid == InvalidOid)
opexpr->opfuncid = get_opcode(opexpr->opno);
- opexpr->op_fcache = NULL; /* XXX will go away soon */
}
*
*
* 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*
/*
* 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)
*
*
* 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.
*
*-------------------------------------------------------------------------
*/
READ_ENUM_FIELD(funcformat, CoercionForm);
READ_NODE_FIELD(args);
- local_node->func_fcache = NULL;
-
READ_DONE();
}
READ_BOOL_FIELD(opretset);
READ_NODE_FIELD(args);
- local_node->op_fcache = NULL;
-
READ_DONE();
}
READ_BOOL_FIELD(opretset);
READ_NODE_FIELD(args);
- local_node->op_fcache = NULL;
-
READ_DONE();
}
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
clause_strategy,
test_strategy;
Expr *test_expr;
+ ExprState *test_exprstate;
Datum test_result;
bool isNull;
Relation relation;
(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);
*
*
* 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
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;
+ }
}
/*
bool has_nonconst_input = false;
bool has_null_input = false;
FuncExpr *newexpr;
+ ExprState *newexprstate;
ExprContext *econtext;
Datum const_val;
bool const_is_null;
*/
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 */
const_val = datumCopy(const_val, resultTypByVal, resultTypLen);
FreeExprContext(econtext);
- pfree(newexpr);
/*
* Make the constant result node.
* 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 $
*
*-------------------------------------------------------------------------
*/
#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"
format_type_be(given_type_id),
format_type_be(expected_type_id));
- fix_opfuncids(expr);
-
lfirst(l) = expr;
paramtypes = lnext(paramtypes);
*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#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"
seteval(PG_FUNCTION_ARGS)
{
Oid funcoid = PG_GETARG_OID(0);
- FunctionCachePtr fcache;
+ FuncExprState *fcache;
Datum result;
bool isNull;
ExprDoneCond isDone;
* 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;
}
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.
*/
fcinfo->isnull = isNull;
# 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 $
#
#-------------------------------------------------------------------------
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
+++ /dev/null
-/*-------------------------------------------------------------------------
- *
- * 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;
-}
* 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 $
*
*-------------------------------------------------------------------------
*/
/*
* 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);
* 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 $
*
*-------------------------------------------------------------------------
*/
#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 */
*
* 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 $
*
*-------------------------------------------------------------------------
*/
#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"
* 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 $
*
*-------------------------------------------------------------------------
*/
* (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?
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;
* 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
* ----------------
*/
/* ----------------------------------------------------------------
- * 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.
* ----------------------------------------------------------------
*/
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
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;
* 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
int iss_MarkIndexPtr;
ScanKey *iss_ScanKeys;
int *iss_NumScanKeys;
- int **iss_RuntimeKeyInfo;
+ ExprState ***iss_RuntimeKeyInfo;
ExprContext *iss_RuntimeContext;
bool iss_RuntimeKeysReady;
RelationPtr iss_RelationDescs;
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;
ScanState ss; /* its first field is NodeTag */
TupleDesc tupdesc;
Tuplestorestate *tuplestorestate;
- Node *funcexpr;
+ ExprState *funcexpr;
} FunctionScanState;
/* ----------------------------------------------------------------
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;
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;
{
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;
/* ----------------
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 */
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 */
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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)
T_HashState,
T_SetOpState,
T_LimitState,
- T_SubPlanState,
/*
* TAGS FOR PRIMITIVE NODES (primnodes.h)
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,
/*
* 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,
* 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 $
*
*-------------------------------------------------------------------------
*/
* 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.
typedef struct ParamExecData
{
- void *execPlan; /* should be "SubPlanState *" */
+ void *execPlan; /* should be "SubPlanExprState *" */
Datum value;
bool isnull;
} ParamExecData;
* 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 $
*
*-------------------------------------------------------------------------
*/
#include "access/attnum.h"
#include "nodes/pg_list.h"
-/* FunctionCache is declared in utils/fcache.h */
-typedef struct FunctionCache *FunctionCachePtr;
-
/* ----------------------------------------------------------------
* node definitions
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;
/* ----------------
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;
/*
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;
/*
SubLink *sublink; /* SubLink node from parser; holds info
* about what to do with subselect's
* results */
-
- struct SubPlanState *pstate; /* XXX TEMPORARY HACK */
} SubPlanExpr;
/* ----------------
+++ /dev/null
-/*-------------------------------------------------------------------------
- *
- * 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 */
* 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.
*
PLpgSQL_recfield *recfield;
int i;
int fno;
+ _SPI_plan *spi_plan;
void *plan;
Oid *argtypes;
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);
_SPI_plan *spi_plan = (_SPI_plan *) expr->plan;
Plan *plan;
TargetEntry *tle;
+ MemoryContext oldcontext;
expr->plan_simple_expr = NULL;
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);
}
* 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.
*
int exprno;
char *query;
void *plan;
- Node *plan_simple_expr;
+ ExprState *plan_simple_expr;
Oid plan_simple_type;
Oid *plan_argtypes;
int nparams;