mirror of
https://github.com/postgres/postgres.git
synced 2025-04-22 23:02:54 +03:00
Support set-returning functions in the target lists of Agg and Group plan
nodes. This is a pretty ugly feature but since we don't yet have a plausible substitute, we'd better support it everywhere. Per gripe from Jeff Davis.
This commit is contained in:
parent
8818f3793e
commit
a26c7e3d71
@ -61,7 +61,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.160 2008/08/25 22:42:32 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/executor/nodeAgg.c,v 1.161 2008/09/08 00:22:55 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -805,6 +805,23 @@ ExecAgg(AggState *node)
|
|||||||
if (node->agg_done)
|
if (node->agg_done)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
|
if (((Agg *) node->ss.ps.plan)->aggstrategy == AGG_HASHED)
|
||||||
{
|
{
|
||||||
if (!node->table_filled)
|
if (!node->table_filled)
|
||||||
@ -825,7 +842,6 @@ agg_retrieve_direct(AggState *aggstate)
|
|||||||
PlanState *outerPlan;
|
PlanState *outerPlan;
|
||||||
ExprContext *econtext;
|
ExprContext *econtext;
|
||||||
ExprContext *tmpcontext;
|
ExprContext *tmpcontext;
|
||||||
ProjectionInfo *projInfo;
|
|
||||||
Datum *aggvalues;
|
Datum *aggvalues;
|
||||||
bool *aggnulls;
|
bool *aggnulls;
|
||||||
AggStatePerAgg peragg;
|
AggStatePerAgg peragg;
|
||||||
@ -844,7 +860,6 @@ agg_retrieve_direct(AggState *aggstate)
|
|||||||
aggnulls = econtext->ecxt_aggnulls;
|
aggnulls = econtext->ecxt_aggnulls;
|
||||||
/* tmpcontext is the per-input-tuple expression context */
|
/* tmpcontext is the per-input-tuple expression context */
|
||||||
tmpcontext = aggstate->tmpcontext;
|
tmpcontext = aggstate->tmpcontext;
|
||||||
projInfo = aggstate->ss.ps.ps_ProjInfo;
|
|
||||||
peragg = aggstate->peragg;
|
peragg = aggstate->peragg;
|
||||||
pergroup = aggstate->pergroup;
|
pergroup = aggstate->pergroup;
|
||||||
firstSlot = aggstate->ss.ss_ScanTupleSlot;
|
firstSlot = aggstate->ss.ss_ScanTupleSlot;
|
||||||
@ -982,10 +997,19 @@ agg_retrieve_direct(AggState *aggstate)
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Form and return a projection tuple using the aggregate results
|
* Form and return a projection tuple using the aggregate results
|
||||||
* and the representative input tuple. Note we do not support
|
* and the representative input tuple.
|
||||||
* aggregates returning sets ...
|
|
||||||
*/
|
*/
|
||||||
return ExecProject(projInfo, NULL);
|
TupleTableSlot *result;
|
||||||
|
ExprDoneCond isDone;
|
||||||
|
|
||||||
|
result = ExecProject(aggstate->ss.ps.ps_ProjInfo, &isDone);
|
||||||
|
|
||||||
|
if (isDone != ExprEndResult)
|
||||||
|
{
|
||||||
|
aggstate->ss.ps.ps_TupFromTlist =
|
||||||
|
(isDone == ExprMultipleResult);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1045,7 +1069,6 @@ static TupleTableSlot *
|
|||||||
agg_retrieve_hash_table(AggState *aggstate)
|
agg_retrieve_hash_table(AggState *aggstate)
|
||||||
{
|
{
|
||||||
ExprContext *econtext;
|
ExprContext *econtext;
|
||||||
ProjectionInfo *projInfo;
|
|
||||||
Datum *aggvalues;
|
Datum *aggvalues;
|
||||||
bool *aggnulls;
|
bool *aggnulls;
|
||||||
AggStatePerAgg peragg;
|
AggStatePerAgg peragg;
|
||||||
@ -1061,7 +1084,6 @@ agg_retrieve_hash_table(AggState *aggstate)
|
|||||||
econtext = aggstate->ss.ps.ps_ExprContext;
|
econtext = aggstate->ss.ps.ps_ExprContext;
|
||||||
aggvalues = econtext->ecxt_aggvalues;
|
aggvalues = econtext->ecxt_aggvalues;
|
||||||
aggnulls = econtext->ecxt_aggnulls;
|
aggnulls = econtext->ecxt_aggnulls;
|
||||||
projInfo = aggstate->ss.ps.ps_ProjInfo;
|
|
||||||
peragg = aggstate->peragg;
|
peragg = aggstate->peragg;
|
||||||
firstSlot = aggstate->ss.ss_ScanTupleSlot;
|
firstSlot = aggstate->ss.ss_ScanTupleSlot;
|
||||||
|
|
||||||
@ -1125,10 +1147,19 @@ agg_retrieve_hash_table(AggState *aggstate)
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Form and return a projection tuple using the aggregate results
|
* Form and return a projection tuple using the aggregate results
|
||||||
* and the representative input tuple. Note we do not support
|
* and the representative input tuple.
|
||||||
* aggregates returning sets ...
|
|
||||||
*/
|
*/
|
||||||
return ExecProject(projInfo, NULL);
|
TupleTableSlot *result;
|
||||||
|
ExprDoneCond isDone;
|
||||||
|
|
||||||
|
result = ExecProject(aggstate->ss.ps.ps_ProjInfo, &isDone);
|
||||||
|
|
||||||
|
if (isDone != ExprEndResult)
|
||||||
|
{
|
||||||
|
aggstate->ss.ps.ps_TupFromTlist =
|
||||||
|
(isDone == ExprMultipleResult);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* locate group boundaries.
|
* locate group boundaries.
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/executor/nodeGroup.c,v 1.70 2008/01/01 19:45:49 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/executor/nodeGroup.c,v 1.71 2008/09/08 00:22:56 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -49,6 +49,23 @@ ExecGroup(GroupState *node)
|
|||||||
numCols = ((Group *) node->ss.ps.plan)->numCols;
|
numCols = ((Group *) node->ss.ps.plan)->numCols;
|
||||||
grpColIdx = ((Group *) node->ss.ps.plan)->grpColIdx;
|
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.
|
* The ScanTupleSlot holds the (copied) first tuple of each group.
|
||||||
*/
|
*/
|
||||||
@ -90,7 +107,16 @@ ExecGroup(GroupState *node)
|
|||||||
/*
|
/*
|
||||||
* Form and return a projection tuple using the first input tuple.
|
* Form and return a projection tuple using the first input tuple.
|
||||||
*/
|
*/
|
||||||
return ExecProject(node->ss.ps.ps_ProjInfo, NULL);
|
TupleTableSlot *result;
|
||||||
|
ExprDoneCond isDone;
|
||||||
|
|
||||||
|
result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
|
||||||
|
|
||||||
|
if (isDone != ExprEndResult)
|
||||||
|
{
|
||||||
|
node->ss.ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +168,16 @@ ExecGroup(GroupState *node)
|
|||||||
/*
|
/*
|
||||||
* Form and return a projection tuple using the first input tuple.
|
* Form and return a projection tuple using the first input tuple.
|
||||||
*/
|
*/
|
||||||
return ExecProject(node->ss.ps.ps_ProjInfo, NULL);
|
TupleTableSlot *result;
|
||||||
|
ExprDoneCond isDone;
|
||||||
|
|
||||||
|
result = ExecProject(node->ss.ps.ps_ProjInfo, &isDone);
|
||||||
|
|
||||||
|
if (isDone != ExprEndResult)
|
||||||
|
{
|
||||||
|
node->ss.ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user