mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-05 15:55:57 +03:00
LIMIT occurs after DISTINCT. Ticket #749. (CVS 1823)
FossilOrigin-Name: e6bc8aa80824a9156e78fc99b5ac7045b97d29c3
This commit is contained in:
16
manifest
16
manifest
@@ -1,5 +1,5 @@
|
|||||||
C more\suses\sof\ssqlite3.pc\s(CVS\s1822)
|
C LIMIT\soccurs\safter\sDISTINCT.\s\sTicket\s#749.\s(CVS\s1823)
|
||||||
D 2004-07-19T22:28:43
|
D 2004-07-19T23:16:39
|
||||||
F Makefile.in 4a5e570a9e2d35b09c31b3cf01b78cea764ade4b
|
F Makefile.in 4a5e570a9e2d35b09c31b3cf01b78cea764ade4b
|
||||||
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
|
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
|
||||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||||
@@ -57,7 +57,7 @@ F src/parse.y 51c8e696276c409618e66a4ccf316fcff245506e
|
|||||||
F src/pragma.c 8326df8c400f573eb43004dfb8e53e5102acb3e4
|
F src/pragma.c 8326df8c400f573eb43004dfb8e53e5102acb3e4
|
||||||
F src/printf.c 36090f6d7b4946539de97c1850675ce55ef66c16
|
F src/printf.c 36090f6d7b4946539de97c1850675ce55ef66c16
|
||||||
F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
|
F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
|
||||||
F src/select.c 6f0bbf8da5b68f9afeb6f51a28ff7526a2f37238
|
F src/select.c d4585c55c460dad2019964e5d0ae18f9b91cd142
|
||||||
F src/shell.c ebec5da57ea401f4886eefc790917b939d94d595
|
F src/shell.c ebec5da57ea401f4886eefc790917b939d94d595
|
||||||
F src/sqlite.h.in aaf46c8d458efd8aca694ec4f18c6ecf616ee55e
|
F src/sqlite.h.in aaf46c8d458efd8aca694ec4f18c6ecf616ee55e
|
||||||
F src/sqliteInt.h aeae6793d1db335ec1179ad9f26b0affc0ec658a
|
F src/sqliteInt.h aeae6793d1db335ec1179ad9f26b0affc0ec658a
|
||||||
@@ -129,7 +129,7 @@ F test/join3.test 8d989e52413199065bd630b3d0a6b2329d173099
|
|||||||
F test/join4.test 8dec387d06b3a4685e1104048065cf5236b99b93
|
F test/join4.test 8dec387d06b3a4685e1104048065cf5236b99b93
|
||||||
F test/lastinsert.test 31382f88b9b0270333ac9e4a17f2c2f4732da718
|
F test/lastinsert.test 31382f88b9b0270333ac9e4a17f2c2f4732da718
|
||||||
F test/laststmtchanges.test 417aa27eb2b5cdfafb46e390e2c9ddd0a20eba43
|
F test/laststmtchanges.test 417aa27eb2b5cdfafb46e390e2c9ddd0a20eba43
|
||||||
F test/limit.test 60d7f856ee7846f7130dee67f10f0e726cd70b5d
|
F test/limit.test 404a540e3fede22cab5667e12d7e3788617b07dc
|
||||||
F test/lock.test 1dbf1d06b0a7eb36237b4f107cfb3da9726b449e
|
F test/lock.test 1dbf1d06b0a7eb36237b4f107cfb3da9726b449e
|
||||||
F test/lock2.test 4108cabaa108a142e5eed83de3b13b6e579c12cf
|
F test/lock2.test 4108cabaa108a142e5eed83de3b13b6e579c12cf
|
||||||
F test/main.test e8c4d9ca6d1e5f5e55e6550d31aec488883b2ed9
|
F test/main.test e8c4d9ca6d1e5f5e55e6550d31aec488883b2ed9
|
||||||
@@ -237,7 +237,7 @@ F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075
|
|||||||
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
|
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
|
||||||
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
|
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
|
||||||
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
||||||
P 511ee6392472d250b542961d1f715cc7453598e6
|
P a0f107ca66f825cc1fd10b15157b22fd9cc0f95c
|
||||||
R a1278fd30ec90b30144977a9a291265d
|
R 2a77d36b9d379fa39cee995a7b6ac780
|
||||||
U dougcurrie
|
U drh
|
||||||
Z 2a946161d6ace42bcae6f510d88d5b18
|
Z ebf8b5ec73a9dc2627883459f07e7b7c
|
||||||
|
@@ -1 +1 @@
|
|||||||
a0f107ca66f825cc1fd10b15157b22fd9cc0f95c
|
e6bc8aa80824a9156e78fc99b5ac7045b97d29c3
|
54
src/select.c
54
src/select.c
@@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** to handle SELECT statements in SQLite.
|
** to handle SELECT statements in SQLite.
|
||||||
**
|
**
|
||||||
** $Id: select.c,v 1.197 2004/07/18 21:33:02 drh Exp $
|
** $Id: select.c,v 1.198 2004/07/19 23:16:39 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -320,6 +320,31 @@ static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){
|
|||||||
sqlite3VdbeAddOp(v, OP_SortPut, 0, 0);
|
sqlite3VdbeAddOp(v, OP_SortPut, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Add code to implement the OFFSET and LIMIT
|
||||||
|
*/
|
||||||
|
static void codeLimiter(
|
||||||
|
Parse *pParse, /* Parsing context */
|
||||||
|
Select *p, /* The SELECT statement being coded */
|
||||||
|
int iContinue, /* Jump here to skip the current record */
|
||||||
|
int iBreak, /* Jump here to end the loop */
|
||||||
|
int nPop /* Number of times to pop stack when jumping */
|
||||||
|
){
|
||||||
|
Vdbe *v = pParse->pVdbe;
|
||||||
|
if( p->iOffset>=0 ){
|
||||||
|
int addr = sqlite3VdbeCurrentAddr(v) + 2;
|
||||||
|
if( nPop>0 ) addr++;
|
||||||
|
sqlite3VdbeAddOp(v, OP_MemIncr, p->iOffset, addr);
|
||||||
|
if( nPop>0 ){
|
||||||
|
sqlite3VdbeAddOp(v, OP_Pop, nPop, 0);
|
||||||
|
}
|
||||||
|
sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue);
|
||||||
|
}
|
||||||
|
if( p->iLimit>=0 ){
|
||||||
|
sqlite3VdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This routine generates the code for the inside of the inner loop
|
** This routine generates the code for the inside of the inner loop
|
||||||
** of a SELECT.
|
** of a SELECT.
|
||||||
@@ -345,6 +370,7 @@ static int selectInnerLoop(
|
|||||||
){
|
){
|
||||||
Vdbe *v = pParse->pVdbe;
|
Vdbe *v = pParse->pVdbe;
|
||||||
int i;
|
int i;
|
||||||
|
int hasDistinct; /* True if the DISTINCT keyword is present */
|
||||||
|
|
||||||
if( v==0 ) return 0;
|
if( v==0 ) return 0;
|
||||||
assert( pEList!=0 );
|
assert( pEList!=0 );
|
||||||
@@ -352,15 +378,9 @@ static int selectInnerLoop(
|
|||||||
/* If there was a LIMIT clause on the SELECT statement, then do the check
|
/* If there was a LIMIT clause on the SELECT statement, then do the check
|
||||||
** to see if this row should be output.
|
** to see if this row should be output.
|
||||||
*/
|
*/
|
||||||
if( pOrderBy==0 ){
|
hasDistinct = distinct>=0 && pEList && pEList->nExpr>0;
|
||||||
if( p->iOffset>=0 ){
|
if( pOrderBy==0 && !hasDistinct ){
|
||||||
int addr = sqlite3VdbeCurrentAddr(v);
|
codeLimiter(pParse, p, iContinue, iBreak, 0);
|
||||||
sqlite3VdbeAddOp(v, OP_MemIncr, p->iOffset, addr+2);
|
|
||||||
sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue);
|
|
||||||
}
|
|
||||||
if( p->iLimit>=0 ){
|
|
||||||
sqlite3VdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pull the requested columns.
|
/* Pull the requested columns.
|
||||||
@@ -380,7 +400,7 @@ static int selectInnerLoop(
|
|||||||
** and this row has been seen before, then do not make this row
|
** and this row has been seen before, then do not make this row
|
||||||
** part of the result.
|
** part of the result.
|
||||||
*/
|
*/
|
||||||
if( distinct>=0 && pEList && pEList->nExpr>0 ){
|
if( hasDistinct ){
|
||||||
#if NULL_ALWAYS_DISTINCT
|
#if NULL_ALWAYS_DISTINCT
|
||||||
sqlite3VdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqlite3VdbeCurrentAddr(v)+7);
|
sqlite3VdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqlite3VdbeCurrentAddr(v)+7);
|
||||||
#endif
|
#endif
|
||||||
@@ -392,6 +412,9 @@ static int selectInnerLoop(
|
|||||||
sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue);
|
sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue);
|
||||||
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
|
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
|
||||||
sqlite3VdbeAddOp(v, OP_PutStrKey, distinct, 0);
|
sqlite3VdbeAddOp(v, OP_PutStrKey, distinct, 0);
|
||||||
|
if( pOrderBy==0 ){
|
||||||
|
codeLimiter(pParse, p, iContinue, iBreak, nColumn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch( eDest ){
|
switch( eDest ){
|
||||||
@@ -559,14 +582,7 @@ static void generateSortTail(
|
|||||||
}
|
}
|
||||||
sqlite3VdbeOp3(v, OP_Sort, 0, 0, (char*)pInfo, P3_KEYINFO_HANDOFF);
|
sqlite3VdbeOp3(v, OP_Sort, 0, 0, (char*)pInfo, P3_KEYINFO_HANDOFF);
|
||||||
addr = sqlite3VdbeAddOp(v, OP_SortNext, 0, end1);
|
addr = sqlite3VdbeAddOp(v, OP_SortNext, 0, end1);
|
||||||
if( p->iOffset>=0 ){
|
codeLimiter(pParse, p, addr, end2, 1);
|
||||||
sqlite3VdbeAddOp(v, OP_MemIncr, p->iOffset, addr+4);
|
|
||||||
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
|
|
||||||
sqlite3VdbeAddOp(v, OP_Goto, 0, addr);
|
|
||||||
}
|
|
||||||
if( p->iLimit>=0 ){
|
|
||||||
sqlite3VdbeAddOp(v, OP_MemIncr, p->iLimit, end2);
|
|
||||||
}
|
|
||||||
switch( eDest ){
|
switch( eDest ){
|
||||||
case SRT_Table:
|
case SRT_Table:
|
||||||
case SRT_TempTable: {
|
case SRT_TempTable: {
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
# focus of this file is testing the LIMIT ... OFFSET ... clause
|
# focus of this file is testing the LIMIT ... OFFSET ... clause
|
||||||
# of SELECT statements.
|
# of SELECT statements.
|
||||||
#
|
#
|
||||||
# $Id: limit.test,v 1.13 2004/05/27 17:22:56 drh Exp $
|
# $Id: limit.test,v 1.14 2004/07/19 23:16:39 drh Exp $
|
||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
@@ -295,4 +295,17 @@ do_test limit-7.12 {
|
|||||||
}
|
}
|
||||||
} {30}
|
} {30}
|
||||||
|
|
||||||
|
# Tests for limit in conjunction with distinct
|
||||||
|
#
|
||||||
|
do_test limit-8.1 {
|
||||||
|
execsql {
|
||||||
|
SELECT DISTINCT x/100 FROM t3 LIMIT 5;
|
||||||
|
}
|
||||||
|
} {0 1 2 3 4}
|
||||||
|
do_test limit-8.2 {
|
||||||
|
execsql {
|
||||||
|
SELECT DISTINCT x/100 FROM t3 LIMIT 5 OFFSET 5;
|
||||||
|
}
|
||||||
|
} {5 6 7 8 9}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
Reference in New Issue
Block a user