aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execQual.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2010-07-12 17:01:06 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2010-07-12 17:01:06 +0000
commit53e757689ce94520f1c53a89dbaa14ea57b09da7 (patch)
treeafa68ba05699223a719104b953bc20f37d4c33d1 /src/backend/executor/execQual.c
parent5a3489357fb61f1ea76412ada33549aca152ad55 (diff)
downloadpostgresql-53e757689ce94520f1c53a89dbaa14ea57b09da7.tar.gz
postgresql-53e757689ce94520f1c53a89dbaa14ea57b09da7.zip
Make NestLoop plan nodes pass outer-relation variables into their inner
relation using the general PARAM_EXEC executor parameter mechanism, rather than the ad-hoc kluge of passing the outer tuple down through ExecReScan. The previous method was hard to understand and could never be extended to handle parameters coming from multiple join levels. This patch doesn't change the set of possible plans nor have any significant performance effect, but it's necessary infrastructure for future generalization of the concept of an inner indexscan plan. ExecReScan's second parameter is now unused, so it's removed.
Diffstat (limited to 'src/backend/executor/execQual.c')
-rw-r--r--src/backend/executor/execQual.c137
1 files changed, 79 insertions, 58 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index e381e112821..e30689bba30 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.263 2010/02/26 02:00:41 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.264 2010/07/12 17:01:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -78,7 +78,9 @@ static Datum ExecEvalWholeRowSlow(ExprState *exprstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalConst(ExprState *exprstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
-static Datum ExecEvalParam(ExprState *exprstate, ExprContext *econtext,
+static Datum ExecEvalParamExec(ExprState *exprstate, ExprContext *econtext,
+ bool *isNull, ExprDoneCond *isDone);
+static Datum ExecEvalParamExtern(ExprState *exprstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static void init_fcache(Oid foid, FuncExprState *fcache,
MemoryContext fcacheCxt, bool needDescForSets);
@@ -961,80 +963,87 @@ ExecEvalConst(ExprState *exprstate, ExprContext *econtext,
}
/* ----------------------------------------------------------------
- * ExecEvalParam
+ * ExecEvalParamExec
*
- * Returns the value of a parameter. A param node contains
- * something like ($.name) and the expression context contains
- * the current parameter bindings (name = "sam") (age = 34)...
- * so our job is to find and return the appropriate datum ("sam").
+ * Returns the value of a PARAM_EXEC parameter.
* ----------------------------------------------------------------
*/
static Datum
-ExecEvalParam(ExprState *exprstate, ExprContext *econtext,
- bool *isNull, ExprDoneCond *isDone)
+ExecEvalParamExec(ExprState *exprstate, ExprContext *econtext,
+ bool *isNull, ExprDoneCond *isDone)
{
Param *expression = (Param *) exprstate->expr;
int thisParamId = expression->paramid;
+ ParamExecData *prm;
if (isDone)
*isDone = ExprSingleResult;
- if (expression->paramkind == PARAM_EXEC)
+ /*
+ * PARAM_EXEC params (internal executor parameters) are stored in the
+ * ecxt_param_exec_vals array, and can be accessed by array index.
+ */
+ prm = &(econtext->ecxt_param_exec_vals[thisParamId]);
+ if (prm->execPlan != NULL)
{
- /*
- * PARAM_EXEC params (internal executor parameters) are stored in the
- * ecxt_param_exec_vals array, and can be accessed by array index.
- */
- ParamExecData *prm;
-
- prm = &(econtext->ecxt_param_exec_vals[thisParamId]);
- if (prm->execPlan != NULL)
- {
- /* Parameter not evaluated yet, so go do it */
- ExecSetParamPlan(prm->execPlan, econtext);
- /* ExecSetParamPlan should have processed this param... */
- Assert(prm->execPlan == NULL);
- }
- *isNull = prm->isnull;
- return prm->value;
+ /* Parameter not evaluated yet, so go do it */
+ ExecSetParamPlan(prm->execPlan, econtext);
+ /* ExecSetParamPlan should have processed this param... */
+ Assert(prm->execPlan == NULL);
}
- else
- {
- /*
- * PARAM_EXTERN parameters must be sought in ecxt_param_list_info.
- */
- ParamListInfo paramInfo = econtext->ecxt_param_list_info;
+ *isNull = prm->isnull;
+ return prm->value;
+}
- Assert(expression->paramkind == PARAM_EXTERN);
- if (paramInfo &&
- thisParamId > 0 && thisParamId <= paramInfo->numParams)
- {
- ParamExternData *prm = &paramInfo->params[thisParamId - 1];
+/* ----------------------------------------------------------------
+ * ExecEvalParamExtern
+ *
+ * Returns the value of a PARAM_EXTERN parameter.
+ * ----------------------------------------------------------------
+ */
+static Datum
+ExecEvalParamExtern(ExprState *exprstate, ExprContext *econtext,
+ bool *isNull, ExprDoneCond *isDone)
+{
+ Param *expression = (Param *) exprstate->expr;
+ int thisParamId = expression->paramid;
+ ParamListInfo paramInfo = econtext->ecxt_param_list_info;
- /* give hook a chance in case parameter is dynamic */
- if (!OidIsValid(prm->ptype) && paramInfo->paramFetch != NULL)
- (*paramInfo->paramFetch) (paramInfo, thisParamId);
+ if (isDone)
+ *isDone = ExprSingleResult;
- if (OidIsValid(prm->ptype))
- {
- /* safety check in case hook did something unexpected */
- if (prm->ptype != expression->paramtype)
- ereport(ERROR,
- (errcode(ERRCODE_DATATYPE_MISMATCH),
- errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
- thisParamId,
- format_type_be(prm->ptype),
- format_type_be(expression->paramtype))));
+ /*
+ * PARAM_EXTERN parameters must be sought in ecxt_param_list_info.
+ */
+ if (paramInfo &&
+ thisParamId > 0 && thisParamId <= paramInfo->numParams)
+ {
+ ParamExternData *prm = &paramInfo->params[thisParamId - 1];
- *isNull = prm->isnull;
- return prm->value;
- }
+ /* give hook a chance in case parameter is dynamic */
+ if (!OidIsValid(prm->ptype) && paramInfo->paramFetch != NULL)
+ (*paramInfo->paramFetch) (paramInfo, thisParamId);
+
+ if (OidIsValid(prm->ptype))
+ {
+ /* safety check in case hook did something unexpected */
+ if (prm->ptype != expression->paramtype)
+ ereport(ERROR,
+ (errcode(ERRCODE_DATATYPE_MISMATCH),
+ errmsg("type of parameter %d (%s) does not match that when preparing the plan (%s)",
+ thisParamId,
+ format_type_be(prm->ptype),
+ format_type_be(expression->paramtype))));
+
+ *isNull = prm->isnull;
+ return prm->value;
}
- ereport(ERROR,
- (errcode(ERRCODE_UNDEFINED_OBJECT),
- errmsg("no value found for parameter %d", thisParamId)));
- return (Datum) 0; /* keep compiler quiet */
}
+
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_OBJECT),
+ errmsg("no value found for parameter %d", thisParamId)));
+ return (Datum) 0; /* keep compiler quiet */
}
@@ -4228,7 +4237,19 @@ ExecInitExpr(Expr *node, PlanState *parent)
break;
case T_Param:
state = (ExprState *) makeNode(ExprState);
- state->evalfunc = ExecEvalParam;
+ switch (((Param *) node)->paramkind)
+ {
+ case PARAM_EXEC:
+ state->evalfunc = ExecEvalParamExec;
+ break;
+ case PARAM_EXTERN:
+ state->evalfunc = ExecEvalParamExtern;
+ break;
+ default:
+ elog(ERROR, "unrecognized paramkind: %d",
+ (int) ((Param *) node)->paramkind);
+ break;
+ }
break;
case T_CoerceToDomainValue:
state = (ExprState *) makeNode(ExprState);