diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execMain.c | 144 | ||||
-rw-r--r-- | src/backend/executor/functions.c | 7 | ||||
-rw-r--r-- | src/backend/executor/spi.c | 39 |
3 files changed, 173 insertions, 17 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 5ce90902b4c..e11869ce783 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -26,7 +26,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.75 1999/02/07 16:17:11 wieck Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.76 1999/02/08 14:14:09 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -60,21 +60,27 @@ void ExecCheckPerms(CmdType operation, int resultRelation, List *rangeTable, /* decls for local routines only used within this module */ -static TupleDesc InitPlan(CmdType operation, Query *parseTree, - Plan *plan, EState *estate); -static void EndPlan(Plan *plan, EState *estate); +static TupleDesc InitPlan(CmdType operation, + Query *parseTree, + Plan *plan, + EState *estate); +static void EndPlan(Plan *plan, + EState *estate); static TupleTableSlot *ExecutePlan(EState *estate, Plan *plan, - CmdType operation, int numberTuples, ScanDirection direction, - DestReceiver *destfunc); + CmdType operation, + int offsetTuples, + int numberTuples, + ScanDirection direction, + DestReceiver *destfunc); static void ExecRetrieve(TupleTableSlot *slot, - DestReceiver *destfunc, - EState *estate); + DestReceiver *destfunc, + EState *estate); static void ExecAppend(TupleTableSlot *slot, ItemPointer tupleid, - EState *estate); + EState *estate); static void ExecDelete(TupleTableSlot *slot, ItemPointer tupleid, - EState *estate); + EState *estate); static void ExecReplace(TupleTableSlot *slot, ItemPointer tupleid, - EState *estate); + EState *estate); TupleTableSlot *EvalPlanQual(EState *estate, Index rti, ItemPointer tid); static TupleTableSlot *EvalPlanQualNext(EState *estate); @@ -187,13 +193,16 @@ ExecutorStart(QueryDesc *queryDesc, EState *estate) * ---------------------------------------------------------------- */ TupleTableSlot * -ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) +ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, + Node *limoffset, Node *limcount) { CmdType operation; Plan *plan; TupleTableSlot *result; CommandDest dest; DestReceiver *destfunc; + int offset = 0; + int count = 0; /****************** * sanity checks @@ -222,6 +231,96 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) */ (*destfunc->setup) (destfunc, (TupleDesc) NULL); + /****************** + * if given get the offset of the LIMIT clause + ****************** + */ + if (limoffset != NULL) + { + Const *coffset; + Param *poffset; + ParamListInfo paramLI; + int i; + + switch (nodeTag(limoffset)) + { + case T_Const: + coffset = (Const *)limoffset; + offset = (int)(coffset->constvalue); + break; + + case T_Param: + poffset = (Param *)limoffset; + paramLI = estate->es_param_list_info; + + if (paramLI == NULL) + elog(ERROR, "parameter for limit offset not in executor state"); + for (i = 0; paramLI[i].kind != PARAM_INVALID; i++) + { + if (paramLI[i].kind == PARAM_NUM && paramLI[i].id == poffset->paramid) + break; + } + if (paramLI[i].kind == PARAM_INVALID) + elog(ERROR, "parameter for limit offset not in executor state"); + if (paramLI[i].isnull) + elog(ERROR, "limit offset cannot be NULL value"); + offset = (int)(paramLI[i].value); + + break; + + default: + elog(ERROR, "unexpected node type %d as limit offset", nodeTag(limoffset)); + } + + if (offset < 0) + elog(ERROR, "limit offset cannot be negative"); + } + + /****************** + * if given get the count of the LIMIT clause + ****************** + */ + if (limcount != NULL) + { + Const *ccount; + Param *pcount; + ParamListInfo paramLI; + int i; + + switch (nodeTag(limcount)) + { + case T_Const: + ccount = (Const *)limcount; + count = (int)(ccount->constvalue); + break; + + case T_Param: + pcount = (Param *)limcount; + paramLI = estate->es_param_list_info; + + if (paramLI == NULL) + elog(ERROR, "parameter for limit count not in executor state"); + for (i = 0; paramLI[i].kind != PARAM_INVALID; i++) + { + if (paramLI[i].kind == PARAM_NUM && paramLI[i].id == pcount->paramid) + break; + } + if (paramLI[i].kind == PARAM_INVALID) + elog(ERROR, "parameter for limit count not in executor state"); + if (paramLI[i].isnull) + elog(ERROR, "limit count cannot be NULL value"); + count = (int)(paramLI[i].value); + + break; + + default: + elog(ERROR, "unexpected node type %d as limit count", nodeTag(limcount)); + } + + if (count < 0) + elog(ERROR, "limit count cannot be negative"); + } + switch (feature) { @@ -229,7 +328,8 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) result = ExecutePlan(estate, plan, operation, - ALL_TUPLES, + offset, + count, ForwardScanDirection, destfunc); break; @@ -237,6 +337,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) result = ExecutePlan(estate, plan, operation, + offset, count, ForwardScanDirection, destfunc); @@ -250,6 +351,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) result = ExecutePlan(estate, plan, operation, + offset, count, BackwardScanDirection, destfunc); @@ -264,6 +366,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count) result = ExecutePlan(estate, plan, operation, + 0, ONE_TUPLE, ForwardScanDirection, destfunc); @@ -784,6 +887,7 @@ static TupleTableSlot * ExecutePlan(EState *estate, Plan *plan, CmdType operation, + int offsetTuples, int numberTuples, ScanDirection direction, DestReceiver* destfunc) @@ -846,6 +950,20 @@ lnext:; } /****************** + * For now we completely execute the plan and skip + * result tuples if requested by LIMIT offset. + * Finally we should try to do it in deeper levels + * if possible (during index scan) + * - Jan + ****************** + */ + if (offsetTuples > 0) + { + --offsetTuples; + continue; + } + + /****************** * if we have a junk filter, then project a new * tuple with the junk removed. * diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c index 51ea6655e9d..7108a1cab52 100644 --- a/src/backend/executor/functions.c +++ b/src/backend/executor/functions.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.22 1999/02/03 21:16:12 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.23 1999/02/08 14:14:09 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -130,6 +130,9 @@ init_execution_state(FunctionCachePtr fcache, None); estate = CreateExecutorState(); + if (queryTree->limitOffset != NULL || queryTree->limitCount != NULL) + elog(ERROR, "LIMIT clause from SQL functions not yet implemented"); + if (nargs > 0) { int i; @@ -199,7 +202,7 @@ postquel_getnext(execution_state *es) feature = (LAST_POSTQUEL_COMMAND(es)) ? EXEC_RETONE : EXEC_RUN; - return ExecutorRun(es->qd, es->estate, feature, 0); + return ExecutorRun(es->qd, es->estate, feature, (Node *)NULL, (Node *)NULL); } static void diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index 7ca2a6c21e5..397f68a4055 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -3,7 +3,7 @@ * spi.c-- * Server Programming Interface * - * $Id: spi.c,v 1.32 1999/01/27 16:15:20 wieck Exp $ + * $Id: spi.c,v 1.33 1999/02/08 14:14:10 wieck Exp $ * *------------------------------------------------------------------------- */ @@ -779,6 +779,8 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount) bool isRetrieveIntoRelation = false; char *intoName = NULL; int res; + Const tcount_const; + Node *count = NULL; switch (operation) { @@ -813,6 +815,39 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount) return SPI_ERROR_OPUNKNOWN; } + /* ---------------- + * Get the query LIMIT tuple count + * ---------------- + */ + if (parseTree->limitCount != NULL) + { + /* ---------------- + * A limit clause in the parsetree overrides the + * tcount parameter + * ---------------- + */ + count = parseTree->limitCount; + } + else + { + /* ---------------- + * No LIMIT clause in parsetree. Use a local Const node + * to put tcount into it + * ---------------- + */ + memset(&tcount_const, 0, sizeof(tcount_const)); + tcount_const.type = T_Const; + tcount_const.consttype = INT4OID; + tcount_const.constlen = sizeof(int4); + tcount_const.constvalue = (Datum)tcount; + tcount_const.constisnull = FALSE; + tcount_const.constbyval = TRUE; + tcount_const.constisset = FALSE; + tcount_const.constiscast = FALSE; + + count = (Node *)&tcount_const; + } + if (state == NULL) /* plan preparation */ return res; #ifdef SPI_EXECUTOR_STATS @@ -833,7 +868,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount) return SPI_OK_CURSOR; } - ExecutorRun(queryDesc, state, EXEC_FOR, tcount); + ExecutorRun(queryDesc, state, EXEC_FOR, parseTree->limitOffset, count); _SPI_current->processed = state->es_processed; if (operation == CMD_SELECT && queryDesc->dest == SPI) |