mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
Remove obsoleted code relating to targetlist SRF evaluation.
Since 69f4b9c
plain expression evaluation (and thus normal projection)
can't return sets of tuples anymore. Thus remove code dealing with
that possibility.
This will require adjustments in external code using
ExecEvalExpr()/ExecProject() - that should neither be hard nor very
common.
Author: Andres Freund and Tom Lane
Discussion: https://postgr.es/m/20160822214023.aaxz5l4igypowyri@alap3.anarazel.de
This commit is contained in:
@ -59,7 +59,6 @@
|
||||
#include "utils/syscache.h"
|
||||
|
||||
|
||||
static bool TargetListSupportsBackwardScan(List *targetlist);
|
||||
static bool IndexSupportsBackwardScan(Oid indexid);
|
||||
|
||||
|
||||
@ -120,7 +119,7 @@ ExecReScan(PlanState *node)
|
||||
UpdateChangedParamSet(node->righttree, node->chgParam);
|
||||
}
|
||||
|
||||
/* Shut down any SRFs in the plan node's targetlist */
|
||||
/* Call expression callbacks */
|
||||
if (node->ps_ExprContext)
|
||||
ReScanExprContext(node->ps_ExprContext);
|
||||
|
||||
@ -460,8 +459,7 @@ ExecSupportsBackwardScan(Plan *node)
|
||||
{
|
||||
case T_Result:
|
||||
if (outerPlan(node) != NULL)
|
||||
return ExecSupportsBackwardScan(outerPlan(node)) &&
|
||||
TargetListSupportsBackwardScan(node->targetlist);
|
||||
return ExecSupportsBackwardScan(outerPlan(node));
|
||||
else
|
||||
return false;
|
||||
|
||||
@ -478,13 +476,6 @@ ExecSupportsBackwardScan(Plan *node)
|
||||
return true;
|
||||
}
|
||||
|
||||
case T_SeqScan:
|
||||
case T_TidScan:
|
||||
case T_FunctionScan:
|
||||
case T_ValuesScan:
|
||||
case T_CteScan:
|
||||
return TargetListSupportsBackwardScan(node->targetlist);
|
||||
|
||||
case T_SampleScan:
|
||||
/* Simplify life for tablesample methods by disallowing this */
|
||||
return false;
|
||||
@ -493,35 +484,34 @@ ExecSupportsBackwardScan(Plan *node)
|
||||
return false;
|
||||
|
||||
case T_IndexScan:
|
||||
return IndexSupportsBackwardScan(((IndexScan *) node)->indexid) &&
|
||||
TargetListSupportsBackwardScan(node->targetlist);
|
||||
return IndexSupportsBackwardScan(((IndexScan *) node)->indexid);
|
||||
|
||||
case T_IndexOnlyScan:
|
||||
return IndexSupportsBackwardScan(((IndexOnlyScan *) node)->indexid) &&
|
||||
TargetListSupportsBackwardScan(node->targetlist);
|
||||
return IndexSupportsBackwardScan(((IndexOnlyScan *) node)->indexid);
|
||||
|
||||
case T_SubqueryScan:
|
||||
return ExecSupportsBackwardScan(((SubqueryScan *) node)->subplan) &&
|
||||
TargetListSupportsBackwardScan(node->targetlist);
|
||||
return ExecSupportsBackwardScan(((SubqueryScan *) node)->subplan);
|
||||
|
||||
case T_CustomScan:
|
||||
{
|
||||
uint32 flags = ((CustomScan *) node)->flags;
|
||||
|
||||
if ((flags & CUSTOMPATH_SUPPORT_BACKWARD_SCAN) &&
|
||||
TargetListSupportsBackwardScan(node->targetlist))
|
||||
if (flags & CUSTOMPATH_SUPPORT_BACKWARD_SCAN)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
case T_SeqScan:
|
||||
case T_TidScan:
|
||||
case T_FunctionScan:
|
||||
case T_ValuesScan:
|
||||
case T_CteScan:
|
||||
case T_Material:
|
||||
case T_Sort:
|
||||
/* these don't evaluate tlist */
|
||||
return true;
|
||||
|
||||
case T_LockRows:
|
||||
case T_Limit:
|
||||
/* these don't evaluate tlist */
|
||||
return ExecSupportsBackwardScan(outerPlan(node));
|
||||
|
||||
default:
|
||||
@ -529,18 +519,6 @@ ExecSupportsBackwardScan(Plan *node)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the tlist contains set-returning functions, we can't support backward
|
||||
* scan, because the TupFromTlist code is direction-ignorant.
|
||||
*/
|
||||
static bool
|
||||
TargetListSupportsBackwardScan(List *targetlist)
|
||||
{
|
||||
if (expression_returns_set((Node *) targetlist))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* An IndexScan or IndexOnlyScan node supports backward scan only if the
|
||||
* index's AM does.
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -125,8 +125,6 @@ ExecScan(ScanState *node,
|
||||
ExprContext *econtext;
|
||||
List *qual;
|
||||
ProjectionInfo *projInfo;
|
||||
ExprDoneCond isDone;
|
||||
TupleTableSlot *resultSlot;
|
||||
|
||||
/*
|
||||
* Fetch data from node
|
||||
@ -145,25 +143,9 @@ ExecScan(ScanState *node,
|
||||
return ExecScanFetch(node, accessMtd, recheckMtd);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if we're still projecting out tuples from a previous scan
|
||||
* tuple (because there is a function-returning-set in the projection
|
||||
* expressions). If so, try to project another one.
|
||||
*/
|
||||
if (node->ps.ps_TupFromTlist)
|
||||
{
|
||||
Assert(projInfo); /* can't get here if not projecting */
|
||||
resultSlot = ExecProject(projInfo, &isDone);
|
||||
if (isDone == ExprMultipleResult)
|
||||
return resultSlot;
|
||||
/* Done with that source tuple... */
|
||||
node->ps.ps_TupFromTlist = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset per-tuple memory context to free any expression evaluation
|
||||
* storage allocated in the previous tuple cycle. Note this can't happen
|
||||
* until we're done projecting out tuples from a scan tuple.
|
||||
* storage allocated in the previous tuple cycle.
|
||||
*/
|
||||
ResetExprContext(econtext);
|
||||
|
||||
@ -214,15 +196,9 @@ ExecScan(ScanState *node,
|
||||
{
|
||||
/*
|
||||
* Form a projection tuple, store it in the result tuple slot
|
||||
* and return it --- unless we find we can project no tuples
|
||||
* from this scan tuple, in which case continue scan.
|
||||
* and return it.
|
||||
*/
|
||||
resultSlot = ExecProject(projInfo, &isDone);
|
||||
if (isDone != ExprEndResult)
|
||||
{
|
||||
node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
|
||||
return resultSlot;
|
||||
}
|
||||
return ExecProject(projInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -352,9 +328,6 @@ ExecScanReScan(ScanState *node)
|
||||
{
|
||||
EState *estate = node->ps.state;
|
||||
|
||||
/* Stop projecting any tuples from SRFs in the targetlist */
|
||||
node->ps.ps_TupFromTlist = false;
|
||||
|
||||
/* Rescan EvalPlanQual tuple if we're inside an EvalPlanQual recheck */
|
||||
if (estate->es_epqScanDone != NULL)
|
||||
{
|
||||
|
@ -586,12 +586,6 @@ ExecBuildProjectionInfo(List *targetList,
|
||||
projInfo->pi_numSimpleVars = numSimpleVars;
|
||||
projInfo->pi_directMap = directMap;
|
||||
|
||||
if (exprlist == NIL)
|
||||
projInfo->pi_itemIsDone = NULL; /* not needed */
|
||||
else
|
||||
projInfo->pi_itemIsDone = (ExprDoneCond *)
|
||||
palloc(len * sizeof(ExprDoneCond));
|
||||
|
||||
return projInfo;
|
||||
}
|
||||
|
||||
|
@ -854,7 +854,7 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
|
||||
|
||||
/* compute input for all aggregates */
|
||||
if (aggstate->evalproj)
|
||||
aggstate->evalslot = ExecProject(aggstate->evalproj, NULL);
|
||||
aggstate->evalslot = ExecProject(aggstate->evalproj);
|
||||
|
||||
for (transno = 0; transno < numTrans; transno++)
|
||||
{
|
||||
@ -871,7 +871,7 @@ advance_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
|
||||
bool isnull;
|
||||
|
||||
res = ExecEvalExprSwitchContext(filter, aggstate->tmpcontext,
|
||||
&isnull, NULL);
|
||||
&isnull);
|
||||
if (isnull || !DatumGetBool(res))
|
||||
continue;
|
||||
}
|
||||
@ -970,7 +970,7 @@ combine_aggregates(AggState *aggstate, AggStatePerGroup pergroup)
|
||||
Assert(aggstate->phase->numsets == 0);
|
||||
|
||||
/* compute input for all aggregates */
|
||||
slot = ExecProject(aggstate->evalproj, NULL);
|
||||
slot = ExecProject(aggstate->evalproj);
|
||||
|
||||
for (transno = 0; transno < numTrans; transno++)
|
||||
{
|
||||
@ -1368,8 +1368,7 @@ finalize_aggregate(AggState *aggstate,
|
||||
|
||||
fcinfo.arg[i] = ExecEvalExpr(expr,
|
||||
aggstate->ss.ps.ps_ExprContext,
|
||||
&fcinfo.argnull[i],
|
||||
NULL);
|
||||
&fcinfo.argnull[i]);
|
||||
anynull |= fcinfo.argnull[i];
|
||||
i++;
|
||||
}
|
||||
@ -1630,7 +1629,7 @@ finalize_aggregates(AggState *aggstate,
|
||||
/*
|
||||
* Project the result of a group (whose aggs have already been calculated by
|
||||
* finalize_aggregates). Returns the result slot, or NULL if no row is
|
||||
* projected (suppressed by qual or by an empty SRF).
|
||||
* projected (suppressed by qual).
|
||||
*/
|
||||
static TupleTableSlot *
|
||||
project_aggregates(AggState *aggstate)
|
||||
@ -1643,20 +1642,10 @@ project_aggregates(AggState *aggstate)
|
||||
if (ExecQual(aggstate->ss.ps.qual, econtext, false))
|
||||
{
|
||||
/*
|
||||
* Form and return or store a projection tuple using the aggregate
|
||||
* results and the representative input tuple.
|
||||
* Form and return projection tuple using the aggregate results and
|
||||
* the representative input tuple.
|
||||
*/
|
||||
ExprDoneCond isDone;
|
||||
TupleTableSlot *result;
|
||||
|
||||
result = ExecProject(aggstate->ss.ps.ps_ProjInfo, &isDone);
|
||||
|
||||
if (isDone != ExprEndResult)
|
||||
{
|
||||
aggstate->ss.ps.ps_TupFromTlist =
|
||||
(isDone == ExprMultipleResult);
|
||||
return result;
|
||||
}
|
||||
return ExecProject(aggstate->ss.ps.ps_ProjInfo);
|
||||
}
|
||||
else
|
||||
InstrCountFiltered1(aggstate, 1);
|
||||
@ -1911,27 +1900,6 @@ ExecAgg(AggState *node)
|
||||
{
|
||||
TupleTableSlot *result;
|
||||
|
||||
/*
|
||||
* Check to see if we're still projecting out tuples from a previous agg
|
||||
* tuple (because there is a function-returning-set in the projection
|
||||
* expressions). If so, try to project another one.
|
||||
*/
|
||||
if (node->ss.ps.ps_TupFromTlist)
|
||||
{
|
||||
ExprDoneCond isDone;
|
||||
|
||||
result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
|
||||
if (isDone == ExprMultipleResult)
|
||||
return result;
|
||||
/* Done with that source tuple... */
|
||||
node->ss.ps.ps_TupFromTlist = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (We must do the ps_TupFromTlist check first, because in some cases
|
||||
* agg_done gets set before we emit the final aggregate tuple, and we have
|
||||
* to finish running SRFs for it.)
|
||||
*/
|
||||
if (!node->agg_done)
|
||||
{
|
||||
/* Dispatch based on strategy */
|
||||
@ -2571,8 +2539,6 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
|
||||
ExecAssignResultTypeFromTL(&aggstate->ss.ps);
|
||||
ExecAssignProjectionInfo(&aggstate->ss.ps, NULL);
|
||||
|
||||
aggstate->ss.ps.ps_TupFromTlist = false;
|
||||
|
||||
/*
|
||||
* get the count of aggregates in targetlist and quals
|
||||
*/
|
||||
@ -3575,8 +3541,6 @@ ExecReScanAgg(AggState *node)
|
||||
|
||||
node->agg_done = false;
|
||||
|
||||
node->ss.ps.ps_TupFromTlist = false;
|
||||
|
||||
if (aggnode->aggstrategy == AGG_HASHED)
|
||||
{
|
||||
/*
|
||||
|
@ -575,8 +575,6 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
|
||||
*/
|
||||
ExecAssignExprContext(estate, &scanstate->ss.ps);
|
||||
|
||||
scanstate->ss.ps.ps_TupFromTlist = false;
|
||||
|
||||
/*
|
||||
* initialize child expressions
|
||||
*/
|
||||
|
@ -269,8 +269,6 @@ ExecInitCteScan(CteScan *node, EState *estate, int eflags)
|
||||
ExecAssignResultTypeFromTL(&scanstate->ss.ps);
|
||||
ExecAssignScanProjectionInfo(&scanstate->ss);
|
||||
|
||||
scanstate->ss.ps.ps_TupFromTlist = false;
|
||||
|
||||
return scanstate;
|
||||
}
|
||||
|
||||
|
@ -48,8 +48,6 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
|
||||
/* create expression context for node */
|
||||
ExecAssignExprContext(estate, &css->ss.ps);
|
||||
|
||||
css->ss.ps.ps_TupFromTlist = false;
|
||||
|
||||
/* initialize child expressions */
|
||||
css->ss.ps.targetlist = (List *)
|
||||
ExecInitExpr((Expr *) cscan->scan.plan.targetlist,
|
||||
|
@ -152,8 +152,6 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
|
||||
*/
|
||||
ExecAssignExprContext(estate, &scanstate->ss.ps);
|
||||
|
||||
scanstate->ss.ps.ps_TupFromTlist = false;
|
||||
|
||||
/*
|
||||
* initialize child expressions
|
||||
*/
|
||||
|
@ -331,8 +331,6 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
|
||||
*/
|
||||
ExecAssignExprContext(estate, &scanstate->ss.ps);
|
||||
|
||||
scanstate->ss.ps.ps_TupFromTlist = false;
|
||||
|
||||
/*
|
||||
* tuple table initialization
|
||||
*/
|
||||
|
@ -100,8 +100,6 @@ ExecInitGather(Gather *node, EState *estate, int eflags)
|
||||
outerNode = outerPlan(node);
|
||||
outerPlanState(gatherstate) = ExecInitNode(outerNode, estate, eflags);
|
||||
|
||||
gatherstate->ps.ps_TupFromTlist = false;
|
||||
|
||||
/*
|
||||
* Initialize result tuple type and projection info.
|
||||
*/
|
||||
@ -132,8 +130,6 @@ ExecGather(GatherState *node)
|
||||
TupleTableSlot *fslot = node->funnel_slot;
|
||||
int i;
|
||||
TupleTableSlot *slot;
|
||||
TupleTableSlot *resultSlot;
|
||||
ExprDoneCond isDone;
|
||||
ExprContext *econtext;
|
||||
|
||||
/*
|
||||
@ -199,26 +195,11 @@ ExecGather(GatherState *node)
|
||||
node->initialized = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if we're still projecting out tuples from a previous scan
|
||||
* tuple (because there is a function-returning-set in the projection
|
||||
* expressions). If so, try to project another one.
|
||||
*/
|
||||
if (node->ps.ps_TupFromTlist)
|
||||
{
|
||||
resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
|
||||
if (isDone == ExprMultipleResult)
|
||||
return resultSlot;
|
||||
/* Done with that source tuple... */
|
||||
node->ps.ps_TupFromTlist = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset per-tuple memory context to free any expression evaluation
|
||||
* storage allocated in the previous tuple cycle. Note we can't do this
|
||||
* until we're done projecting. This will also clear any previous tuple
|
||||
* returned by a TupleQueueReader; to make sure we don't leave a dangling
|
||||
* pointer around, clear the working slot first.
|
||||
* storage allocated in the previous tuple cycle. This will also clear
|
||||
* any previous tuple returned by a TupleQueueReader; to make sure we
|
||||
* don't leave a dangling pointer around, clear the working slot first.
|
||||
*/
|
||||
ExecClearTuple(node->funnel_slot);
|
||||
econtext = node->ps.ps_ExprContext;
|
||||
@ -241,13 +222,8 @@ ExecGather(GatherState *node)
|
||||
* back around for another tuple
|
||||
*/
|
||||
econtext->ecxt_outertuple = slot;
|
||||
resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
|
||||
|
||||
if (isDone != ExprEndResult)
|
||||
{
|
||||
node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
|
||||
return resultSlot;
|
||||
}
|
||||
return ExecProject(node->ps.ps_ProjInfo);
|
||||
}
|
||||
|
||||
return slot;
|
||||
|
@ -49,23 +49,6 @@ ExecGroup(GroupState *node)
|
||||
numCols = ((Group *) node->ss.ps.plan)->numCols;
|
||||
grpColIdx = ((Group *) node->ss.ps.plan)->grpColIdx;
|
||||
|
||||
/*
|
||||
* Check to see if we're still projecting out tuples from a previous group
|
||||
* tuple (because there is a function-returning-set in the projection
|
||||
* expressions). If so, try to project another one.
|
||||
*/
|
||||
if (node->ss.ps.ps_TupFromTlist)
|
||||
{
|
||||
TupleTableSlot *result;
|
||||
ExprDoneCond isDone;
|
||||
|
||||
result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
|
||||
if (isDone == ExprMultipleResult)
|
||||
return result;
|
||||
/* Done with that source tuple... */
|
||||
node->ss.ps.ps_TupFromTlist = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* The ScanTupleSlot holds the (copied) first tuple of each group.
|
||||
*/
|
||||
@ -107,16 +90,7 @@ ExecGroup(GroupState *node)
|
||||
/*
|
||||
* Form and return a projection tuple using the first input tuple.
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
ExprDoneCond isDone;
|
||||
|
||||
result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
|
||||
|
||||
if (isDone != ExprEndResult)
|
||||
{
|
||||
node->ss.ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
|
||||
return result;
|
||||
}
|
||||
return ExecProject(node->ss.ps.ps_ProjInfo);
|
||||
}
|
||||
else
|
||||
InstrCountFiltered1(node, 1);
|
||||
@ -170,16 +144,7 @@ ExecGroup(GroupState *node)
|
||||
/*
|
||||
* Form and return a projection tuple using the first input tuple.
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
ExprDoneCond isDone;
|
||||
|
||||
result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
|
||||
|
||||
if (isDone != ExprEndResult)
|
||||
{
|
||||
node->ss.ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
|
||||
return result;
|
||||
}
|
||||
return ExecProject(node->ss.ps.ps_ProjInfo);
|
||||
}
|
||||
else
|
||||
InstrCountFiltered1(node, 1);
|
||||
@ -246,8 +211,6 @@ ExecInitGroup(Group *node, EState *estate, int eflags)
|
||||
ExecAssignResultTypeFromTL(&grpstate->ss.ps);
|
||||
ExecAssignProjectionInfo(&grpstate->ss.ps, NULL);
|
||||
|
||||
grpstate->ss.ps.ps_TupFromTlist = false;
|
||||
|
||||
/*
|
||||
* Precompute fmgr lookup data for inner loop
|
||||
*/
|
||||
@ -283,7 +246,6 @@ ExecReScanGroup(GroupState *node)
|
||||
PlanState *outerPlan = outerPlanState(node);
|
||||
|
||||
node->grp_done = FALSE;
|
||||
node->ss.ps.ps_TupFromTlist = false;
|
||||
/* must clear first tuple */
|
||||
ExecClearTuple(node->ss.ss_ScanTupleSlot);
|
||||
|
||||
|
@ -959,7 +959,7 @@ ExecHashGetHashValue(HashJoinTable hashtable,
|
||||
/*
|
||||
* Get the join attribute value of the tuple
|
||||
*/
|
||||
keyval = ExecEvalExpr(keyexpr, econtext, &isNull, NULL);
|
||||
keyval = ExecEvalExpr(keyexpr, econtext, &isNull);
|
||||
|
||||
/*
|
||||
* If the attribute is NULL, and the join operator is strict, then
|
||||
|
@ -66,7 +66,6 @@ ExecHashJoin(HashJoinState *node)
|
||||
List *joinqual;
|
||||
List *otherqual;
|
||||
ExprContext *econtext;
|
||||
ExprDoneCond isDone;
|
||||
HashJoinTable hashtable;
|
||||
TupleTableSlot *outerTupleSlot;
|
||||
uint32 hashvalue;
|
||||
@ -82,26 +81,9 @@ ExecHashJoin(HashJoinState *node)
|
||||
hashtable = node->hj_HashTable;
|
||||
econtext = node->js.ps.ps_ExprContext;
|
||||
|
||||
/*
|
||||
* Check to see if we're still projecting out tuples from a previous join
|
||||
* tuple (because there is a function-returning-set in the projection
|
||||
* expressions). If so, try to project another one.
|
||||
*/
|
||||
if (node->js.ps.ps_TupFromTlist)
|
||||
{
|
||||
TupleTableSlot *result;
|
||||
|
||||
result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
|
||||
if (isDone == ExprMultipleResult)
|
||||
return result;
|
||||
/* Done with that source tuple... */
|
||||
node->js.ps.ps_TupFromTlist = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset per-tuple memory context to free any expression evaluation
|
||||
* storage allocated in the previous tuple cycle. Note this can't happen
|
||||
* until we're done projecting out tuples from a join tuple.
|
||||
* storage allocated in the previous tuple cycle.
|
||||
*/
|
||||
ResetExprContext(econtext);
|
||||
|
||||
@ -314,18 +296,7 @@ ExecHashJoin(HashJoinState *node)
|
||||
|
||||
if (otherqual == NIL ||
|
||||
ExecQual(otherqual, econtext, false))
|
||||
{
|
||||
TupleTableSlot *result;
|
||||
|
||||
result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
|
||||
|
||||
if (isDone != ExprEndResult)
|
||||
{
|
||||
node->js.ps.ps_TupFromTlist =
|
||||
(isDone == ExprMultipleResult);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return ExecProject(node->js.ps.ps_ProjInfo);
|
||||
else
|
||||
InstrCountFiltered2(node, 1);
|
||||
}
|
||||
@ -353,18 +324,7 @@ ExecHashJoin(HashJoinState *node)
|
||||
|
||||
if (otherqual == NIL ||
|
||||
ExecQual(otherqual, econtext, false))
|
||||
{
|
||||
TupleTableSlot *result;
|
||||
|
||||
result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
|
||||
|
||||
if (isDone != ExprEndResult)
|
||||
{
|
||||
node->js.ps.ps_TupFromTlist =
|
||||
(isDone == ExprMultipleResult);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return ExecProject(node->js.ps.ps_ProjInfo);
|
||||
else
|
||||
InstrCountFiltered2(node, 1);
|
||||
}
|
||||
@ -392,18 +352,7 @@ ExecHashJoin(HashJoinState *node)
|
||||
|
||||
if (otherqual == NIL ||
|
||||
ExecQual(otherqual, econtext, false))
|
||||
{
|
||||
TupleTableSlot *result;
|
||||
|
||||
result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
|
||||
|
||||
if (isDone != ExprEndResult)
|
||||
{
|
||||
node->js.ps.ps_TupFromTlist =
|
||||
(isDone == ExprMultipleResult);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return ExecProject(node->js.ps.ps_ProjInfo);
|
||||
else
|
||||
InstrCountFiltered2(node, 1);
|
||||
break;
|
||||
@ -586,7 +535,6 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
|
||||
/* child Hash node needs to evaluate inner hash keys, too */
|
||||
((HashState *) innerPlanState(hjstate))->hashkeys = rclauses;
|
||||
|
||||
hjstate->js.ps.ps_TupFromTlist = false;
|
||||
hjstate->hj_JoinState = HJ_BUILD_HASHTABLE;
|
||||
hjstate->hj_MatchedOuter = false;
|
||||
hjstate->hj_OuterNotEmpty = false;
|
||||
@ -1000,7 +948,6 @@ ExecReScanHashJoin(HashJoinState *node)
|
||||
node->hj_CurSkewBucketNo = INVALID_SKEW_BUCKET_NO;
|
||||
node->hj_CurTuple = NULL;
|
||||
|
||||
node->js.ps.ps_TupFromTlist = false;
|
||||
node->hj_MatchedOuter = false;
|
||||
node->hj_FirstOuterTupleSlot = NULL;
|
||||
|
||||
|
@ -412,8 +412,6 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
|
||||
*/
|
||||
ExecAssignExprContext(estate, &indexstate->ss.ps);
|
||||
|
||||
indexstate->ss.ps.ps_TupFromTlist = false;
|
||||
|
||||
/*
|
||||
* initialize child expressions
|
||||
*
|
||||
|
@ -336,8 +336,7 @@ EvalOrderByExpressions(IndexScanState *node, ExprContext *econtext)
|
||||
|
||||
node->iss_OrderByValues[i] = ExecEvalExpr(orderby,
|
||||
econtext,
|
||||
&node->iss_OrderByNulls[i],
|
||||
NULL);
|
||||
&node->iss_OrderByNulls[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
@ -590,8 +589,7 @@ ExecIndexEvalRuntimeKeys(ExprContext *econtext,
|
||||
*/
|
||||
scanvalue = ExecEvalExpr(key_expr,
|
||||
econtext,
|
||||
&isNull,
|
||||
NULL);
|
||||
&isNull);
|
||||
if (isNull)
|
||||
{
|
||||
scan_key->sk_argument = scanvalue;
|
||||
@ -648,8 +646,7 @@ ExecIndexEvalArrayKeys(ExprContext *econtext,
|
||||
*/
|
||||
arraydatum = ExecEvalExpr(array_expr,
|
||||
econtext,
|
||||
&isNull,
|
||||
NULL);
|
||||
&isNull);
|
||||
if (isNull)
|
||||
{
|
||||
result = false;
|
||||
@ -837,8 +834,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
|
||||
*/
|
||||
ExecAssignExprContext(estate, &indexstate->ss.ps);
|
||||
|
||||
indexstate->ss.ps.ps_TupFromTlist = false;
|
||||
|
||||
/*
|
||||
* initialize child expressions
|
||||
*
|
||||
|
@ -239,8 +239,7 @@ recompute_limits(LimitState *node)
|
||||
{
|
||||
val = ExecEvalExprSwitchContext(node->limitOffset,
|
||||
econtext,
|
||||
&isNull,
|
||||
NULL);
|
||||
&isNull);
|
||||
/* Interpret NULL offset as no offset */
|
||||
if (isNull)
|
||||
node->offset = 0;
|
||||
@ -263,8 +262,7 @@ recompute_limits(LimitState *node)
|
||||
{
|
||||
val = ExecEvalExprSwitchContext(node->limitCount,
|
||||
econtext,
|
||||
&isNull,
|
||||
NULL);
|
||||
&isNull);
|
||||
/* Interpret NULL count as no count (LIMIT ALL) */
|
||||
if (isNull)
|
||||
{
|
||||
@ -346,18 +344,11 @@ pass_down_bound(LimitState *node, PlanState *child_node)
|
||||
else if (IsA(child_node, ResultState))
|
||||
{
|
||||
/*
|
||||
* An extra consideration here is that if the Result is projecting a
|
||||
* targetlist that contains any SRFs, we can't assume that every input
|
||||
* tuple generates an output tuple, so a Sort underneath might need to
|
||||
* return more than N tuples to satisfy LIMIT N. So we cannot use
|
||||
* bounded sort.
|
||||
*
|
||||
* If Result supported qual checking, we'd have to punt on seeing a
|
||||
* qual, too. Note that having a resconstantqual is not a
|
||||
* showstopper: if that fails we're not getting any rows at all.
|
||||
* qual. Note that having a resconstantqual is not a showstopper: if
|
||||
* that fails we're not getting any rows at all.
|
||||
*/
|
||||
if (outerPlanState(child_node) &&
|
||||
!expression_returns_set((Node *) child_node->plan->targetlist))
|
||||
if (outerPlanState(child_node))
|
||||
pass_down_bound(node, outerPlanState(child_node));
|
||||
}
|
||||
}
|
||||
|
@ -313,7 +313,7 @@ MJEvalOuterValues(MergeJoinState *mergestate)
|
||||
MergeJoinClause clause = &mergestate->mj_Clauses[i];
|
||||
|
||||
clause->ldatum = ExecEvalExpr(clause->lexpr, econtext,
|
||||
&clause->lisnull, NULL);
|
||||
&clause->lisnull);
|
||||
if (clause->lisnull)
|
||||
{
|
||||
/* match is impossible; can we end the join early? */
|
||||
@ -360,7 +360,7 @@ MJEvalInnerValues(MergeJoinState *mergestate, TupleTableSlot *innerslot)
|
||||
MergeJoinClause clause = &mergestate->mj_Clauses[i];
|
||||
|
||||
clause->rdatum = ExecEvalExpr(clause->rexpr, econtext,
|
||||
&clause->risnull, NULL);
|
||||
&clause->risnull);
|
||||
if (clause->risnull)
|
||||
{
|
||||
/* match is impossible; can we end the join early? */
|
||||
@ -465,19 +465,9 @@ MJFillOuter(MergeJoinState *node)
|
||||
* qualification succeeded. now form the desired projection tuple and
|
||||
* return the slot containing it.
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
ExprDoneCond isDone;
|
||||
|
||||
MJ_printf("ExecMergeJoin: returning outer fill tuple\n");
|
||||
|
||||
result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
|
||||
|
||||
if (isDone != ExprEndResult)
|
||||
{
|
||||
node->js.ps.ps_TupFromTlist =
|
||||
(isDone == ExprMultipleResult);
|
||||
return result;
|
||||
}
|
||||
return ExecProject(node->js.ps.ps_ProjInfo);
|
||||
}
|
||||
else
|
||||
InstrCountFiltered2(node, 1);
|
||||
@ -506,19 +496,9 @@ MJFillInner(MergeJoinState *node)
|
||||
* qualification succeeded. now form the desired projection tuple and
|
||||
* return the slot containing it.
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
ExprDoneCond isDone;
|
||||
|
||||
MJ_printf("ExecMergeJoin: returning inner fill tuple\n");
|
||||
|
||||
result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
|
||||
|
||||
if (isDone != ExprEndResult)
|
||||
{
|
||||
node->js.ps.ps_TupFromTlist =
|
||||
(isDone == ExprMultipleResult);
|
||||
return result;
|
||||
}
|
||||
return ExecProject(node->js.ps.ps_ProjInfo);
|
||||
}
|
||||
else
|
||||
InstrCountFiltered2(node, 1);
|
||||
@ -641,27 +621,9 @@ ExecMergeJoin(MergeJoinState *node)
|
||||
doFillOuter = node->mj_FillOuter;
|
||||
doFillInner = node->mj_FillInner;
|
||||
|
||||
/*
|
||||
* Check to see if we're still projecting out tuples from a previous join
|
||||
* tuple (because there is a function-returning-set in the projection
|
||||
* expressions). If so, try to project another one.
|
||||
*/
|
||||
if (node->js.ps.ps_TupFromTlist)
|
||||
{
|
||||
TupleTableSlot *result;
|
||||
ExprDoneCond isDone;
|
||||
|
||||
result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
|
||||
if (isDone == ExprMultipleResult)
|
||||
return result;
|
||||
/* Done with that source tuple... */
|
||||
node->js.ps.ps_TupFromTlist = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset per-tuple memory context to free any expression evaluation
|
||||
* storage allocated in the previous tuple cycle. Note this can't happen
|
||||
* until we're done projecting out tuples from a join tuple.
|
||||
* storage allocated in the previous tuple cycle.
|
||||
*/
|
||||
ResetExprContext(econtext);
|
||||
|
||||
@ -856,20 +818,9 @@ ExecMergeJoin(MergeJoinState *node)
|
||||
* qualification succeeded. now form the desired
|
||||
* projection tuple and return the slot containing it.
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
ExprDoneCond isDone;
|
||||
|
||||
MJ_printf("ExecMergeJoin: returning tuple\n");
|
||||
|
||||
result = ExecProject(node->js.ps.ps_ProjInfo,
|
||||
&isDone);
|
||||
|
||||
if (isDone != ExprEndResult)
|
||||
{
|
||||
node->js.ps.ps_TupFromTlist =
|
||||
(isDone == ExprMultipleResult);
|
||||
return result;
|
||||
}
|
||||
return ExecProject(node->js.ps.ps_ProjInfo);
|
||||
}
|
||||
else
|
||||
InstrCountFiltered2(node, 1);
|
||||
@ -1629,7 +1580,6 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
|
||||
* initialize join state
|
||||
*/
|
||||
mergestate->mj_JoinState = EXEC_MJ_INITIALIZE_OUTER;
|
||||
mergestate->js.ps.ps_TupFromTlist = false;
|
||||
mergestate->mj_MatchedOuter = false;
|
||||
mergestate->mj_MatchedInner = false;
|
||||
mergestate->mj_OuterTupleSlot = NULL;
|
||||
@ -1684,7 +1634,6 @@ ExecReScanMergeJoin(MergeJoinState *node)
|
||||
ExecClearTuple(node->mj_MarkedTupleSlot);
|
||||
|
||||
node->mj_JoinState = EXEC_MJ_INITIALIZE_OUTER;
|
||||
node->js.ps.ps_TupFromTlist = false;
|
||||
node->mj_MatchedOuter = false;
|
||||
node->mj_MatchedInner = false;
|
||||
node->mj_OuterTupleSlot = NULL;
|
||||
|
@ -175,7 +175,7 @@ ExecProcessReturning(ResultRelInfo *resultRelInfo,
|
||||
econtext->ecxt_outertuple = planSlot;
|
||||
|
||||
/* Compute the RETURNING expressions */
|
||||
return ExecProject(projectReturning, NULL);
|
||||
return ExecProject(projectReturning);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1300,7 +1300,7 @@ ExecOnConflictUpdate(ModifyTableState *mtstate,
|
||||
}
|
||||
|
||||
/* Project the new tuple version */
|
||||
ExecProject(resultRelInfo->ri_onConflictSetProj, NULL);
|
||||
ExecProject(resultRelInfo->ri_onConflictSetProj);
|
||||
|
||||
/*
|
||||
* Note that it is possible that the target tuple has been modified in
|
||||
|
@ -81,27 +81,9 @@ ExecNestLoop(NestLoopState *node)
|
||||
innerPlan = innerPlanState(node);
|
||||
econtext = node->js.ps.ps_ExprContext;
|
||||
|
||||
/*
|
||||
* Check to see if we're still projecting out tuples from a previous join
|
||||
* tuple (because there is a function-returning-set in the projection
|
||||
* expressions). If so, try to project another one.
|
||||
*/
|
||||
if (node->js.ps.ps_TupFromTlist)
|
||||
{
|
||||
TupleTableSlot *result;
|
||||
ExprDoneCond isDone;
|
||||
|
||||
result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
|
||||
if (isDone == ExprMultipleResult)
|
||||
return result;
|
||||
/* Done with that source tuple... */
|
||||
node->js.ps.ps_TupFromTlist = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset per-tuple memory context to free any expression evaluation
|
||||
* storage allocated in the previous tuple cycle. Note this can't happen
|
||||
* until we're done projecting out tuples from a join tuple.
|
||||
* storage allocated in the previous tuple cycle.
|
||||
*/
|
||||
ResetExprContext(econtext);
|
||||
|
||||
@ -201,19 +183,9 @@ ExecNestLoop(NestLoopState *node)
|
||||
* the slot containing the result tuple using
|
||||
* ExecProject().
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
ExprDoneCond isDone;
|
||||
|
||||
ENL1_printf("qualification succeeded, projecting tuple");
|
||||
|
||||
result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
|
||||
|
||||
if (isDone != ExprEndResult)
|
||||
{
|
||||
node->js.ps.ps_TupFromTlist =
|
||||
(isDone == ExprMultipleResult);
|
||||
return result;
|
||||
}
|
||||
return ExecProject(node->js.ps.ps_ProjInfo);
|
||||
}
|
||||
else
|
||||
InstrCountFiltered2(node, 1);
|
||||
@ -259,19 +231,9 @@ ExecNestLoop(NestLoopState *node)
|
||||
* qualification was satisfied so we project and return the
|
||||
* slot containing the result tuple using ExecProject().
|
||||
*/
|
||||
TupleTableSlot *result;
|
||||
ExprDoneCond isDone;
|
||||
|
||||
ENL1_printf("qualification succeeded, projecting tuple");
|
||||
|
||||
result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
|
||||
|
||||
if (isDone != ExprEndResult)
|
||||
{
|
||||
node->js.ps.ps_TupFromTlist =
|
||||
(isDone == ExprMultipleResult);
|
||||
return result;
|
||||
}
|
||||
return ExecProject(node->js.ps.ps_ProjInfo);
|
||||
}
|
||||
else
|
||||
InstrCountFiltered2(node, 1);
|
||||
@ -377,7 +339,6 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
|
||||
/*
|
||||
* finally, wipe the current outer tuple clean.
|
||||
*/
|
||||
nlstate->js.ps.ps_TupFromTlist = false;
|
||||
nlstate->nl_NeedNewOuter = true;
|
||||
nlstate->nl_MatchedOuter = false;
|
||||
|
||||
@ -441,7 +402,6 @@ ExecReScanNestLoop(NestLoopState *node)
|
||||
* outer Vars are used as run-time keys...
|
||||
*/
|
||||
|
||||
node->js.ps.ps_TupFromTlist = false;
|
||||
node->nl_NeedNewOuter = true;
|
||||
node->nl_MatchedOuter = false;
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ ExecProjectSRF(ProjectSetState *node, bool continuing)
|
||||
else
|
||||
{
|
||||
/* Non-SRF tlist expression, just evaluate normally. */
|
||||
*result = ExecEvalExpr(gstate->arg, econtext, isnull, NULL);
|
||||
*result = ExecEvalExpr(gstate->arg, econtext, isnull);
|
||||
*isdone = ExprSingleResult;
|
||||
}
|
||||
|
||||
|
@ -67,10 +67,8 @@ TupleTableSlot *
|
||||
ExecResult(ResultState *node)
|
||||
{
|
||||
TupleTableSlot *outerTupleSlot;
|
||||
TupleTableSlot *resultSlot;
|
||||
PlanState *outerPlan;
|
||||
ExprContext *econtext;
|
||||
ExprDoneCond isDone;
|
||||
|
||||
econtext = node->ps.ps_ExprContext;
|
||||
|
||||
@ -91,24 +89,9 @@ ExecResult(ResultState *node)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if we're still projecting out tuples from a previous scan
|
||||
* tuple (because there is a function-returning-set in the projection
|
||||
* expressions). If so, try to project another one.
|
||||
*/
|
||||
if (node->ps.ps_TupFromTlist)
|
||||
{
|
||||
resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
|
||||
if (isDone == ExprMultipleResult)
|
||||
return resultSlot;
|
||||
/* Done with that source tuple... */
|
||||
node->ps.ps_TupFromTlist = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset per-tuple memory context to free any expression evaluation
|
||||
* storage allocated in the previous tuple cycle. Note this can't happen
|
||||
* until we're done projecting out tuples from a scan tuple.
|
||||
* storage allocated in the previous tuple cycle.
|
||||
*/
|
||||
ResetExprContext(econtext);
|
||||
|
||||
@ -147,18 +130,8 @@ ExecResult(ResultState *node)
|
||||
node->rs_done = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* form the result tuple using ExecProject(), and return it --- unless
|
||||
* the projection produces an empty set, in which case we must loop
|
||||
* back to see if there are more outerPlan tuples.
|
||||
*/
|
||||
resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
|
||||
|
||||
if (isDone != ExprEndResult)
|
||||
{
|
||||
node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
|
||||
return resultSlot;
|
||||
}
|
||||
/* form the result tuple using ExecProject(), and return it */
|
||||
return ExecProject(node->ps.ps_ProjInfo);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@ -228,8 +201,6 @@ ExecInitResult(Result *node, EState *estate, int eflags)
|
||||
*/
|
||||
ExecAssignExprContext(estate, &resstate->ps);
|
||||
|
||||
resstate->ps.ps_TupFromTlist = false;
|
||||
|
||||
/*
|
||||
* tuple table initialization
|
||||
*/
|
||||
@ -295,7 +266,6 @@ void
|
||||
ExecReScanResult(ResultState *node)
|
||||
{
|
||||
node->rs_done = false;
|
||||
node->ps.ps_TupFromTlist = false;
|
||||
node->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
|
||||
|
||||
/*
|
||||
|
@ -189,8 +189,6 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags)
|
||||
*/
|
||||
InitScanRelation(scanstate, estate, eflags);
|
||||
|
||||
scanstate->ss.ps.ps_TupFromTlist = false;
|
||||
|
||||
/*
|
||||
* Initialize result tuple type and projection info.
|
||||
*/
|
||||
@ -300,8 +298,7 @@ tablesample_init(SampleScanState *scanstate)
|
||||
|
||||
params[i] = ExecEvalExprSwitchContext(argstate,
|
||||
econtext,
|
||||
&isnull,
|
||||
NULL);
|
||||
&isnull);
|
||||
if (isnull)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TABLESAMPLE_ARGUMENT),
|
||||
@ -313,8 +310,7 @@ tablesample_init(SampleScanState *scanstate)
|
||||
{
|
||||
datum = ExecEvalExprSwitchContext(scanstate->repeatable,
|
||||
econtext,
|
||||
&isnull,
|
||||
NULL);
|
||||
&isnull);
|
||||
if (isnull)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_TABLESAMPLE_REPEAT),
|
||||
|
@ -206,8 +206,6 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
|
||||
*/
|
||||
InitScanRelation(scanstate, estate, eflags);
|
||||
|
||||
scanstate->ss.ps.ps_TupFromTlist = false;
|
||||
|
||||
/*
|
||||
* Initialize result tuple type and projection info.
|
||||
*/
|
||||
|
@ -41,12 +41,10 @@
|
||||
|
||||
static Datum ExecSubPlan(SubPlanState *node,
|
||||
ExprContext *econtext,
|
||||
bool *isNull,
|
||||
ExprDoneCond *isDone);
|
||||
bool *isNull);
|
||||
static Datum ExecAlternativeSubPlan(AlternativeSubPlanState *node,
|
||||
ExprContext *econtext,
|
||||
bool *isNull,
|
||||
ExprDoneCond *isDone);
|
||||
bool *isNull);
|
||||
static Datum ExecHashSubPlan(SubPlanState *node,
|
||||
ExprContext *econtext,
|
||||
bool *isNull);
|
||||
@ -69,15 +67,12 @@ static bool slotNoNulls(TupleTableSlot *slot);
|
||||
static Datum
|
||||
ExecSubPlan(SubPlanState *node,
|
||||
ExprContext *econtext,
|
||||
bool *isNull,
|
||||
ExprDoneCond *isDone)
|
||||
bool *isNull)
|
||||
{
|
||||
SubPlan *subplan = (SubPlan *) node->xprstate.expr;
|
||||
|
||||
/* Set default values for result flags: non-null, not a set result */
|
||||
/* Set non-null as default */
|
||||
*isNull = false;
|
||||
if (isDone)
|
||||
*isDone = ExprSingleResult;
|
||||
|
||||
/* Sanity checks */
|
||||
if (subplan->subLinkType == CTE_SUBLINK)
|
||||
@ -128,7 +123,7 @@ ExecHashSubPlan(SubPlanState *node,
|
||||
* have to set the econtext to use (hack alert!).
|
||||
*/
|
||||
node->projLeft->pi_exprContext = econtext;
|
||||
slot = ExecProject(node->projLeft, NULL);
|
||||
slot = ExecProject(node->projLeft);
|
||||
|
||||
/*
|
||||
* Note: because we are typically called in a per-tuple context, we have
|
||||
@ -285,8 +280,7 @@ ExecScanSubPlan(SubPlanState *node,
|
||||
|
||||
prm->value = ExecEvalExprSwitchContext((ExprState *) lfirst(pvar),
|
||||
econtext,
|
||||
&(prm->isnull),
|
||||
NULL);
|
||||
&(prm->isnull));
|
||||
planstate->chgParam = bms_add_member(planstate->chgParam, paramid);
|
||||
}
|
||||
|
||||
@ -403,7 +397,7 @@ ExecScanSubPlan(SubPlanState *node,
|
||||
}
|
||||
|
||||
rowresult = ExecEvalExprSwitchContext(node->testexpr, econtext,
|
||||
&rownull, NULL);
|
||||
&rownull);
|
||||
|
||||
if (subLinkType == ANY_SUBLINK)
|
||||
{
|
||||
@ -572,7 +566,7 @@ buildSubPlanHash(SubPlanState *node, ExprContext *econtext)
|
||||
&(prmdata->isnull));
|
||||
col++;
|
||||
}
|
||||
slot = ExecProject(node->projRight, NULL);
|
||||
slot = ExecProject(node->projRight);
|
||||
|
||||
/*
|
||||
* If result contains any nulls, store separately or not at all.
|
||||
@ -985,8 +979,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
|
||||
|
||||
prm->value = ExecEvalExprSwitchContext((ExprState *) lfirst(pvar),
|
||||
econtext,
|
||||
&(prm->isnull),
|
||||
NULL);
|
||||
&(prm->isnull));
|
||||
planstate->chgParam = bms_add_member(planstate->chgParam, paramid);
|
||||
}
|
||||
|
||||
@ -1222,8 +1215,7 @@ ExecInitAlternativeSubPlan(AlternativeSubPlan *asplan, PlanState *parent)
|
||||
static Datum
|
||||
ExecAlternativeSubPlan(AlternativeSubPlanState *node,
|
||||
ExprContext *econtext,
|
||||
bool *isNull,
|
||||
ExprDoneCond *isDone)
|
||||
bool *isNull)
|
||||
{
|
||||
/* Just pass control to the active subplan */
|
||||
SubPlanState *activesp = (SubPlanState *) list_nth(node->subplans,
|
||||
@ -1231,8 +1223,5 @@ ExecAlternativeSubPlan(AlternativeSubPlanState *node,
|
||||
|
||||
Assert(IsA(activesp, SubPlanState));
|
||||
|
||||
return ExecSubPlan(activesp,
|
||||
econtext,
|
||||
isNull,
|
||||
isDone);
|
||||
return ExecSubPlan(activesp, econtext, isNull);
|
||||
}
|
||||
|
@ -138,8 +138,6 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
|
||||
*/
|
||||
subquerystate->subplan = ExecInitNode(node->subplan, estate, eflags);
|
||||
|
||||
subquerystate->ss.ps.ps_TupFromTlist = false;
|
||||
|
||||
/*
|
||||
* Initialize scan tuple type (needed by ExecAssignScanProjectionInfo)
|
||||
*/
|
||||
|
@ -104,8 +104,7 @@ TidListCreate(TidScanState *tidstate)
|
||||
itemptr = (ItemPointer)
|
||||
DatumGetPointer(ExecEvalExprSwitchContext(exstate,
|
||||
econtext,
|
||||
&isNull,
|
||||
NULL));
|
||||
&isNull));
|
||||
if (!isNull &&
|
||||
ItemPointerIsValid(itemptr) &&
|
||||
ItemPointerGetBlockNumber(itemptr) < nblocks)
|
||||
@ -133,8 +132,7 @@ TidListCreate(TidScanState *tidstate)
|
||||
exstate = (ExprState *) lsecond(saexstate->fxprstate.args);
|
||||
arraydatum = ExecEvalExprSwitchContext(exstate,
|
||||
econtext,
|
||||
&isNull,
|
||||
NULL);
|
||||
&isNull);
|
||||
if (isNull)
|
||||
continue;
|
||||
itemarray = DatumGetArrayTypeP(arraydatum);
|
||||
@ -469,8 +467,6 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
|
||||
*/
|
||||
ExecAssignExprContext(estate, &tidstate->ss.ps);
|
||||
|
||||
tidstate->ss.ps.ps_TupFromTlist = false;
|
||||
|
||||
/*
|
||||
* initialize child expressions
|
||||
*/
|
||||
|
@ -140,8 +140,7 @@ ValuesNext(ValuesScanState *node)
|
||||
|
||||
values[resind] = ExecEvalExpr(estate,
|
||||
econtext,
|
||||
&isnull[resind],
|
||||
NULL);
|
||||
&isnull[resind]);
|
||||
|
||||
/*
|
||||
* We must force any R/W expanded datums to read-only state, in
|
||||
@ -272,8 +271,6 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
|
||||
scanstate->exprlists[i++] = (List *) lfirst(vtl);
|
||||
}
|
||||
|
||||
scanstate->ss.ps.ps_TupFromTlist = false;
|
||||
|
||||
/*
|
||||
* Initialize result tuple type and projection info.
|
||||
*/
|
||||
|
@ -256,7 +256,7 @@ advance_windowaggregate(WindowAggState *winstate,
|
||||
if (filter)
|
||||
{
|
||||
bool isnull;
|
||||
Datum res = ExecEvalExpr(filter, econtext, &isnull, NULL);
|
||||
Datum res = ExecEvalExpr(filter, econtext, &isnull);
|
||||
|
||||
if (isnull || !DatumGetBool(res))
|
||||
{
|
||||
@ -272,7 +272,7 @@ advance_windowaggregate(WindowAggState *winstate,
|
||||
ExprState *argstate = (ExprState *) lfirst(arg);
|
||||
|
||||
fcinfo->arg[i] = ExecEvalExpr(argstate, econtext,
|
||||
&fcinfo->argnull[i], NULL);
|
||||
&fcinfo->argnull[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
@ -433,7 +433,7 @@ advance_windowaggregate_base(WindowAggState *winstate,
|
||||
if (filter)
|
||||
{
|
||||
bool isnull;
|
||||
Datum res = ExecEvalExpr(filter, econtext, &isnull, NULL);
|
||||
Datum res = ExecEvalExpr(filter, econtext, &isnull);
|
||||
|
||||
if (isnull || !DatumGetBool(res))
|
||||
{
|
||||
@ -449,7 +449,7 @@ advance_windowaggregate_base(WindowAggState *winstate,
|
||||
ExprState *argstate = (ExprState *) lfirst(arg);
|
||||
|
||||
fcinfo->arg[i] = ExecEvalExpr(argstate, econtext,
|
||||
&fcinfo->argnull[i], NULL);
|
||||
&fcinfo->argnull[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
@ -1584,15 +1584,12 @@ update_frametailpos(WindowObject winobj, TupleTableSlot *slot)
|
||||
* ExecWindowAgg receives tuples from its outer subplan and
|
||||
* stores them into a tuplestore, then processes window functions.
|
||||
* This node doesn't reduce nor qualify any row so the number of
|
||||
* returned rows is exactly the same as its outer subplan's result
|
||||
* (ignoring the case of SRFs in the targetlist, that is).
|
||||
* returned rows is exactly the same as its outer subplan's result.
|
||||
* -----------------
|
||||
*/
|
||||
TupleTableSlot *
|
||||
ExecWindowAgg(WindowAggState *winstate)
|
||||
{
|
||||
TupleTableSlot *result;
|
||||
ExprDoneCond isDone;
|
||||
ExprContext *econtext;
|
||||
int i;
|
||||
int numfuncs;
|
||||
@ -1600,23 +1597,6 @@ ExecWindowAgg(WindowAggState *winstate)
|
||||
if (winstate->all_done)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Check to see if we're still projecting out tuples from a previous
|
||||
* output tuple (because there is a function-returning-set in the
|
||||
* projection expressions). If so, try to project another one.
|
||||
*/
|
||||
if (winstate->ss.ps.ps_TupFromTlist)
|
||||
{
|
||||
TupleTableSlot *result;
|
||||
ExprDoneCond isDone;
|
||||
|
||||
result = ExecProject(winstate->ss.ps.ps_ProjInfo, &isDone);
|
||||
if (isDone == ExprMultipleResult)
|
||||
return result;
|
||||
/* Done with that source tuple... */
|
||||
winstate->ss.ps.ps_TupFromTlist = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute frame offset values, if any, during first call.
|
||||
*/
|
||||
@ -1634,8 +1614,7 @@ ExecWindowAgg(WindowAggState *winstate)
|
||||
Assert(winstate->startOffset != NULL);
|
||||
value = ExecEvalExprSwitchContext(winstate->startOffset,
|
||||
econtext,
|
||||
&isnull,
|
||||
NULL);
|
||||
&isnull);
|
||||
if (isnull)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
|
||||
@ -1660,8 +1639,7 @@ ExecWindowAgg(WindowAggState *winstate)
|
||||
Assert(winstate->endOffset != NULL);
|
||||
value = ExecEvalExprSwitchContext(winstate->endOffset,
|
||||
econtext,
|
||||
&isnull,
|
||||
NULL);
|
||||
&isnull);
|
||||
if (isnull)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
|
||||
@ -1684,7 +1662,6 @@ ExecWindowAgg(WindowAggState *winstate)
|
||||
winstate->all_first = false;
|
||||
}
|
||||
|
||||
restart:
|
||||
if (winstate->buffer == NULL)
|
||||
{
|
||||
/* Initialize for first partition and set current row = 0 */
|
||||
@ -1776,17 +1753,8 @@ restart:
|
||||
* evaluated with respect to that row.
|
||||
*/
|
||||
econtext->ecxt_outertuple = winstate->ss.ss_ScanTupleSlot;
|
||||
result = ExecProject(winstate->ss.ps.ps_ProjInfo, &isDone);
|
||||
|
||||
if (isDone == ExprEndResult)
|
||||
{
|
||||
/* SRF in tlist returned no rows, so advance to next input tuple */
|
||||
goto restart;
|
||||
}
|
||||
|
||||
winstate->ss.ps.ps_TupFromTlist =
|
||||
(isDone == ExprMultipleResult);
|
||||
return result;
|
||||
return ExecProject(winstate->ss.ps.ps_ProjInfo);
|
||||
}
|
||||
|
||||
/* -----------------
|
||||
@ -1896,8 +1864,6 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
|
||||
ExecAssignResultTypeFromTL(&winstate->ss.ps);
|
||||
ExecAssignProjectionInfo(&winstate->ss.ps, NULL);
|
||||
|
||||
winstate->ss.ps.ps_TupFromTlist = false;
|
||||
|
||||
/* Set up data for comparing tuples */
|
||||
if (node->partNumCols > 0)
|
||||
winstate->partEqfunctions = execTuplesMatchPrepare(node->partNumCols,
|
||||
@ -2090,8 +2056,6 @@ ExecReScanWindowAgg(WindowAggState *node)
|
||||
ExprContext *econtext = node->ss.ps.ps_ExprContext;
|
||||
|
||||
node->all_done = false;
|
||||
|
||||
node->ss.ps.ps_TupFromTlist = false;
|
||||
node->all_first = true;
|
||||
|
||||
/* release tuplestore et al */
|
||||
@ -2712,7 +2676,7 @@ WinGetFuncArgInPartition(WindowObject winobj, int argno,
|
||||
}
|
||||
econtext->ecxt_outertuple = slot;
|
||||
return ExecEvalExpr((ExprState *) list_nth(winobj->argstates, argno),
|
||||
econtext, isnull, NULL);
|
||||
econtext, isnull);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2811,7 +2775,7 @@ WinGetFuncArgInFrame(WindowObject winobj, int argno,
|
||||
}
|
||||
econtext->ecxt_outertuple = slot;
|
||||
return ExecEvalExpr((ExprState *) list_nth(winobj->argstates, argno),
|
||||
econtext, isnull, NULL);
|
||||
econtext, isnull);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2841,5 +2805,5 @@ WinGetFuncArgCurrent(WindowObject winobj, int argno, bool *isnull)
|
||||
|
||||
econtext->ecxt_outertuple = winstate->ss.ss_ScanTupleSlot;
|
||||
return ExecEvalExpr((ExprState *) list_nth(winobj->argstates, argno),
|
||||
econtext, isnull, NULL);
|
||||
econtext, isnull);
|
||||
}
|
||||
|
@ -174,8 +174,6 @@ ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags)
|
||||
*/
|
||||
ExecAssignResultTypeFromTL(&scanstate->ss.ps);
|
||||
|
||||
scanstate->ss.ps.ps_TupFromTlist = false;
|
||||
|
||||
return scanstate;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user