]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Limit occurs after DISTINCT. Ticket #749. (CVS 1824)
authordrh <drh@noemail.net>
Mon, 19 Jul 2004 23:33:02 +0000 (23:33 +0000)
committerdrh <drh@noemail.net>
Mon, 19 Jul 2004 23:33:02 +0000 (23:33 +0000)
FossilOrigin-Name: db5ae13db3edec82dd2ead3b76fc9f89f33b2dc2

manifest
manifest.uuid
src/select.c
test/limit.test

index 35251f5b46e5a875a953e0c09ca708276101fce4..747aba6ebd32a631db6e3b9fc327d102e53f4960 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sfor\sticket\s#813.\s(CVS\s1820)
-D 2004-07-19T19:30:50
+C Limit\soccurs\safter\sDISTINCT.\s\sTicket\s#749.\s(CVS\s1824)
+D 2004-07-19T23:33:03
 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -46,7 +46,7 @@ F src/parse.y 023720cb8c3bef74e51738bca78335d0dc6d2cfd
 F src/pragma.c f9c157b0591419d2d3407dac90222020d2a6d822
 F src/printf.c 378ec63d9303993eef24814a56a9fc7260aacbea
 F src/random.c 775913e0b7fbd6295d21f12a7bd35b46387c44b2
-F src/select.c b8fe5c69d414af1a831593e41439f93e793874dc
+F src/select.c 894bdac9404d1a42097e0c9717b644f762bf9b5e
 F src/shell.c 920af040d3a33ea8919c82cee45b424ad841cee0
 F src/sqlite.h.in 35bec264dfb4965bbfeb7e75221f8658f210c30d
 F src/sqliteInt.h 3e9203f16d12baf3a364fae9d64903d813651abd
@@ -101,7 +101,7 @@ F test/join.test 9ef6aabaac9de51d5fc41e68d1f4355da05a84cd
 F test/join2.test c97e4c5aa65dea462145529e58212a709b4722b8
 F test/lastinsert.test 31382f88b9b0270333ac9e4a17f2c2f4732da718
 F test/laststmtchanges.test cabd11bdfbaf73a4486c50b58297d9c2038ccc18
-F test/limit.test e28ce938ddacefdff860d082be45e1e5e2801441
+F test/limit.test c6365450f3180170c0fa1b0bf1ae48522c33b731
 F test/lock.test 226ef831dad60ad4d200dc83e25479ba952aac7e
 F test/main.test 6a851b5992c4881a725a3d9647e629199df8de9d
 F test/malloc.test 2cfcffb7c858640e01e6520ee1cd54ca57d98e80
@@ -189,7 +189,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
 F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
 F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P 5ba0acd6c788b6ec07b29dc40c17265f8fb8a337
-R 04b738396073cd6e3f5def26476223ed
+P 0cc612f8aa458034d3dc246861c529c57ac5b2b1
+R ac26673074971ea42a1c00adb7738364
 U drh
-Z e025b922d80b327cd770a3f0a861e529
+Z 92f099eb6b982fdc1c22acb201e5fa38
index 2d705777d1c38418d821f08fcd779267ee815386..90db777a2fb06438f3c11755321b121971cc3d14 100644 (file)
@@ -1 +1 @@
-0cc612f8aa458034d3dc246861c529c57ac5b2b1
\ No newline at end of file
+db5ae13db3edec82dd2ead3b76fc9f89f33b2dc2
\ No newline at end of file
index 01cdcf5acf9bd77062fe42e690b5e96fba6cfee7..5e48d714ae830113868c580da83d8700770c42a8 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle SELECT statements in SQLite.
 **
-** $Id: select.c,v 1.161.2.1 2004/07/18 21:14:05 drh Exp $
+** $Id: select.c,v 1.161.2.2 2004/07/19 23:33:03 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -364,6 +364,30 @@ void sqliteAddKeyType(Vdbe *v, ExprList *pEList){
   sqliteVdbeChangeP3(v, -1, zType, P3_DYNAMIC);
 }
 
