Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitbe948af

Browse files
Jan WieckJan Wieck
Jan Wieck
authored and
Jan Wieck
committed
Added LIMIT/OFFSET functionality including new regression test for it.
Removed CURRENT keyword for rule queries and changed rules regressionaccordingly. CURRENT has beed announced to disappear in v6.5.Jan
1 parent54e5d25 commitbe948af

File tree

15 files changed

+472
-63
lines changed

15 files changed

+472
-63
lines changed

‎src/backend/commands/command.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.36 1999/02/03 21:16:02 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.37 1999/02/08 14:14:08 wieck Exp $
1111
*
1212
* NOTES
1313
* The PortalExecutorHeapMemory crap needs to be eliminated
@@ -40,6 +40,7 @@
4040
#include"utils/portal.h"
4141
#include"utils/syscache.h"
4242
#include"miscadmin.h"
43+
#include"string.h"
4344

4445
/* ----------------
4546
*PortalExecutorHeapMemory stuff
@@ -102,6 +103,7 @@ PerformPortalFetch(char *name,
102103
intfeature;
103104
QueryDesc*queryDesc;
104105
MemoryContextcontext;
106+
Constlimcount;
105107

106108
/* ----------------
107109
*sanity checks
@@ -113,6 +115,21 @@ PerformPortalFetch(char *name,
113115
return;
114116
}
115117

118+
/* ----------------
119+
* Create a const node from the given count value
120+
* ----------------
121+
*/
122+
memset(&limcount,0,sizeof(limcount));
123+
limcount.type=T_Const;
124+
limcount.consttype=INT4OID;
125+
limcount.constlen=sizeof(int4);
126+
limcount.constvalue= (Datum)count;
127+
limcount.constisnull= FALSE;
128+
limcount.constbyval= TRUE;
129+
limcount.constisset= FALSE;
130+
limcount.constiscast= FALSE;
131+
132+
116133
/* ----------------
117134
*get the portal from the portal name
118135
* ----------------
@@ -176,7 +193,8 @@ PerformPortalFetch(char *name,
176193
PortalExecutorHeapMemory= (MemoryContext)
177194
PortalGetHeapMemory(portal);
178195

179-
ExecutorRun(queryDesc,PortalGetState(portal),feature,count);
196+
ExecutorRun(queryDesc,PortalGetState(portal),feature,
197+
(Node*)NULL, (Node*)&limcount);
180198

181199
if (dest==None)/* MOVE */
182200
pfree(queryDesc);

‎src/backend/executor/execMain.c

Lines changed: 131 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*
2727
*
2828
* IDENTIFICATION
29-
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.75 1999/02/07 16:17:11 wieck Exp $
29+
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.76 1999/02/08 14:14:09 wieck Exp $
3030
*
3131
*-------------------------------------------------------------------------
3232
*/
@@ -60,21 +60,27 @@ void ExecCheckPerms(CmdType operation, int resultRelation, List *rangeTable,
6060

6161

6262
/* decls for local routines only used within this module */
63-
staticTupleDescInitPlan(CmdTypeoperation,Query*parseTree,
64-
Plan*plan,EState*estate);
65-
staticvoidEndPlan(Plan*plan,EState*estate);
63+
staticTupleDescInitPlan(CmdTypeoperation,
64+
Query*parseTree,
65+
Plan*plan,
66+
EState*estate);
67+
staticvoidEndPlan(Plan*plan,
68+
EState*estate);
6669
staticTupleTableSlot*ExecutePlan(EState*estate,Plan*plan,
67-
CmdTypeoperation,intnumberTuples,ScanDirectiondirection,
68-
DestReceiver*destfunc);
70+
CmdTypeoperation,
71+
intoffsetTuples,
72+
intnumberTuples,
73+
ScanDirectiondirection,
74+
DestReceiver*destfunc);
6975
staticvoidExecRetrieve(TupleTableSlot*slot,
70-
DestReceiver*destfunc,
71-
EState*estate);
76+
DestReceiver*destfunc,
77+
EState*estate);
7278
staticvoidExecAppend(TupleTableSlot*slot,ItemPointertupleid,
73-
EState*estate);
79+
EState*estate);
7480
staticvoidExecDelete(TupleTableSlot*slot,ItemPointertupleid,
75-
EState*estate);
81+
EState*estate);
7682
staticvoidExecReplace(TupleTableSlot*slot,ItemPointertupleid,
77-
EState*estate);
83+
EState*estate);
7884

