mirror of
https://github.com/postgres/postgres.git
synced 2025-07-31 22:04:40 +03:00
Teach the planner to remove SubqueryScan nodes from the plan if they
aren't doing anything useful (ie, neither selection nor projection). Also, extend to SubqueryScan the hacks already in place to avoid unnecessary ExecProject calls when the result would just be the same tuple the subquery already delivered. This saves some overhead in UNION and other set operations, as well as avoiding overhead for unflatten-able subqueries. Per example from Sokolov Yura.
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/executor/nodeAppend.c,v 1.63 2005/04/24 11:46:20 neilc Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/executor/nodeAppend.c,v 1.64 2005/05/22 22:30:19 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -251,67 +251,52 @@ ExecCountSlotsAppend(Append *node)
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecAppend
|
||||
*
|
||||
* Handles the iteration over the multiple scans.
|
||||
* Handles iteration over multiple subplans.
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
TupleTableSlot *
|
||||
ExecAppend(AppendState *node)
|
||||
{
|
||||
EState *estate;
|
||||
int whichplan;
|
||||
PlanState *subnode;
|
||||
TupleTableSlot *result;
|
||||
TupleTableSlot *result_slot;
|
||||
ScanDirection direction;
|
||||
|
||||
/*
|
||||
* get information from the node
|
||||
*/
|
||||
estate = node->ps.state;
|
||||
direction = estate->es_direction;
|
||||
whichplan = node->as_whichplan;
|
||||
result_slot = node->ps.ps_ResultTupleSlot;
|
||||
|
||||
/*
|
||||
* figure out which subplan we are currently processing
|
||||
*/
|
||||
subnode = node->appendplans[whichplan];
|
||||
|
||||
/*
|
||||
* get a tuple from the subplan
|
||||
*/
|
||||
result = ExecProcNode(subnode);
|
||||
|
||||
if (!TupIsNull(result))
|
||||
for (;;)
|
||||
{
|
||||
PlanState *subnode;
|
||||
TupleTableSlot *result;
|
||||
|
||||
/*
|
||||
* if the subplan gave us something then return it as-is. We do
|
||||
* NOT make use of the result slot that was set up in ExecInitAppend,
|
||||
* first because there's no reason to and second because it may have
|
||||
* the wrong tuple descriptor in inherited-UPDATE cases.
|
||||
* figure out which subplan we are currently processing
|
||||
*/
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
subnode = node->appendplans[node->as_whichplan];
|
||||
|
||||
/*
|
||||
* .. go on to the "next" subplan in the appropriate direction and
|
||||
* try processing again (recursively)
|
||||
* get a tuple from the subplan
|
||||
*/
|
||||
if (ScanDirectionIsForward(direction))
|
||||
result = ExecProcNode(subnode);
|
||||
|
||||
if (!TupIsNull(result))
|
||||
{
|
||||
/*
|
||||
* If the subplan gave us something then return it as-is.
|
||||
* We do NOT make use of the result slot that was set up in
|
||||
* ExecInitAppend, first because there's no reason to and
|
||||
* second because it may have the wrong tuple descriptor in
|
||||
* inherited-UPDATE cases.
|
||||
*/
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Go on to the "next" subplan in the appropriate direction.
|
||||
* If no more subplans, return the empty slot set up for us
|
||||
* by ExecInitAppend.
|
||||
*/
|
||||
if (ScanDirectionIsForward(node->ps.state->es_direction))
|
||||
node->as_whichplan++;
|
||||
else
|
||||
node->as_whichplan--;
|
||||
if (!exec_append_initialize_next(node))
|
||||
return ExecClearTuple(node->ps.ps_ResultTupleSlot);
|
||||
|
||||
/*
|
||||
* return something from next node or an empty slot if all of our
|
||||
* subplans have been exhausted. The empty slot is the one set up
|
||||
* by ExecInitAppend.
|
||||
*/
|
||||
if (exec_append_initialize_next(node))
|
||||
return ExecAppend(node);
|
||||
else
|
||||
return ExecClearTuple(result_slot);
|
||||
/* Else loop back and try to get a tuple from the new subplan */
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user