diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execAmi.c | 10 | ||||
-rw-r--r-- | src/backend/executor/execMain.c | 5 | ||||
-rw-r--r-- | src/backend/executor/execProcnode.c | 25 | ||||
-rw-r--r-- | src/backend/executor/execQual.c | 658 | ||||
-rw-r--r-- | src/backend/executor/execTuples.c | 3 | ||||
-rw-r--r-- | src/backend/executor/execUtils.c | 10 | ||||
-rw-r--r-- | src/backend/executor/nodeAgg.c | 22 | ||||
-rw-r--r-- | src/backend/executor/nodeFunctionscan.c | 9 | ||||
-rw-r--r-- | src/backend/executor/nodeGroup.c | 6 | ||||
-rw-r--r-- | src/backend/executor/nodeHash.c | 11 | ||||
-rw-r--r-- | src/backend/executor/nodeHashjoin.c | 31 | ||||
-rw-r--r-- | src/backend/executor/nodeIndexscan.c | 128 | ||||
-rw-r--r-- | src/backend/executor/nodeLimit.c | 6 | ||||
-rw-r--r-- | src/backend/executor/nodeMergejoin.c | 44 | ||||
-rw-r--r-- | src/backend/executor/nodeNestloop.c | 8 | ||||
-rw-r--r-- | src/backend/executor/nodeResult.c | 8 | ||||
-rw-r--r-- | src/backend/executor/nodeSeqscan.c | 6 | ||||
-rw-r--r-- | src/backend/executor/nodeSubplan.c | 95 | ||||
-rw-r--r-- | src/backend/executor/nodeSubqueryscan.c | 6 | ||||
-rw-r--r-- | src/backend/executor/nodeTidscan.c | 11 |
20 files changed, 603 insertions, 499 deletions
diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c index 4ac4781ec7c..fa95ad6d992 100644 --- a/src/backend/executor/execAmi.c +++ b/src/backend/executor/execAmi.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.66 2002/12/05 15:50:30 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execAmi.c,v 1.67 2002/12/13 19:45:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -61,17 +61,19 @@ ExecReScan(PlanState *node, ExprContext *exprCtxt) foreach(lst, node->initPlan) { - PlanState *splan = ((SubPlanState *) lfirst(lst))->planstate; + SubPlanExprState *sstate = (SubPlanExprState *) lfirst(lst); + PlanState *splan = sstate->planstate; if (splan->plan->extParam != NIL) /* don't care about child * locParam */ SetChangedParamList(splan, node->chgParam); if (splan->chgParam != NIL) - ExecReScanSetParamPlan((SubPlanState *) lfirst(lst), node); + ExecReScanSetParamPlan(sstate, node); } foreach(lst, node->subPlan) { - PlanState *splan = ((SubPlanState *) lfirst(lst))->planstate; + SubPlanExprState *sstate = (SubPlanExprState *) lfirst(lst); + PlanState *splan = sstate->planstate; if (splan->plan->extParam != NIL) SetChangedParamList(splan, node->chgParam); diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index abd099c08c0..bac7398825e 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -26,7 +26,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.191 2002/12/12 15:49:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.192 2002/12/13 19:45:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1543,7 +1543,8 @@ ExecRelCheck(ResultRelInfo *resultRelInfo, { qual = (List *) stringToNode(check[i].ccbin); fix_opfuncids((Node *) qual); - resultRelInfo->ri_ConstraintExprs[i] = qual; + resultRelInfo->ri_ConstraintExprs[i] = (List *) + ExecInitExpr((Expr *) qual, NULL); } MemoryContextSwitchTo(oldContext); } diff --git a/src/backend/executor/execProcnode.c b/src/backend/executor/execProcnode.c index 680a6da609b..59c798b267a 100644 --- a/src/backend/executor/execProcnode.c +++ b/src/backend/executor/execProcnode.c @@ -12,7 +12,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.32 2002/12/12 15:49:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execProcnode.c,v 1.33 2002/12/13 19:45:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -229,23 +229,29 @@ ExecInitNode(Plan *node, EState *estate) foreach(subp, node->initPlan) { SubPlanExpr *subplan = (SubPlanExpr *) lfirst(subp); + SubPlanExprState *sstate; Assert(IsA(subplan, SubPlanExpr)); - subps = lappend(subps, ExecInitSubPlan(subplan, estate)); + sstate = ExecInitExprInitPlan(subplan, result); + ExecInitSubPlan(sstate, estate); + subps = lappend(subps, sstate); } result->initPlan = subps; /* * Initialize any subPlans present in this node. These were found - * by ExecInitExpr during initialization of the PlanState. + * by ExecInitExpr during initialization of the PlanState. Note we + * must do this after initializing initPlans, in case their arguments + * contain subPlans (is that actually possible? perhaps not). */ subps = NIL; foreach(subp, result->subPlan) { - SubPlanExpr *subplan = (SubPlanExpr *) lfirst(subp); + SubPlanExprState *sstate = (SubPlanExprState *) lfirst(subp); - Assert(IsA(subplan, SubPlanExpr)); - subps = lappend(subps, ExecInitSubPlan(subplan, estate)); + Assert(IsA(sstate, SubPlanExprState)); + ExecInitSubPlan(sstate, estate); + subps = lappend(subps, sstate); } result->subPlan = subps; @@ -492,14 +498,11 @@ ExecEndNode(PlanState *node) if (node == NULL) return; - if (node->instrument) - InstrEndLoop(node->instrument); - /* Clean up initPlans and subPlans */ foreach(subp, node->initPlan) - ExecEndSubPlan((SubPlanState *) lfirst(subp)); + ExecEndSubPlan((SubPlanExprState *) lfirst(subp)); foreach(subp, node->subPlan) - ExecEndSubPlan((SubPlanState *) lfirst(subp)); + ExecEndSubPlan((SubPlanExprState *) lfirst(subp)); if (node->chgParam != NIL) { diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index 79796f1c0b2..b529d045c4d 100644 --- a/src/backend/executor/execQual.c +++ b/src/backend/executor/execQual.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.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 $ * *------------------------------------------------------------------------- */ @@ -41,43 +41,52 @@ #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); /*---------- @@ -106,11 +115,12 @@ static Datum ExecEvalConstraintTestValue(ConstraintTestValue *conVal, *---------- */ 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); @@ -124,7 +134,7 @@ ExecEvalArrayRef(ArrayRef *arrayRef, if (arrayRef->refexpr != NULL) { array_source = (ArrayType *) - DatumGetPointer(ExecEvalExpr((Node *) arrayRef->refexpr, + DatumGetPointer(ExecEvalExpr(astate->refexpr, econtext, isNull, isDone)); @@ -150,13 +160,13 @@ ExecEvalArrayRef(ArrayRef *arrayRef, 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)); @@ -170,15 +180,15 @@ ExecEvalArrayRef(ArrayRef *arrayRef, } } - 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)); @@ -205,7 +215,7 @@ ExecEvalArrayRef(ArrayRef *arrayRef, if (isAssignment) { - Datum sourceData = ExecEvalExpr((Node *) arrayRef->refassgnexpr, + Datum sourceData = ExecEvalExpr(astate->refassgnexpr, econtext, isNull, NULL); @@ -275,7 +285,7 @@ ExecEvalArrayRef(ArrayRef *arrayRef, * ---------------------------------------------------------------- */ 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"); @@ -403,7 +413,7 @@ ExecEvalVar(Var *variable, ExprContext *econtext, bool *isNull) * (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; @@ -575,6 +585,30 @@ GetAttributeByName(TupleTableSlot *slot, char *attname, bool *isNull) } /* + * 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 @@ -593,7 +627,7 @@ ExecEvalFuncArgs(FunctionCallInfo fcinfo, { ExprDoneCond thisArgIsDone; - fcinfo->arg[i] = ExecEvalExpr((Node *) lfirst(arg), + fcinfo->arg[i] = ExecEvalExpr((ExprState *) lfirst(arg), econtext, &fcinfo->argnull[i], &thisArgIsDone); @@ -624,12 +658,12 @@ ExecEvalFuncArgs(FunctionCallInfo fcinfo, * 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 */ @@ -823,7 +857,7 @@ ExecMakeFunctionResult(FunctionCachePtr fcache, * 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) @@ -841,7 +875,7 @@ ExecMakeTableFunctionResult(Node *funcexpr, 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 @@ -850,11 +884,10 @@ ExecMakeTableFunctionResult(Node *funcexpr, * 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; /* @@ -862,19 +895,14 @@ ExecMakeTableFunctionResult(Node *funcexpr, */ 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); } /* @@ -887,7 +915,7 @@ ExecMakeTableFunctionResult(Node *funcexpr, */ 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"); @@ -914,9 +942,10 @@ ExecMakeTableFunctionResult(Node *funcexpr, { /* 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 @@ -1087,8 +1116,8 @@ ExecMakeTableFunctionResult(Node *funcexpr, /* ---------------------------------------------------------------- - * ExecEvalOper * ExecEvalFunc + * ExecEvalOper * ExecEvalDistinct * * Evaluate the functional result of a list of arguments by calling the @@ -1097,80 +1126,49 @@ ExecMakeTableFunctionResult(Node *funcexpr, */ /* ---------------------------------------------------------------- - * 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); } /* ---------------------------------------------------------------- @@ -1185,34 +1183,31 @@ ExecEvalFunc(FuncExpr *func, * ---------------------------------------------------------------- */ 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)); @@ -1260,9 +1255,9 @@ ExecEvalDistinct(DistinctExpr *op, * ---------------------------------------------------------------- */ 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); @@ -1288,7 +1283,7 @@ ExecEvalNot(BoolExpr *notclause, ExprContext *econtext, bool *isNull) * ---------------------------------------------------------------- */ static Datum -ExecEvalOr(BoolExpr *orExpr, ExprContext *econtext, bool *isNull) +ExecEvalOr(BoolExprState *orExpr, ExprContext *econtext, bool *isNull) { List *clauses; List *clause; @@ -1314,7 +1309,7 @@ ExecEvalOr(BoolExpr *orExpr, ExprContext *econtext, bool *isNull) */ foreach(clause, clauses) { - clause_value = ExecEvalExpr((Node *) lfirst(clause), + clause_value = ExecEvalExpr((ExprState *) lfirst(clause), econtext, isNull, NULL); /* @@ -1336,7 +1331,7 @@ ExecEvalOr(BoolExpr *orExpr, ExprContext *econtext, bool *isNull) * ---------------------------------------------------------------- */ static Datum -ExecEvalAnd(BoolExpr *andExpr, ExprContext *econtext, bool *isNull) +ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext, bool *isNull) { List *clauses; List *clause; @@ -1356,7 +1351,7 @@ ExecEvalAnd(BoolExpr *andExpr, ExprContext *econtext, bool *isNull) */ foreach(clause, clauses) { - clause_value = ExecEvalExpr((Node *) lfirst(clause), + clause_value = ExecEvalExpr((ExprState *) lfirst(clause), econtext, isNull, NULL); /* @@ -1383,7 +1378,7 @@ ExecEvalAnd(BoolExpr *andExpr, ExprContext *econtext, bool *isNull) * ---------------------------------------------------------------- */ static Datum -ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, +ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone) { List *clauses; @@ -1399,9 +1394,9 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, */ 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); @@ -1413,7 +1408,7 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, */ if (DatumGetBool(clause_value) && !*isNull) { - return ExecEvalExpr((Node *) wclause->result, + return ExecEvalExpr(wclause->result, econtext, isNull, isDone); @@ -1422,7 +1417,7 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, if (caseExpr->defresult) { - return ExecEvalExpr((Node *) caseExpr->defresult, + return ExecEvalExpr(caseExpr->defresult, econtext, isNull, isDone); @@ -1439,14 +1434,19 @@ ExecEvalCase(CaseExpr *caseExpr, ExprContext *econtext, * ---------------------------------------------------------------- */ 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: @@ -1479,14 +1479,19 @@ ExecEvalNullTest(NullTest *ntest, * ---------------------------------------------------------------- */ 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: @@ -1560,12 +1565,13 @@ ExecEvalBooleanTest(BooleanTest *btest, * 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 */ @@ -1596,7 +1602,7 @@ ExecEvalConstraintTest(ConstraintTest *constraint, ExprContext *econtext, econtext->domainValue_datum = result; econtext->domainValue_isNull = *isNull; - conResult = ExecEvalExpr((Node *) constraint->check_expr, + conResult = ExecEvalExpr(cstate->check_expr, econtext, &conIsNull, NULL); if (!conIsNull && @@ -1637,17 +1643,21 @@ ExecEvalConstraintTestValue(ConstraintTestValue *conVal, ExprContext *econtext, * ---------------------------------------------------------------- */ 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, @@ -1663,7 +1673,7 @@ ExecEvalFieldSelect(FieldSelect *fselect, * 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: @@ -1697,12 +1707,13 @@ ExecEvalFieldSelect(FieldSelect *fselect, * ---------------------------------------------------------------- */ 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; @@ -1720,111 +1731,112 @@ ExecEvalExpr(Node *expression, * 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; @@ -1843,7 +1855,7 @@ ExecEvalExpr(Node *expression, * Same as above, but get into the right allocation context explicitly. */ Datum -ExecEvalExprSwitchContext(Node *expression, +ExecEvalExprSwitchContext(ExprState *expression, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone) @@ -1861,166 +1873,301 @@ ExecEvalExprSwitchContext(Node *expression, /* * 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; } @@ -2094,7 +2241,7 @@ ExecQual(List *qual, ExprContext *econtext, bool resultForNull) foreach(qlist, qual) { - Node *clause = (Node *) lfirst(qlist); + ExprState *clause = (ExprState *) lfirst(qlist); Datum expr_value; bool isNull; @@ -2146,6 +2293,7 @@ ExecCleanTargetListLength(List *targetlist) { TargetEntry *curTle = (TargetEntry *) lfirst(tl); + Assert(IsA(curTle, TargetEntry)); if (!curTle->resdom->resjunk) len++; } @@ -2180,8 +2328,6 @@ ExecTargetList(List *targetlist, char *nulls; ExprDoneCond *itemIsDone; List *tl; - TargetEntry *tle; - AttrNumber resind; HeapTuple newTuple; bool isNull; bool haveDoneSets; @@ -2243,11 +2389,11 @@ ExecTargetList(List *targetlist, 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]); @@ -2295,29 +2441,26 @@ ExecTargetList(List *targetlist, */ 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; } } } @@ -2326,24 +2469,23 @@ ExecTargetList(List *targetlist, * 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]); } } diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c index eecc108fb1c..2e7291a006d 100644 --- a/src/backend/executor/execTuples.c +++ b/src/backend/executor/execTuples.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.62 2002/12/12 15:49:28 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execTuples.c,v 1.63 2002/12/13 19:45:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -550,6 +550,7 @@ ExecInitNullTupleSlot(EState *estate, TupleDesc tupType) * ExecTypeFromTL * * Generate a tuple descriptor for the result tuple of a targetlist. + * (A parse/plan tlist must be passed, not an ExprState tlist.) * Note that resjunk columns, if any, are included in the result. * * Currently there are about 4 different places where we create diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c index 0dd17b7965b..36997a49103 100644 --- a/src/backend/executor/execUtils.c +++ b/src/backend/executor/execUtils.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.91 2002/12/05 15:50:32 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execUtils.c,v 1.92 2002/12/13 19:45:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -321,9 +321,9 @@ ExecAssignResultTypeFromTL(PlanState *planstate) } /* - * XXX Some plan nodes don't bother to set up planstate->targetlist, - * so use the underlying plan's targetlist instead. This will probably - * need to be fixed later. + * ExecTypeFromTL needs the parse-time representation of the tlist, not + * a list of ExprStates. This is good because some plan nodes don't + * bother to set up planstate->targetlist ... */ tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid); ExecAssignResultType(planstate, tupDesc, true); @@ -681,7 +681,7 @@ ExecInsertIndexTuples(TupleTableSlot *slot, continue; indexInfo = indexInfoArray[i]; - predicate = indexInfo->ii_Predicate; + predicate = indexInfo->ii_PredicateState; if (predicate != NIL) { /* Skip this index-update if the predicate isn't satisfied */ diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 73e4a8044ef..e6ba3887630 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -45,7 +45,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.99 2002/12/12 15:49:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.100 2002/12/13 19:45:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -82,7 +82,8 @@ typedef struct AggStatePerAggData * thereafter: */ - /* Link to Aggref node this working state is for */ + /* Links to Aggref expr and state nodes this working state is for */ + AggrefExprState *aggrefstate; Aggref *aggref; /* Oids of transfer functions */ @@ -237,7 +238,7 @@ initialize_aggregates(AggState *aggstate, { AggStatePerAgg peraggstate = &peragg[aggno]; AggStatePerGroup pergroupstate = &pergroup[aggno]; - Aggref *aggref = peraggstate->aggref; + Aggref *aggref = peraggstate->aggref; /* * Start a fresh sort operation for each DISTINCT aggregate. @@ -411,11 +412,12 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup) { AggStatePerAgg peraggstate = &aggstate->peragg[aggno]; AggStatePerGroup pergroupstate = &pergroup[aggno]; + AggrefExprState *aggrefstate = peraggstate->aggrefstate; Aggref *aggref = peraggstate->aggref; Datum newVal; bool isNull; - newVal = ExecEvalExprSwitchContext((Node *) aggref->target, econtext, + newVal = ExecEvalExprSwitchContext(aggrefstate->target, econtext, &isNull, NULL); if (aggref->aggdistinct) @@ -1145,10 +1147,10 @@ ExecInitAgg(Agg *node, EState *estate) * particular order. */ aggstate->ss.ps.targetlist = (List *) - ExecInitExpr((Node *) node->plan.targetlist, + ExecInitExpr((Expr *) node->plan.targetlist, (PlanState *) aggstate); aggstate->ss.ps.qual = (List *) - ExecInitExpr((Node *) node->plan.qual, + ExecInitExpr((Expr *) node->plan.qual, (PlanState *) aggstate); /* @@ -1227,7 +1229,8 @@ ExecInitAgg(Agg *node, EState *estate) aggno = -1; foreach(alist, aggstate->aggs) { - Aggref *aggref = (Aggref *) lfirst(alist); + AggrefExprState *aggrefstate = (AggrefExprState *) lfirst(alist); + Aggref *aggref = (Aggref *) aggrefstate->xprstate.expr; AggStatePerAgg peraggstate = &peragg[++aggno]; HeapTuple aggTuple; Form_pg_aggregate aggform; @@ -1236,10 +1239,11 @@ ExecInitAgg(Agg *node, EState *estate) finalfn_oid; Datum textInitVal; - /* Mark Aggref node with its associated index in the result array */ - aggref->aggno = aggno; + /* Mark Aggref state node with assigned index in the result array */ + aggrefstate->aggno = aggno; /* Fill in the peraggstate data */ + peraggstate->aggrefstate = aggrefstate; peraggstate->aggref = aggref; aggTuple = SearchSysCache(AGGFNOID, diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c index f6df416d0f9..d0bf78631da 100644 --- a/src/backend/executor/nodeFunctionscan.c +++ b/src/backend/executor/nodeFunctionscan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.14 2002/12/05 15:50:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeFunctionscan.c,v 1.15 2002/12/13 19:45:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -172,10 +172,10 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate) * initialize child expressions */ scanstate->ss.ps.targetlist = (List *) - ExecInitExpr((Node *) node->scan.plan.targetlist, + ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) scanstate); scanstate->ss.ps.qual = (List *) - ExecInitExpr((Node *) node->scan.plan.qual, + ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) scanstate); /* @@ -241,7 +241,8 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate) * Other node-specific setup */ scanstate->tuplestorestate = NULL; - scanstate->funcexpr = rte->funcexpr; + scanstate->funcexpr = ExecInitExpr((Expr *) rte->funcexpr, + (PlanState *) scanstate); scanstate->ss.ps.ps_TupFromTlist = false; diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c index 3d562a476b8..8bb72ba3438 100644 --- a/src/backend/executor/nodeGroup.c +++ b/src/backend/executor/nodeGroup.c @@ -15,7 +15,7 @@ * locate group boundaries. * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.51 2002/12/05 15:50:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeGroup.c,v 1.52 2002/12/13 19:45:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -168,10 +168,10 @@ ExecInitGroup(Group *node, EState *estate) * initialize child expressions */ grpstate->ss.ps.targetlist = (List *) - ExecInitExpr((Node *) node->plan.targetlist, + ExecInitExpr((Expr *) node->plan.targetlist, (PlanState *) grpstate); grpstate->ss.ps.qual = (List *) - ExecInitExpr((Node *) node->plan.qual, + ExecInitExpr((Expr *) node->plan.qual, (PlanState *) grpstate); /* diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c index 9448ee466a8..45ba826317d 100644 --- a/src/backend/executor/nodeHash.c +++ b/src/backend/executor/nodeHash.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeHash.c,v 1.69 2002/12/05 15:50:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeHash.c,v 1.70 2002/12/13 19:45:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -76,7 +76,7 @@ ExecHash(HashState *node) /* * set expression context */ - hashkeys = ((Hash *) node->ps.plan)->hashkeys; + hashkeys = node->hashkeys; econtext = node->ps.ps_ExprContext; /* @@ -138,10 +138,10 @@ ExecInitHash(Hash *node, EState *estate) * initialize child expressions */ hashstate->ps.targetlist = (List *) - ExecInitExpr((Node *) node->plan.targetlist, + ExecInitExpr((Expr *) node->plan.targetlist, (PlanState *) hashstate); hashstate->ps.qual = (List *) - ExecInitExpr((Node *) node->plan.qual, + ExecInitExpr((Expr *) node->plan.qual, (PlanState *) hashstate); /* @@ -554,7 +554,8 @@ ExecHashGetBucket(HashJoinTable hashtable, /* * Get the join attribute value of the tuple */ - keyval = ExecEvalExpr(lfirst(hk), econtext, &isNull, NULL); + keyval = ExecEvalExpr((ExprState *) lfirst(hk), + econtext, &isNull, NULL); /* * Compute the hash function diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c index 06796c590e3..07de8703812 100644 --- a/src/backend/executor/nodeHashjoin.c +++ b/src/backend/executor/nodeHashjoin.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.43 2002/12/05 15:50:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.44 2002/12/13 19:45:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -169,7 +169,7 @@ ExecHashJoin(HashJoinState *node) * for this tuple from the hash table */ node->hj_CurBucketNo = ExecHashGetBucket(hashtable, econtext, - outerkeys); + outerkeys); node->hj_CurTuple = NULL; /* @@ -302,6 +302,7 @@ ExecInitHashJoin(HashJoin *node, EState *estate) HashJoinState *hjstate; Plan *outerNode; Hash *hashNode; + List *hclauses; List *hcl; /* @@ -322,17 +323,17 @@ ExecInitHashJoin(HashJoin *node, EState *estate) * initialize child expressions */ hjstate->js.ps.targetlist = (List *) - ExecInitExpr((Node *) node->join.plan.targetlist, + ExecInitExpr((Expr *) node->join.plan.targetlist, (PlanState *) hjstate); hjstate->js.ps.qual = (List *) - ExecInitExpr((Node *) node->join.plan.qual, + ExecInitExpr((Expr *) node->join.plan.qual, (PlanState *) hjstate); hjstate->js.jointype = node->join.jointype; hjstate->js.joinqual = (List *) - ExecInitExpr((Node *) node->join.joinqual, + ExecInitExpr((Expr *) node->join.joinqual, (PlanState *) hjstate); hjstate->hashclauses = (List *) - ExecInitExpr((Node *) node->hashclauses, + ExecInitExpr((Expr *) node->hashclauses, (PlanState *) hjstate); /* @@ -402,15 +403,23 @@ ExecInitHashJoin(HashJoin *node, EState *estate) /* * The planner already made a list of the inner hashkeys for us, - * but we also need a list of the outer hashkeys. + * but we also need a list of the outer hashkeys. Each list of + * exprs must then be prepared for execution. */ - hjstate->hj_InnerHashKeys = hashNode->hashkeys; - hjstate->hj_OuterHashKeys = NIL; + hjstate->hj_InnerHashKeys = (List *) + ExecInitExpr((Expr *) hashNode->hashkeys, + innerPlanState(hjstate)); + ((HashState *) innerPlanState(hjstate))->hashkeys = + hjstate->hj_InnerHashKeys; + + hclauses = NIL; foreach(hcl, node->hashclauses) { - hjstate->hj_OuterHashKeys = lappend(hjstate->hj_OuterHashKeys, - get_leftop(lfirst(hcl))); + hclauses = lappend(hclauses, get_leftop(lfirst(hcl))); } + hjstate->hj_OuterHashKeys = (List *) + ExecInitExpr((Expr *) hclauses, + (PlanState *) hjstate); hjstate->js.ps.ps_OuterTupleSlot = NULL; hjstate->js.ps.ps_TupFromTlist = false; diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c index 0112d3641de..1e36e93113d 100644 --- a/src/backend/executor/nodeIndexscan.c +++ b/src/backend/executor/nodeIndexscan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.73 2002/12/12 15:49:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.74 2002/12/13 19:45:52 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -283,7 +283,7 @@ ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt) int numIndices; IndexScanDescPtr scanDescs; ScanKey *scanKeys; - int **runtimeKeyInfo; + ExprState ***runtimeKeyInfo; int *numScanKeys; Index scanrelid; int i; @@ -328,29 +328,18 @@ ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt) */ if (runtimeKeyInfo) { - List *indxqual; - - indxqual = node->indxqual; for (i = 0; i < numIndices; i++) { - List *qual = lfirst(indxqual); int n_keys; ScanKey scan_keys; - int *run_keys; - List *listscan; + ExprState **run_keys; - indxqual = lnext(indxqual); n_keys = numScanKeys[i]; scan_keys = scanKeys[i]; run_keys = runtimeKeyInfo[i]; - listscan = qual; for (j = 0; j < n_keys; j++) { - Expr *clause = lfirst(listscan); - - listscan = lnext(listscan); - /* * If we have a run-time key, then extract the run-time * expression and evaluate it with respect to the current @@ -364,17 +353,12 @@ ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt) * is wrong, we could copy the result into our context * explicitly, but I think that's not necessary... */ - if (run_keys[j] != NO_OP) + if (run_keys[j] != NULL) { - Node *scanexpr; Datum scanvalue; bool isNull; - scanexpr = (run_keys[j] == RIGHT_OP) ? - (Node *) get_rightop(clause) : - (Node *) get_leftop(clause); - - scanvalue = ExecEvalExprSwitchContext(scanexpr, + scanvalue = ExecEvalExprSwitchContext(run_keys[j], econtext, &isNull, NULL); @@ -424,7 +408,7 @@ ExecIndexReScan(IndexScanState *node, ExprContext *exprCtxt) void ExecEndIndexScan(IndexScanState *node) { - int **runtimeKeyInfo; + ExprState ***runtimeKeyInfo; ScanKey *scanKeys; int *numScanKeys; int numIndices; @@ -585,7 +569,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate) int *numScanKeys; RelationPtr indexDescs; IndexScanDescPtr scanDescs; - int **runtimeKeyInfo; + ExprState ***runtimeKeyInfo; bool have_runtime_keys; RangeTblEntry *rtentry; Index relid; @@ -610,16 +594,16 @@ ExecInitIndexScan(IndexScan *node, EState *estate) * initialize child expressions */ indexstate->ss.ps.targetlist = (List *) - ExecInitExpr((Node *) node->scan.plan.targetlist, + ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) indexstate); indexstate->ss.ps.qual = (List *) - ExecInitExpr((Node *) node->scan.plan.qual, + ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) indexstate); indexstate->indxqual = (List *) - ExecInitExpr((Node *) node->indxqual, + ExecInitExpr((Expr *) node->indxqual, (PlanState *) indexstate); indexstate->indxqualorig = (List *) - ExecInitExpr((Node *) node->indxqualorig, + ExecInitExpr((Expr *) node->indxqualorig, (PlanState *) indexstate); #define INDEXSCAN_NSLOTS 2 @@ -672,7 +656,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate) * initialize space for runtime key info (may not be needed) */ have_runtime_keys = false; - runtimeKeyInfo = (int **) palloc(numIndices * sizeof(int *)); + runtimeKeyInfo = (ExprState ***) palloc0(numIndices * sizeof(ExprState **)); /* * build the index scan keys from the index qualification @@ -684,15 +668,15 @@ ExecInitIndexScan(IndexScan *node, EState *estate) List *qual; int n_keys; ScanKey scan_keys; - int *run_keys; + ExprState **run_keys; qual = lfirst(indxqual); indxqual = lnext(indxqual); n_keys = length(qual); scan_keys = (n_keys <= 0) ? (ScanKey) NULL : (ScanKey) palloc(n_keys * sizeof(ScanKeyData)); - run_keys = (n_keys <= 0) ? (int *) NULL : - (int *) palloc(n_keys * sizeof(int)); + run_keys = (n_keys <= 0) ? (ExprState **) NULL : + (ExprState **) palloc(n_keys * sizeof(ExprState *)); CXT1_printf("ExecInitIndexScan: context is %d\n", CurrentMemoryContext); @@ -704,8 +688,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate) for (j = 0; j < n_keys; j++) { OpExpr *clause; /* one clause of index qual */ - Node *leftop; /* expr on lhs of operator */ - Node *rightop; /* expr on rhs ... */ + Expr *leftop; /* expr on lhs of operator */ + Expr *rightop; /* expr on rhs ... */ bits16 flags = 0; int scanvar; /* which var identifies varattno */ @@ -740,9 +724,9 @@ ExecInitIndexScan(IndexScan *node, EState *estate) * which case we need to recalculate the index scan key at run * time. * - * Hence, we set have_runtime_keys to true and then set the - * appropriate flag in run_keys to LEFT_OP or RIGHT_OP. The - * corresponding scan keys are recomputed at run time. + * Hence, we set have_runtime_keys to true and place the + * appropriate subexpression in run_keys. The corresponding + * scan key values are recomputed at run time. * * XXX Although this code *thinks* it can handle an indexqual * with the indexkey on either side, in fact it cannot. @@ -760,19 +744,20 @@ ExecInitIndexScan(IndexScan *node, EState *estate) */ scanvar = NO_OP; - run_keys[j] = NO_OP; + run_keys[j] = NULL; /* * determine information in leftop */ - leftop = (Node *) get_leftop((Expr *) clause); + leftop = (Expr *) get_leftop((Expr *) clause); if (leftop && IsA(leftop, RelabelType)) - leftop = (Node *) ((RelabelType *) leftop)->arg; + leftop = ((RelabelType *) leftop)->arg; Assert(leftop != NULL); - if (IsA(leftop, Var) &&var_is_rel((Var *) leftop)) + if (IsA(leftop, Var) && + var_is_rel((Var *) leftop)) { /* * if the leftop is a "rel-var", then it means that it is @@ -792,32 +777,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate) if (((Const *) leftop)->constisnull) flags |= SK_ISNULL; } - else if (IsA(leftop, Param)) - { - bool isnull; - - /* - * if the leftop is a Param node then it means it - * identifies the value to place in our scan key. - */ - - /* Life was so easy before ... subselects */ - if (((Param *) leftop)->paramkind == PARAM_EXEC) - { - /* treat Param as runtime key */ - have_runtime_keys = true; - run_keys[j] = LEFT_OP; - } - else - { - /* treat Param like a constant */ - scanvalue = ExecEvalParam((Param *) leftop, - indexstate->ss.ps.ps_ExprContext, - &isnull); - if (isnull) - flags |= SK_ISNULL; - } - } else { /* @@ -826,20 +785,21 @@ ExecInitIndexScan(IndexScan *node, EState *estate) * key. */ have_runtime_keys = true; - run_keys[j] = LEFT_OP; + run_keys[j] = ExecInitExpr(leftop, (PlanState *) indexstate); } /* * now determine information in rightop */ - rightop = (Node *) get_rightop((Expr *) clause); + rightop = (Expr *) get_rightop((Expr *) clause); if (rightop && IsA(rightop, RelabelType)) - rightop = (Node *) ((RelabelType *) rightop)->arg; + rightop = ((RelabelType *) rightop)->arg; Assert(rightop != NULL); - if (IsA(rightop, Var) &&var_is_rel((Var *) rightop)) + if (IsA(rightop, Var) && + var_is_rel((Var *) rightop)) { /* * here we make sure only one op identifies the @@ -867,32 +827,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate) if (((Const *) rightop)->constisnull) flags |= SK_ISNULL; } - else if (IsA(rightop, Param)) - { - bool isnull; - - /* - * if the rightop is a Param node then it means it - * identifies the value to place in our scan key. - */ - - /* Life was so easy before ... subselects */ - if (((Param *) rightop)->paramkind == PARAM_EXEC) - { - /* treat Param as runtime key */ - have_runtime_keys = true; - run_keys[j] = RIGHT_OP; - } - else - { - /* treat Param like a constant */ - scanvalue = ExecEvalParam((Param *) rightop, - indexstate->ss.ps.ps_ExprContext, - &isnull); - if (isnull) - flags |= SK_ISNULL; - } - } else { /* @@ -901,7 +835,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate) * key. */ have_runtime_keys = true; - run_keys[j] = RIGHT_OP; + run_keys[j] = ExecInitExpr(rightop, (PlanState *) indexstate); } /* diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c index 1ea3aa62b52..6abd83de8aa 100644 --- a/src/backend/executor/nodeLimit.c +++ b/src/backend/executor/nodeLimit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeLimit.c,v 1.12 2002/12/05 15:50:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeLimit.c,v 1.13 2002/12/13 19:45:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -301,9 +301,9 @@ ExecInitLimit(Limit *node, EState *estate) /* * initialize child expressions */ - limitstate->limitOffset = ExecInitExpr(node->limitOffset, + limitstate->limitOffset = ExecInitExpr((Expr *) node->limitOffset, (PlanState *) limitstate); - limitstate->limitCount = ExecInitExpr(node->limitCount, + limitstate->limitCount = ExecInitExpr((Expr *) node->limitCount, (PlanState *) limitstate); #define LIMIT_NSLOTS 1 diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c index e6c2c86be19..1bb5878d819 100644 --- a/src/backend/executor/nodeMergejoin.c +++ b/src/backend/executor/nodeMergejoin.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.53 2002/12/12 15:49:25 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.54 2002/12/13 19:45:54 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -101,23 +101,26 @@ static bool MergeCompare(List *eqQual, List *compareQual, ExprContext *econtext) * ---------------------------------------------------------------- */ static void -MJFormSkipQuals(List *qualList, List **ltQuals, List **gtQuals) +MJFormSkipQuals(List *qualList, List **ltQuals, List **gtQuals, + PlanState *parent) { - List *ltcdr, + List *ltexprs, + *gtexprs, + *ltcdr, *gtcdr; /* * Make modifiable copies of the qualList. */ - *ltQuals = (List *) copyObject((Node *) qualList); - *gtQuals = (List *) copyObject((Node *) qualList); + ltexprs = (List *) copyObject((Node *) qualList); + gtexprs = (List *) copyObject((Node *) qualList); /* * Scan both lists in parallel, so that we can update the operators * with the minimum number of syscache searches. */ - ltcdr = *ltQuals; - foreach(gtcdr, *gtQuals) + ltcdr = ltexprs; + foreach(gtcdr, gtexprs) { OpExpr *ltop = (OpExpr *) lfirst(ltcdr); OpExpr *gtop = (OpExpr *) lfirst(gtcdr); @@ -137,11 +140,15 @@ MJFormSkipQuals(List *qualList, List **ltQuals, List **gtQuals) >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); } /* ---------------------------------------------------------------- @@ -193,8 +200,10 @@ MergeCompare(List *eqQual, List *compareQual, ExprContext *econtext) * * A NULL result is considered false. */ - const_value = ExecEvalExpr((Node *) lfirst(clause), econtext, - &isNull, NULL); + const_value = ExecEvalExpr((ExprState *) lfirst(clause), + econtext, + &isNull, + NULL); if (DatumGetBool(const_value) && !isNull) { @@ -208,7 +217,7 @@ MergeCompare(List *eqQual, List *compareQual, ExprContext *econtext) * key1 = key2 so we move on to the next pair of keys. *----------- */ - const_value = ExecEvalExpr((Node *) lfirst(eqclause), + const_value = ExecEvalExpr((ExprState *) lfirst(eqclause), econtext, &isNull, NULL); @@ -1409,17 +1418,17 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate) * initialize child expressions */ mergestate->js.ps.targetlist = (List *) - ExecInitExpr((Node *) node->join.plan.targetlist, + ExecInitExpr((Expr *) node->join.plan.targetlist, (PlanState *) mergestate); mergestate->js.ps.qual = (List *) - ExecInitExpr((Node *) node->join.plan.qual, + ExecInitExpr((Expr *) node->join.plan.qual, (PlanState *) mergestate); mergestate->js.jointype = node->join.jointype; mergestate->js.joinqual = (List *) - ExecInitExpr((Node *) node->join.joinqual, + ExecInitExpr((Expr *) node->join.joinqual, (PlanState *) mergestate); mergestate->mergeclauses = (List *) - ExecInitExpr((Node *) node->mergeclauses, + ExecInitExpr((Expr *) node->mergeclauses, (PlanState *) mergestate); /* @@ -1492,7 +1501,8 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate) */ MJFormSkipQuals(node->mergeclauses, &mergestate->mj_OuterSkipQual, - &mergestate->mj_InnerSkipQual); + &mergestate->mj_InnerSkipQual, + (PlanState *) mergestate); MJ_printf("\nExecInitMergeJoin: OuterSkipQual is "); MJ_nodeDisplay(mergestate->mj_OuterSkipQual); diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c index ae2061aa969..452ed7d70c3 100644 --- a/src/backend/executor/nodeNestloop.c +++ b/src/backend/executor/nodeNestloop.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeNestloop.c,v 1.27 2002/12/05 15:50:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeNestloop.c,v 1.28 2002/12/13 19:45:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -286,14 +286,14 @@ ExecInitNestLoop(NestLoop *node, EState *estate) * initialize child expressions */ nlstate->js.ps.targetlist = (List *) - ExecInitExpr((Node *) node->join.plan.targetlist, + ExecInitExpr((Expr *) node->join.plan.targetlist, (PlanState *) nlstate); nlstate->js.ps.qual = (List *) - ExecInitExpr((Node *) node->join.plan.qual, + ExecInitExpr((Expr *) node->join.plan.qual, (PlanState *) nlstate); nlstate->js.jointype = node->join.jointype; nlstate->js.joinqual = (List *) - ExecInitExpr((Node *) node->join.joinqual, + ExecInitExpr((Expr *) node->join.joinqual, (PlanState *) nlstate); /* diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c index f14fd01c424..3f2c9927e01 100644 --- a/src/backend/executor/nodeResult.c +++ b/src/backend/executor/nodeResult.c @@ -34,7 +34,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeResult.c,v 1.22 2002/12/05 15:50:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeResult.c,v 1.23 2002/12/13 19:45:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -205,12 +205,12 @@ ExecInitResult(Result *node, EState *estate) * initialize child expressions */ resstate->ps.targetlist = (List *) - ExecInitExpr((Node *) node->plan.targetlist, + ExecInitExpr((Expr *) node->plan.targetlist, (PlanState *) resstate); resstate->ps.qual = (List *) - ExecInitExpr((Node *) node->plan.qual, + ExecInitExpr((Expr *) node->plan.qual, (PlanState *) resstate); - resstate->resconstantqual = ExecInitExpr(node->resconstantqual, + resstate->resconstantqual = ExecInitExpr((Expr *) node->resconstantqual, (PlanState *) resstate); /* diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c index e19098fba23..6a7393795b2 100644 --- a/src/backend/executor/nodeSeqscan.c +++ b/src/backend/executor/nodeSeqscan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.39 2002/12/05 15:50:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.40 2002/12/13 19:45:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -207,10 +207,10 @@ ExecInitSeqScan(SeqScan *node, EState *estate) * initialize child expressions */ scanstate->ps.targetlist = (List *) - ExecInitExpr((Node *) node->plan.targetlist, + ExecInitExpr((Expr *) node->plan.targetlist, (PlanState *) scanstate); scanstate->ps.qual = (List *) - ExecInitExpr((Node *) node->plan.qual, + ExecInitExpr((Expr *) node->plan.qual, (PlanState *) scanstate); #define SEQSCAN_NSLOTS 2 diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c index 880a6233db2..69fcc58e079 100644 --- a/src/backend/executor/nodeSubplan.c +++ b/src/backend/executor/nodeSubplan.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.36 2002/12/12 15:49:27 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubplan.c,v 1.37 2002/12/13 19:45:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -30,11 +30,12 @@ * ---------------------------------------------------------------- */ Datum -ExecSubPlan(SubPlanState *node, List *pvar, - ExprContext *econtext, bool *isNull) +ExecSubPlan(SubPlanExprState *node, + ExprContext *econtext, + bool *isNull) { PlanState *planstate = node->planstate; - SubPlanExpr *subplan = (SubPlanExpr *) node->ps.plan; + SubPlanExpr *subplan = (SubPlanExpr *) node->xprstate.expr; SubLink *sublink = subplan->sublink; SubLinkType subLinkType = sublink->subLinkType; bool useor = sublink->useor; @@ -42,6 +43,7 @@ ExecSubPlan(SubPlanState *node, List *pvar, TupleTableSlot *slot; Datum result; bool found = false; /* TRUE if got at least one subplan tuple */ + List *pvar; List *lst; /* @@ -56,6 +58,7 @@ ExecSubPlan(SubPlanState *node, List *pvar, /* * Set Params of this plan from parent plan correlation Vars */ + pvar = node->args; if (subplan->parParam != NIL) { foreach(lst, subplan->parParam) @@ -64,7 +67,7 @@ ExecSubPlan(SubPlanState *node, List *pvar, prm = &(econtext->ecxt_param_exec_vals[lfirsti(lst)]); Assert(pvar != NIL); - prm->value = ExecEvalExprSwitchContext((Node *) lfirst(pvar), + prm->value = ExecEvalExprSwitchContext((ExprState *) lfirst(pvar), econtext, &(prm->isnull), NULL); @@ -149,9 +152,10 @@ ExecSubPlan(SubPlanState *node, List *pvar, * For ALL, ANY, and MULTIEXPR sublinks, iterate over combining * operators for columns of tuple. */ - foreach(lst, sublink->oper) + foreach(lst, node->oper) { - OpExpr *expr = (OpExpr *) lfirst(lst); + ExprState *exprstate = (ExprState *) lfirst(lst); + OpExpr *expr = (OpExpr *) exprstate->expr; Param *prm = lsecond(expr->args); ParamExecData *prmdata; Datum expresult; @@ -194,7 +198,7 @@ ExecSubPlan(SubPlanState *node, List *pvar, /* * Now we can eval the combining operator for this column. */ - expresult = ExecEvalExprSwitchContext((Node *) expr, econtext, + expresult = ExecEvalExprSwitchContext(exprstate, econtext, &expnull, NULL); /* @@ -287,64 +291,57 @@ ExecSubPlan(SubPlanState *node, List *pvar, * ExecInitSubPlan * ---------------------------------------------------------------- */ -SubPlanState * -ExecInitSubPlan(SubPlanExpr *node, EState *estate) +void +ExecInitSubPlan(SubPlanExprState *sstate, EState *estate) { - SubPlanState *subplanstate; + SubPlanExpr *expr = (SubPlanExpr *) sstate->xprstate.expr; EState *sp_estate; /* * Do access checking on the rangetable entries in the subquery. * Here, we assume the subquery is a SELECT. */ - ExecCheckRTPerms(node->rtable, CMD_SELECT); + ExecCheckRTPerms(expr->rtable, CMD_SELECT); /* - * create state structure + * initialize state */ - subplanstate = makeNode(SubPlanState); - subplanstate->ps.plan = (Plan *) node; - subplanstate->ps.state = estate; - - subplanstate->needShutdown = false; - subplanstate->curTuple = NULL; - - /* XXX temporary hack */ - node->pstate = subplanstate; + sstate->needShutdown = false; + sstate->curTuple = NULL; /* * create an EState for the subplan */ sp_estate = CreateExecutorState(); - sp_estate->es_range_table = node->rtable; + sp_estate->es_range_table = expr->rtable; sp_estate->es_param_list_info = estate->es_param_list_info; sp_estate->es_param_exec_vals = estate->es_param_exec_vals; sp_estate->es_tupleTable = - ExecCreateTupleTable(ExecCountSlotsNode(node->plan) + 10); + ExecCreateTupleTable(ExecCountSlotsNode(expr->plan) + 10); sp_estate->es_snapshot = estate->es_snapshot; sp_estate->es_instrument = estate->es_instrument; /* * Start up the subplan */ - subplanstate->planstate = ExecInitNode(node->plan, sp_estate); + sstate->planstate = ExecInitNode(expr->plan, sp_estate); - subplanstate->needShutdown = true; /* now we need to shutdown the subplan */ + sstate->needShutdown = true; /* now we need to shutdown the subplan */ /* * If this plan is un-correlated or undirect correlated one and want * to set params for parent plan then prepare parameters. */ - if (node->setParam != NIL) + if (expr->setParam != NIL) { List *lst; - foreach(lst, node->setParam) + foreach(lst, expr->setParam) { ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]); - prm->execPlan = subplanstate; + prm->execPlan = sstate; } /* @@ -353,8 +350,6 @@ ExecInitSubPlan(SubPlanExpr *node, EState *estate) * it, for others - it doesn't matter... */ } - - return subplanstate; } /* ---------------------------------------------------------------- @@ -371,12 +366,11 @@ ExecInitSubPlan(SubPlanExpr *node, EState *estate) * ---------------------------------------------------------------- */ void -ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) +ExecSetParamPlan(SubPlanExprState *node, ExprContext *econtext) { PlanState *planstate = node->planstate; - SubPlanExpr *subplan = (SubPlanExpr *) node->ps.plan; - SubLink *sublink = subplan->sublink; - EState *estate = node->ps.state; + SubPlanExpr *subplan = (SubPlanExpr *) node->xprstate.expr; + SubLinkType subLinkType = subplan->sublink->subLinkType; MemoryContext oldcontext; TupleTableSlot *slot; List *lst; @@ -388,8 +382,8 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) */ oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory); - if (sublink->subLinkType == ANY_SUBLINK || - sublink->subLinkType == ALL_SUBLINK) + if (subLinkType == ANY_SUBLINK || + subLinkType == ALL_SUBLINK) elog(ERROR, "ExecSetParamPlan: ANY/ALL subselect unsupported"); if (planstate->chgParam != NULL) @@ -403,9 +397,9 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) TupleDesc tdesc = slot->ttc_tupleDescriptor; int i = 1; - if (sublink->subLinkType == EXISTS_SUBLINK) + if (subLinkType == EXISTS_SUBLINK) { - ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(subplan->setParam)]); + ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(subplan->setParam)]); prm->execPlan = NULL; prm->value = BoolGetDatum(true); @@ -415,8 +409,8 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) } if (found && - (sublink->subLinkType == EXPR_SUBLINK || - sublink->subLinkType == MULTIEXPR_SUBLINK)) + (subLinkType == EXPR_SUBLINK || + subLinkType == MULTIEXPR_SUBLINK)) elog(ERROR, "More than one tuple returned by a subselect used as an expression."); found = true; @@ -434,7 +428,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) foreach(lst, subplan->setParam) { - ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]); + ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(lst)]); prm->execPlan = NULL; prm->value = heap_getattr(tup, i, tdesc, &(prm->isnull)); @@ -444,9 +438,9 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) if (!found) { - if (sublink->subLinkType == EXISTS_SUBLINK) + if (subLinkType == EXISTS_SUBLINK) { - ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(subplan->setParam)]); + ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(subplan->setParam)]); prm->execPlan = NULL; prm->value = BoolGetDatum(false); @@ -456,7 +450,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) { foreach(lst, subplan->setParam) { - ParamExecData *prm = &(estate->es_param_exec_vals[lfirsti(lst)]); + ParamExecData *prm = &(econtext->ecxt_param_exec_vals[lfirsti(lst)]); prm->execPlan = NULL; prm->value = (Datum) 0; @@ -479,7 +473,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext) * ---------------------------------------------------------------- */ void -ExecEndSubPlan(SubPlanState *node) +ExecEndSubPlan(SubPlanExprState *node) { if (node->needShutdown) { @@ -494,11 +488,11 @@ ExecEndSubPlan(SubPlanState *node) } void -ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent) +ExecReScanSetParamPlan(SubPlanExprState *node, PlanState *parent) { PlanState *planstate = node->planstate; - SubPlanExpr *subplan = (SubPlanExpr *) node->ps.plan; - EState *estate = node->ps.state; + SubPlanExpr *subplan = (SubPlanExpr *) node->xprstate.expr; + EState *estate = parent->state; List *lst; if (subplan->parParam != NULL) @@ -509,8 +503,7 @@ ExecReScanSetParamPlan(SubPlanState *node, PlanState *parent) elog(ERROR, "ExecReScanSetParamPlan: extParam list of plan is NULL"); /* - * Don't actual re-scan: ExecSetParamPlan does re-scan if - * subplan->plan->chgParam is not NULL... ExecReScan (planstate, NULL); + * Don't actually re-scan: ExecSetParamPlan does it if needed. */ /* diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c index ba0ed8635b7..68291ba6e34 100644 --- a/src/backend/executor/nodeSubqueryscan.c +++ b/src/backend/executor/nodeSubqueryscan.c @@ -12,7 +12,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.14 2002/12/05 15:50:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.15 2002/12/13 19:45:55 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -131,10 +131,10 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate) * initialize child expressions */ subquerystate->ss.ps.targetlist = (List *) - ExecInitExpr((Node *) node->scan.plan.targetlist, + ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) subquerystate); subquerystate->ss.ps.qual = (List *) - ExecInitExpr((Node *) node->scan.plan.qual, + ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) subquerystate); #define SUBQUERYSCAN_NSLOTS 1 diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c index 53b3c26d35a..ba2793407ce 100644 --- a/src/backend/executor/nodeTidscan.c +++ b/src/backend/executor/nodeTidscan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.28 2002/12/05 15:50:34 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.29 2002/12/13 19:45:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -380,10 +380,10 @@ ExecInitTidScan(TidScan *node, EState *estate) * initialize child expressions */ tidstate->ss.ps.targetlist = (List *) - ExecInitExpr((Node *) node->scan.plan.targetlist, + ExecInitExpr((Expr *) node->scan.plan.targetlist, (PlanState *) tidstate); tidstate->ss.ps.qual = (List *) - ExecInitExpr((Node *) node->scan.plan.qual, + ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) tidstate); #define TIDSCAN_NSLOTS 2 @@ -404,7 +404,10 @@ ExecInitTidScan(TidScan *node, EState *estate) * get the tid node information */ tidList = (ItemPointerData *) palloc(length(node->tideval) * sizeof(ItemPointerData)); - numTids = TidListCreate(node->tideval, + tidstate->tss_tideval = (List *) + ExecInitExpr((Expr *) node->tideval, + (PlanState *) tidstate); + numTids = TidListCreate(tidstate->tss_tideval, tidstate->ss.ps.ps_ExprContext, tidList); tidPtr = -1; |