7985
TupleTableSlot*EvalPlanQual(EState*estate,Indexrti,ItemPointertid);
8086
staticTupleTableSlot*EvalPlanQualNext(EState*estate);
@@ -187,13 +193,16 @@ ExecutorStart(QueryDesc *queryDesc, EState *estate)
187193
* ----------------------------------------------------------------
188194
*/
189195
TupleTableSlot*
190-
ExecutorRun(QueryDesc*queryDesc,EState*estate,intfeature,intcount)
196+
ExecutorRun(QueryDesc*queryDesc,EState*estate,intfeature,
197+
Node*limoffset,Node*limcount)
191198
{
192199
CmdTypeoperation;
193200
Plan*plan;
194201
TupleTableSlot*result;
195202
CommandDestdest;
196203
DestReceiver*destfunc;
204+
intoffset=0;
205+
intcount=0;
197206

198207
/******************
199208
*sanity checks
@@ -222,21 +231,113 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
222231
*/
223232
(*destfunc->setup) (destfunc, (TupleDesc)NULL);
224233

234+
/******************
235+
* if given get the offset of the LIMIT clause
236+
******************
237+
*/
238+
if (limoffset!=NULL)
239+
{
240+
Const*coffset;
241+
Param*poffset;
242+
ParamListInfoparamLI;
243+
inti;
244+
245+
switch (nodeTag(limoffset))
246+
{
247+
caseT_Const:
248+
coffset= (Const*)limoffset;
249+
offset= (int)(coffset->constvalue);
250+
break;
251+
252+
caseT_Param:
253+
poffset= (Param*)limoffset;
254+
paramLI=estate->es_param_list_info;
255+
256+
if (paramLI==NULL)
257+
elog(ERROR,"parameter for limit offset not in executor state");
258+
for (i=0;paramLI[i].kind!=PARAM_INVALID;i++)
259+
{
260+
if (paramLI[i].kind==PARAM_NUM&&paramLI[i].id==poffset->paramid)
261+
break;
262+
}
263+
if (paramLI[i].kind==PARAM_INVALID)
264+
elog(ERROR,"parameter for limit offset not in executor state");
265+
if (paramLI[i].isnull)
266+
elog(ERROR,"limit offset cannot be NULL value");
267+
offset= (int)(paramLI[i].value);
268+
269+
break;
270+
271+
default:
272+
elog(ERROR,"unexpected node type %d as limit offset",nodeTag(limoffset));
273+
}
274+
275+
if (offset<0)
276+
elog(ERROR,"limit offset cannot be negative");
277+
}
278+
279+
/******************
280+
* if given get the count of the LIMIT clause
281+
******************
282+
*/
283+
if (limcount!=NULL)
284+
{
285+
Const*ccount;
286+
Param*pcount;
287+
ParamListInfoparamLI;
288+
inti;
289+
290+
switch (nodeTag(limcount))
291+
{
292+
caseT_Const:
293+
ccount= (Const*)limcount;
294+
count= (int)(ccount->constvalue);
295+
break;
296+
297+
caseT_Param:
298+
pcount= (Param*)limcount;
299+
paramLI=estate->es_param_list_info;
300+
301+
if (paramLI==NULL)
302+
elog(ERROR,"parameter for limit count not in executor state");
303+
for (i=0;paramLI[i].kind!=PARAM_INVALID;i++)
304+
{
305+
if (paramLI[i].kind==PARAM_NUM&&paramLI[i].id==pcount->paramid)
306+
break;
307+
}
308+
if (paramLI[i].kind==PARAM_INVALID)
309+
elog(ERROR,"parameter for limit count not in executor state");
310+
if (paramLI[i].isnull)
311+
elog(ERROR,"limit count cannot be NULL value");
312+
count= (int)(paramLI[i].value);
313+
314+
break;
315+
316+
default:
317+
elog(ERROR,"unexpected node type %d as limit count",nodeTag(limcount));
318+
}
319+
320+
if (count<0)
321+
elog(ERROR,"limit count cannot be negative");
322+
}
323+
225324
switch (feature)
226325
{
227326

228327
caseEXEC_RUN:
229328
result=ExecutePlan(estate,
230329
plan,
231330
operation,
232-
ALL_TUPLES,
331+
offset,
332+
count,
233333
ForwardScanDirection,
234334
destfunc);
235335
break;
236336
caseEXEC_FOR:
237337
result=ExecutePlan(estate,
238338
plan,
239339
operation,
340+
offset,
240341
count,
241342
ForwardScanDirection,
242343
destfunc);
@@ -250,6 +351,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
250351
result=ExecutePlan(estate,
251352
plan,
252353
operation,
354+
offset,
253355
count,
254356
BackwardScanDirection,
255357
destfunc);
@@ -264,6 +366,7 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, int count)
264366
result=ExecutePlan(estate,
265367
plan,
266368
operation,
369+
0,
267370
ONE_TUPLE,
268371
ForwardScanDirection,
269372
destfunc);
@@ -784,6 +887,7 @@ static TupleTableSlot *
784887
ExecutePlan(EState*estate,
785888
Plan*plan,
786889
CmdTypeoperation,
890+
intoffsetTuples,
787891
intnumberTuples,
788892
ScanDirectiondirection,
789893
DestReceiver*destfunc)
@@ -845,6 +949,20 @@ lnext:;
845949
break;
846950
}
847951