+/*
+** Add code to implement the OFFSET and LIMIT
+*/
+static void codeLimiter(
+  Vdbe *v,          /* Generate code into this VM */
+  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 */
+){
+  if( p->iOffset>=0 ){
+    int addr = sqliteVdbeCurrentAddr(v) + 2;
+    if( nPop>0 ) addr++;
+    sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr);
+    if( nPop>0 ){
+      sqliteVdbeAddOp(v, OP_Pop, nPop, 0);
+    }
+    sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
+  }
+  if( p->iLimit>=0 ){
+    sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak);
+  }
+}
+
 /*
 ** This routine generates the code for the inside of the inner loop
 ** of a SELECT.
@@ -388,6 +412,7 @@ static int selectInnerLoop(
 ){
   Vdbe *v = pParse->pVdbe;
   int i;
+  int hasDistinct;        /* True if the DISTINCT keyword is present */
 
   if( v==0 ) return 0;
   assert( pEList!=0 );
@@ -395,15 +420,9 @@ static int selectInnerLoop(
   /* If there was a LIMIT clause on the SELECT statement, then do the check
   ** to see if this row should be output.
   */
-  if( pOrderBy==0 ){
-    if( p->iOffset>=0 ){
-      int addr = sqliteVdbeCurrentAddr(v);
-      sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr+2);
-      sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
-    }
-    if( p->iLimit>=0 ){
-      sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak);
-    }
+  hasDistinct = distinct>=0 && pEList && pEList->nExpr>0;
+  if( pOrderBy==0 && !hasDistinct ){
+    codeLimiter(v, p, iContinue, iBreak, 0);
   }
 
   /* Pull the requested columns.
@@ -423,7 +442,7 @@ static int selectInnerLoop(
   ** and this row has been seen before, then do not make this row
   ** part of the result.
   */
-  if( distinct>=0 && pEList && pEList->nExpr>0 ){
+  if( hasDistinct ){
 #if NULL_ALWAYS_DISTINCT
     sqliteVdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqliteVdbeCurrentAddr(v)+7);
 #endif
@@ -434,6 +453,9 @@ static int selectInnerLoop(
     sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
     sqliteVdbeAddOp(v, OP_String, 0, 0);
     sqliteVdbeAddOp(v, OP_PutStrKey, distinct, 0);
+    if( pOrderBy==0 ){
+      codeLimiter(v, p, iContinue, iBreak, nColumn);
+    }
   }
 
   switch( eDest ){
@@ -570,14 +592,7 @@ static void generateSortTail(
   if( eDest==SRT_Sorter ) return;
   sqliteVdbeAddOp(v, OP_Sort, 0, 0);
   addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end1);
-  if( p->iOffset>=0 ){
-    sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr+4);
-    sqliteVdbeAddOp(v, OP_Pop, 1, 0);
-    sqliteVdbeAddOp(v, OP_Goto, 0, addr);
-  }
-  if( p->iLimit>=0 ){
-    sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, end2);
-  }
+  codeLimiter(v, p, addr, end2, 1);
   switch( eDest ){
     case SRT_Callback: {
       sqliteVdbeAddOp(v, OP_SortCallback, nColumn, 0);
index 9f964017b7cadb31b4e56876ad4dc37cf3a7c3e8..9b9592e67966a5aead6f661a1ad882b8e266dcf7 100644 (file)
@@ -12,7 +12,7 @@
 # focus of this file is testing the LIMIT ... OFFSET ... clause
 #  of SELECT statements.
 #
-# $Id: limit.test,v 1.11 2004/03/08 13:26:18 drh Exp $
+# $Id: limit.test,v 1.11.2.1 2004/07/19 23:33:04 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -294,4 +294,24 @@ do_test limit-7.12 {
   }
 } {30}
 
+# Tests for limit in conjunction with distinct.  The distinct should
+# occur before both the limit and the offset.  Ticket #749.
+#
+do_test limit-8.1 {
+  execsql {
+    SELECT DISTINCT round(x/100) FROM t3 LIMIT 5;
+  }
+} {0 1 2 3 4}
+do_test limit-8.2 {
+  execsql {
+    SELECT DISTINCT round(x/100) FROM t3 LIMIT 5 OFFSET 5;
+  }
+} {5 6 7 8 9}
+do_test limit-8.3 {
+  execsql {
+    SELECT DISTINCT round(x/100) FROM t3 LIMIT 5 OFFSET 25;
+  }
+} {25 26 27 28 29}
+
+
 finish_test