diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2005-05-22 22:30:20 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2005-05-22 22:30:20 +0000 |
commit | e2159f384268e01282af60515582943bf595ba7b (patch) | |
tree | 89fa7f4dce0cb8ed7a3296e08e30e71c01f7f84f /src/backend/executor/nodeAppend.c | |
parent | c61207b0913b947d17b837a3d532de81a385977d (diff) | |
download | postgresql-e2159f384268e01282af60515582943bf595ba7b.tar.gz postgresql-e2159f384268e01282af60515582943bf595ba7b.zip |
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.
Diffstat (limited to 'src/backend/executor/nodeAppend.c')
-rw-r--r-- | src/backend/executor/nodeAppend.c | 79 |
1 files changed, 32 insertions, 47 deletions
diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c index 0f77741a825..b88eec46a40 100644 --- a/src/backend/executor/nodeAppend.c +++ b/src/backend/executor/nodeAppend.c @@ -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)) - node->as_whichplan++; - else - node->as_whichplan--; + 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; + } /* - * 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 + * 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 (exec_append_initialize_next(node)) - return ExecAppend(node); + if (ScanDirectionIsForward(node->ps.state->es_direction)) + node->as_whichplan++; else - return ExecClearTuple(result_slot); + node->as_whichplan--; + if (!exec_append_initialize_next(node)) + return ExecClearTuple(node->ps.ps_ResultTupleSlot); + + /* Else loop back and try to get a tuple from the new subplan */ } } |