952+
/******************
953+
* For now we completely execute the plan and skip
954+
* result tuples if requested by LIMIT offset.
955+
* Finally we should try to do it in deeper levels
956+
* if possible (during index scan)
957+
* - Jan
958+
******************
959+
*/
960+
if (offsetTuples>0)
961+
{
962+
--offsetTuples;
963+
continue;
964+
}
965+
848966
/******************
849967
*if we have a junk filter, then project a new
850968
*tuple with the junk removed.

‎src/backend/executor/functions.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.22 1999/02/03 21:16:12 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.23 1999/02/08 14:14:09 wieck Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -130,6 +130,9 @@ init_execution_state(FunctionCachePtr fcache,
130130
None);
131131
estate=CreateExecutorState();
132132

133+
if (queryTree->limitOffset!=NULL||queryTree->limitCount!=NULL)
134+
elog(ERROR,"LIMIT clause from SQL functions not yet implemented");
135+
133136
if (nargs>0)
134137
{
135138
inti;
@@ -199,7 +202,7 @@ postquel_getnext(execution_state *es)
199202

200203
feature= (LAST_POSTQUEL_COMMAND(es)) ?EXEC_RETONE :EXEC_RUN;
201204

202-
returnExecutorRun(es->qd,es->estate,feature,0);
205+
returnExecutorRun(es->qd,es->estate,feature,(Node*)NULL, (Node*)NULL);
203206
}
204207

205208
staticvoid

‎src/backend/executor/spi.c

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* spi.c--
44
*Server Programming Interface
55
*
6-
* $Id: spi.c,v 1.32 1999/01/27 16:15:20 wieck Exp $
6+
* $Id: spi.c,v 1.33 1999/02/08 14:14:10 wieck Exp $
77
*
88
*-------------------------------------------------------------------------
99
*/
@@ -779,6 +779,8 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
779779
boolisRetrieveIntoRelation= false;
780780
char*intoName=NULL;
781781
intres;
782+
Consttcount_const;
783+
Node*count=NULL;
782784

783785
switch (operation)
784786
{
@@ -813,6 +815,39 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
813815
returnSPI_ERROR_OPUNKNOWN;
814816
}
815817

818+
/* ----------------
819+
* Get the query LIMIT tuple count
820+
* ----------------
821+
*/
822+
if (parseTree->limitCount!=NULL)
823+
{
824+
/* ----------------
825+
* A limit clause in the parsetree overrides the
826+
* tcount parameter
827+
* ----------------
828+
*/
829+
count=parseTree->limitCount;
830+
}
831+
else
832+
{
833+
/* ----------------
834+
* No LIMIT clause in parsetree. Use a local Const node
835+
* to put tcount into it
836+
* ----------------
837+
*/
838+
memset(&tcount_const,0,sizeof(tcount_const));
839+
tcount_const.type=T_Const;
840+
tcount_const.consttype=INT4OID;
841+
tcount_const.constlen=sizeof(int4);
842+
tcount_const.constvalue= (Datum)tcount;
843+
tcount_const.constisnull= FALSE;
844+
tcount_const.constbyval= TRUE;
845+
tcount_const.constisset= FALSE;
846+
tcount_const.constiscast= FALSE;
847+
848+
count= (Node*)&tcount_const;
849+
}
850+
816851
if (state==NULL)/* plan preparation */
817852
returnres;
818853
#ifdefSPI_EXECUTOR_STATS
@@ -833,7 +868,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
833868
returnSPI_OK_CURSOR;
834869
}
835870

836-
ExecutorRun(queryDesc,state,EXEC_FOR,tcount);
871+
ExecutorRun(queryDesc,state,EXEC_FOR,parseTree->limitOffset,count);
837872

838873
_SPI_current->processed=state->es_processed;
839874
if (operation==CMD_SELECT&&queryDesc->dest==SPI)

‎src/backend/parser/analyze.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* Copyright (c) 1994, Regents of the University of California
77
*
8-
* $Id: analyze.c,v 1.97 1999/02/02 03:44:32 momjian Exp $
8+
* $Id: analyze.c,v 1.98 1999/02/08 14:14:11 wieck Exp $
99
*
1010
*-------------------------------------------------------------------------
1111
*/
@@ -205,7 +205,11 @@ transformStmt(ParseState *pstate, Node *parseTree)
205205

206206
caseT_SelectStmt:
207207
if (!((SelectStmt*)parseTree)->portalname)
208+
{
208209
result=transformSelectStmt(pstate, (SelectStmt*)parseTree);
210+
result->limitOffset= ((SelectStmt*)parseTree)->limitOffset;
211+
result->limitCount= ((SelectStmt*)parseTree)->limitCount;
212+
}
209213
else
210214
result=transformCursorStmt(pstate, (SelectStmt*)parseTree);
211215
break;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp