X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=src%2Fbackend%2Fexecutor%2FexecQual.c;h=c7bfe7c76ca6b926f2dcbe1eee05b3a0b8b6ecc0;hb=76d4abf2d974ffa578ddc7ff40984cc05c1d48b1;hp=ed53a62e383a4f2ae4910a9c404d0a3f35710172;hpb=511db38ace2690f19816465baed07cefe535bfec;p=postgresql diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c index ed53a62e38..c7bfe7c76c 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.240 2009/01/01 17:23:41 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.247 2009/06/04 18:33:07 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -45,7 +45,7 @@ #include "miscadmin.h" #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" -#include "optimizer/planmain.h" +#include "optimizer/planner.h" #include "pgstat.h" #include "utils/acl.h" #include "utils/builtins.h" @@ -616,8 +616,11 @@ ExecEvalVar(ExprState *exprstate, ExprContext *econtext, ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("table row type and query-specified row type do not match"), - errdetail("Table row contains %d attributes, but query expects %d.", - slot_tupdesc->natts, var_tupdesc->natts))); + errdetail_plural("Table row contains %d attribute, but query expects %d.", + "Table row contains %d attributes, but query expects %d.", + slot_tupdesc->natts, + slot_tupdesc->natts, + var_tupdesc->natts))); else if (var_tupdesc->natts < slot_tupdesc->natts) needslow = true; @@ -1041,8 +1044,10 @@ init_fcache(Oid foid, FuncExprState *fcache, if (list_length(fcache->args) > FUNC_MAX_ARGS) ereport(ERROR, (errcode(ERRCODE_TOO_MANY_ARGUMENTS), - errmsg("cannot pass more than %d arguments to a function", - FUNC_MAX_ARGS))); + errmsg_plural("cannot pass more than %d argument to a function", + "cannot pass more than %d arguments to a function", + FUNC_MAX_ARGS, + FUNC_MAX_ARGS))); /* Set up the primary fmgr lookup information */ fmgr_info_cxt(foid, &(fcache->func), fcacheCxt); @@ -1310,8 +1315,10 @@ tupledesc_match(TupleDesc dst_tupdesc, TupleDesc src_tupdesc) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("function return row and query-specified return row do not match"), - errdetail("Returned row contains %d attributes, but query expects %d.", - src_tupdesc->natts, dst_tupdesc->natts))); + errdetail_plural("Returned row contains %d attribute, but query expects %d.", + "Returned row contains %d attributes, but query expects %d.", + src_tupdesc->natts, + src_tupdesc->natts, dst_tupdesc->natts))); for (i = 0; i < dst_tupdesc->natts; i++) { @@ -1379,7 +1386,7 @@ restart: if (fcache->funcResultStore) { Assert(isDone); /* it was provided before ... */ - if (tuplestore_gettupleslot(fcache->funcResultStore, true, + if (tuplestore_gettupleslot(fcache->funcResultStore, true, false, fcache->funcResultSlot)) { *isDone = ExprMultipleResult; @@ -4320,7 +4327,7 @@ ExecInitExpr(Expr *node, PlanState *parent) sstate = ExecInitSubPlan(subplan, parent); /* Add SubPlanState nodes to parent->subPlan */ - parent->subPlan = lcons(sstate, parent->subPlan); + parent->subPlan = lappend(parent->subPlan, sstate); state = (ExprState *) sstate; } @@ -4665,27 +4672,16 @@ ExecInitExpr(Expr *node, PlanState *parent) XmlExprState *xstate = makeNode(XmlExprState); List *outlist; ListCell *arg; - int i; xstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalXml; - xstate->named_outfuncs = (FmgrInfo *) - palloc0(list_length(xexpr->named_args) * sizeof(FmgrInfo)); outlist = NIL; - i = 0; foreach(arg, xexpr->named_args) { Expr *e = (Expr *) lfirst(arg); ExprState *estate; - Oid typOutFunc; - bool typIsVarlena; estate = ExecInitExpr(e, parent); outlist = lappend(outlist, estate); - - getTypeOutputInfo(exprType((Node *) e), - &typOutFunc, &typIsVarlena); - fmgr_info(typOutFunc, &xstate->named_outfuncs[i]); - i++; } xstate->named_args = outlist; @@ -4794,10 +4790,11 @@ ExecInitExpr(Expr *node, PlanState *parent) * Plan tree context. * * This differs from ExecInitExpr in that we don't assume the caller is - * already running in the EState's per-query context. Also, we apply - * fix_opfuncids() to the passed expression tree to be sure it is ready - * to run. (In ordinary Plan trees the planner will have fixed opfuncids, - * but callers outside the executor will not have done this.) + * already running in the EState's per-query context. Also, we run the + * passed expression tree through expression_planner() to prepare it for + * execution. (In ordinary Plan trees the regular planning process will have + * made the appropriate transformations on expressions, but for standalone + * expressions this won't have happened.) */ ExprState * ExecPrepareExpr(Expr *node, EState *estate) @@ -4805,10 +4802,10 @@ ExecPrepareExpr(Expr *node, EState *estate) ExprState *result; MemoryContext oldcontext; - fix_opfuncids((Node *) node); - oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); + node = expression_planner(node); + result = ExecInitExpr(node, NULL); MemoryContextSwitchTo(oldcontext); @@ -4959,6 +4956,7 @@ ExecCleanTargetListLength(List *targetlist) * prepared to deal with sets of result tuples. Otherwise, a return * of *isDone = ExprMultipleResult signifies a set element, and a return * of *isDone = ExprEndResult signifies end of the set of tuple. + * We assume that *isDone has been initialized to ExprSingleResult by caller. */ static bool ExecTargetList(List *targetlist, @@ -4980,9 +4978,6 @@ ExecTargetList(List *targetlist, /* * evaluate all the expressions in the target list */ - if (isDone) - *isDone = ExprSingleResult; /* until proven otherwise */ - haveDoneSets = false; /* any exhausted set exprs in tlist? */ foreach(tl, targetlist) @@ -5097,50 +5092,6 @@ ExecTargetList(List *targetlist, return true; } -/* - * ExecVariableList - * Evaluates a simple-Variable-list projection. - * - * Results are stored into the passed values and isnull arrays. - */ -static void -ExecVariableList(ProjectionInfo *projInfo, - Datum *values, - bool *isnull) -{ - ExprContext *econtext = projInfo->pi_exprContext; - int *varSlotOffsets = projInfo->pi_varSlotOffsets; - int *varNumbers = projInfo->pi_varNumbers; - int i; - - /* - * Force extraction of all input values that we need. - */ - if (projInfo->pi_lastInnerVar > 0) - slot_getsomeattrs(econtext->ecxt_innertuple, - projInfo->pi_lastInnerVar); - if (projInfo->pi_lastOuterVar > 0) - slot_getsomeattrs(econtext->ecxt_outertuple, - projInfo->pi_lastOuterVar); - if (projInfo->pi_lastScanVar > 0) - slot_getsomeattrs(econtext->ecxt_scantuple, - projInfo->pi_lastScanVar); - - /* - * Assign to result by direct extraction of fields from source slots ... a - * mite ugly, but fast ... - */ - for (i = list_length(projInfo->pi_targetlist) - 1; i >= 0; i--) - { - char *slotptr = ((char *) econtext) + varSlotOffsets[i]; - TupleTableSlot *varSlot = *((TupleTableSlot **) slotptr); - int varNumber = varNumbers[i] - 1; - - values[i] = varSlot->tts_values[varNumber]; - isnull[i] = varSlot->tts_isnull[varNumber]; - } -} - /* * ExecProject * @@ -5158,6 +5109,8 @@ TupleTableSlot * ExecProject(ProjectionInfo *projInfo, ExprDoneCond *isDone) { TupleTableSlot *slot; + ExprContext *econtext; + int numSimpleVars; /* * sanity checks @@ -5168,6 +5121,11 @@ ExecProject(ProjectionInfo *projInfo, ExprDoneCond *isDone) * get the projection info we want */ slot = projInfo->pi_slot; + econtext = projInfo->pi_exprContext; + + /* Assume single result row until proven otherwise */ + if (isDone) + *isDone = ExprSingleResult; /* * Clear any former contents of the result slot. This makes it safe for @@ -5177,29 +5135,84 @@ ExecProject(ProjectionInfo *projInfo, ExprDoneCond *isDone) ExecClearTuple(slot); /* - * form a new result tuple (if possible); if successful, mark the result - * slot as containing a valid virtual tuple + * Force extraction of all input values that we'll need. The + * Var-extraction loops below depend on this, and we are also prefetching + * all attributes that will be referenced in the generic expressions. + */ + if (projInfo->pi_lastInnerVar > 0) + slot_getsomeattrs(econtext->ecxt_innertuple, + projInfo->pi_lastInnerVar); + if (projInfo->pi_lastOuterVar > 0) + slot_getsomeattrs(econtext->ecxt_outertuple, + projInfo->pi_lastOuterVar); + if (projInfo->pi_lastScanVar > 0) + slot_getsomeattrs(econtext->ecxt_scantuple, + projInfo->pi_lastScanVar); + + /* + * Assign simple Vars to result by direct extraction of fields from source + * slots ... a mite ugly, but fast ... */ - if (projInfo->pi_isVarList) + numSimpleVars = projInfo->pi_numSimpleVars; + if (numSimpleVars > 0) { - /* simple Var list: this always succeeds with one result row */ - if (isDone) - *isDone = ExprSingleResult; - ExecVariableList(projInfo, - slot->tts_values, - slot->tts_isnull); - ExecStoreVirtualTuple(slot); + Datum *values = slot->tts_values; + bool *isnull = slot->tts_isnull; + int *varSlotOffsets = projInfo->pi_varSlotOffsets; + int *varNumbers = projInfo->pi_varNumbers; + int i; + + if (projInfo->pi_directMap) + { + /* especially simple case where vars go to output in order */ + for (i = 0; i < numSimpleVars; i++) + { + char *slotptr = ((char *) econtext) + varSlotOffsets[i]; + TupleTableSlot *varSlot = *((TupleTableSlot **) slotptr); + int varNumber = varNumbers[i] - 1; + + values[i] = varSlot->tts_values[varNumber]; + isnull[i] = varSlot->tts_isnull[varNumber]; + } + } + else + { + /* we have to pay attention to varOutputCols[] */ + int *varOutputCols = projInfo->pi_varOutputCols; + + for (i = 0; i < numSimpleVars; i++) + { + char *slotptr = ((char *) econtext) + varSlotOffsets[i]; + TupleTableSlot *varSlot = *((TupleTableSlot **) slotptr); + int varNumber = varNumbers[i] - 1; + int varOutputCol = varOutputCols[i] - 1; + + values[varOutputCol] = varSlot->tts_values[varNumber]; + isnull[varOutputCol] = varSlot->tts_isnull[varNumber]; + } + } } - else + + /* + * If there are any generic expressions, evaluate them. It's possible + * that there are set-returning functions in such expressions; if so + * and we have reached the end of the set, we return the result slot, + * which we already marked empty. + */ + if (projInfo->pi_targetlist) { - if (ExecTargetList(projInfo->pi_targetlist, - projInfo->pi_exprContext, - slot->tts_values, - slot->tts_isnull, - projInfo->pi_itemIsDone, - isDone)) - ExecStoreVirtualTuple(slot); + if (!ExecTargetList(projInfo->pi_targetlist, + econtext, + slot->tts_values, + slot->tts_isnull, + projInfo->pi_itemIsDone, + isDone)) + return slot; /* no more result rows, return empty slot */ } - return slot; + /* + * Successfully formed a result row. Mark the result slot as containing a + * valid virtual tuple. + */ + return ExecStoreVirtualTuple(slot); }