diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execMain.c | 16 | ||||
-rw-r--r-- | src/backend/executor/execScan.c | 13 | ||||
-rw-r--r-- | src/backend/executor/nodeAppend.c | 79 | ||||
-rw-r--r-- | src/backend/executor/nodeFunctionscan.c | 7 | ||||
-rw-r--r-- | src/backend/executor/nodeSubqueryscan.c | 25 |
5 files changed, 70 insertions, 70 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index b45850bd2b4..a390829bb8e 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -26,7 +26,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.248 2005/05/06 17:24:53 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.249 2005/05/22 22:30:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -353,16 +353,10 @@ ExecCheckRTEPerms(RangeTblEntry *rte) AclId userid; /* - * If it's a subquery, recursively examine its rangetable. - */ - if (rte->rtekind == RTE_SUBQUERY) - { - ExecCheckRTPerms(rte->subquery->rtable); - return; - } - - /* - * Otherwise, only plain-relation RTEs need to be checked here. + * Only plain-relation RTEs need to be checked here. Subquery RTEs + * are checked by ExecInitSubqueryScan if the subquery is still a + * separate subquery --- if it's been pulled up into our query level + * then the RTEs are in our rangetable and will be checked here. * Function RTEs are checked by init_fcache when the function is * prepared for execution. Join and special RTEs need no checks. */ diff --git a/src/backend/executor/execScan.c b/src/backend/executor/execScan.c index 1e80fa7be06..843aa15101c 100644 --- a/src/backend/executor/execScan.c +++ b/src/backend/executor/execScan.c @@ -12,7 +12,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/execScan.c,v 1.35 2005/03/16 21:38:06 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/execScan.c,v 1.36 2005/05/22 22:30:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -48,7 +48,6 @@ TupleTableSlot * ExecScan(ScanState *node, ExecScanAccessMtd accessMtd) /* function returning a tuple */ { - EState *estate; ExprContext *econtext; List *qual; ProjectionInfo *projInfo; @@ -58,12 +57,17 @@ ExecScan(ScanState *node, /* * Fetch data from node */ - estate = node->ps.state; - econtext = node->ps.ps_ExprContext; qual = node->ps.qual; projInfo = node->ps.ps_ProjInfo; /* + * If we have neither a qual to check nor a projection to do, + * just skip all the overhead and return the raw scan tuple. + */ + if (!qual && !projInfo) + return (*accessMtd) (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. @@ -83,6 +87,7 @@ ExecScan(ScanState *node, * storage allocated in the previous tuple cycle. Note this can't * happen until we're done projecting out tuples from a scan tuple. */ + econtext = node->ps.ps_ExprContext; ResetExprContext(econtext); /* 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 */ } } diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c index f8f13f1c786..5cd6de45fda 100644 --- a/src/backend/executor/nodeFunctionscan.c +++ b/src/backend/executor/nodeFunctionscan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.33 2005/04/14 22:09:40 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeFunctionscan.c,v 1.34 2005/05/22 22:30:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -219,8 +219,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate) BlessTupleDesc(tupdesc); scanstate->tupdesc = tupdesc; - ExecSetSlotDescriptor(scanstate->ss.ss_ScanTupleSlot, - tupdesc, false); + ExecAssignScanType(&scanstate->ss, tupdesc, false); /* * Other node-specific setup @@ -235,7 +234,7 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate) * Initialize result tuple type and projection info. */ ExecAssignResultTypeFromTL(&scanstate->ss.ps); - ExecAssignProjectionInfo(&scanstate->ss.ps); + ExecAssignScanProjectionInfo(&scanstate->ss); return scanstate; } 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 |