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/nodeSubqueryscan.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/nodeSubqueryscan.c')
-rw-r--r-- | src/backend/executor/nodeSubqueryscan.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c index 9bc5a6294d0..90e59f90f4d 100644 --- a/src/backend/executor/nodeSubqueryscan.c +++ b/src/backend/executor/nodeSubqueryscan.c @@ -12,7 +12,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.25 2004/12/31 21:59:45 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeSubqueryscan.c,v 1.26 2005/05/22 22:30:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -78,6 +78,10 @@ SubqueryNext(SubqueryScanState *node) MemoryContextSwitchTo(oldcontext); + /* + * We just overwrite our ScanTupleSlot with the subplan's result slot, + * rather than expending the cycles for ExecCopySlot(). + */ node->ss.ss_ScanTupleSlot = slot; return slot; @@ -144,12 +148,13 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate) ExecInitExpr((Expr *) node->scan.plan.qual, (PlanState *) subquerystate); -#define SUBQUERYSCAN_NSLOTS 1 +#define SUBQUERYSCAN_NSLOTS 2 /* * tuple table initialization */ ExecInitResultTupleSlot(estate, &subquerystate->ss.ps); + ExecInitScanTupleSlot(estate, &subquerystate->ss); /* * initialize subquery @@ -160,6 +165,11 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate) Assert(rte->rtekind == RTE_SUBQUERY); /* + * Do access checking on the rangetable entries in the subquery. + */ + ExecCheckRTPerms(rte->subquery->rtable); + + /* * The subquery needs its own EState because it has its own * rangetable. It shares our Param ID space, however. XXX if * rangetable access were done differently, the subquery could share @@ -187,14 +197,20 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate) MemoryContextSwitchTo(oldcontext); - subquerystate->ss.ss_ScanTupleSlot = NULL; subquerystate->ss.ps.ps_TupFromTlist = false; /* + * Initialize scan tuple type (needed by ExecAssignScanProjectionInfo) + */ + ExecAssignScanType(&subquerystate->ss, + ExecGetResultType(subquerystate->subplan), + false); + + /* * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&subquerystate->ss.ps); - ExecAssignProjectionInfo(&subquerystate->ss.ps); + ExecAssignScanProjectionInfo(&subquerystate->ss); return subquerystate; } @@ -230,6 +246,7 @@ ExecEndSubqueryScan(SubqueryScanState *node) * clean out the upper tuple table */ ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); + node->ss.ss_ScanTupleSlot = NULL; /* not ours to clear */ /* * close down subquery |