]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
When the [https://www.sqlite.org/queryplanner.html#partialsort|block sorting optimiza...
authordrh <drh@noemail.net>
Wed, 13 Jan 2016 17:59:28 +0000 (17:59 +0000)
committerdrh <drh@noemail.net>
Wed, 13 Jan 2016 17:59:28 +0000 (17:59 +0000)
is used in a scalar subquery, be sure to exit the loop as soon as the first
valid output row is received.  Fix for ticket [cb3aa0641d9a4].

FossilOrigin-Name: 8b4f5080621a8c23d9d32bf578bb83edc43de5c3

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

index 84ab4c9e57b033400d0dcba7281a9a79e162e910..853503a0c07db3a2b4eb15d467f9c07b44c3ea0c 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Version\s3.10.0
-D 2016-01-06T11:01:07.739
+C When\sthe\s[https://www.sqlite.org/queryplanner.html#partialsort|block\ssorting\soptimization]\nis\sused\sin\sa\sscalar\ssubquery,\sbe\ssure\sto\sexit\sthe\sloop\sas\ssoon\sas\sthe\sfirst\nvalid\soutput\srow\sis\sreceived.\s\sFix\sfor\sticket\s[cb3aa0641d9a4].
+D 2016-01-13T17:59:28.834
 F Makefile.in 7c8cc4c2f0179efc6fa9492141d1fb65f4807054
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc e45d8b9b56dfa3f2cd860b2c28bd9d304513b042
@@ -333,7 +333,7 @@ F src/printf.c af589a27b7d40f6f4f704e9eea99f02f18ad6d32
 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
 F src/resolve.c a83b41104e6ff69855d03cd0aaa09e93927ec39f
 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
-F src/select.c f8fded11fc443a9f5a73cc5db069d06b34460e2f
+F src/select.c 47cd4189c47d937478dae4fc8ec4bceb4ecebf11
 F src/shell.c ed71dc7679e6f087a3f1ea3f9dae4b0fae7209c3
 F src/sqlite.h.in 7d87d71b9a4689c51fa092f48f16590ff71558e3
 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
@@ -903,7 +903,7 @@ F test/numcast.test 5d126f7f581432e86a90d1e35cac625164aec4a1
 F test/numindex1.test 20a5450d4b056e48cd5db30e659f13347a099823
 F test/offset1.test f06b83657bcf26f9ce805e67450e189e282143b2
 F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
-F test/orderby1.test 870e150450437d3980badbde3d0166b81d9e33f6
+F test/orderby1.test 4d22a7c75f6a83fc1f188cc7bb5192285fdf2552
 F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
 F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99
 F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4
@@ -1406,10 +1406,11 @@ F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P a855697719e288c908ddb7950d32fd17ef546509
-R 658872c8eaad4f517adfb9642371bf29
-T +bgcolor * #d0c0ff
-T +sym-release *
-T +sym-version-3.10.0 *
+P fd0a50f0797d154fefff724624f00548b5320566
+Q +cdbb0947f9ce18d6d7e29ffab5ea6a2ee5365fbb
+R 2d754bf0dc48cb48804e183af36b6602
+T *branch * branch-3.10
+T *sym-branch-3.10 *
+T -sym-trunk *
 U drh
-Z 024a1b2bbd235a427c0ebcd39a99300a
+Z 6f8b5d3bc045113db8218e754cbb7983
index 01d9768cad85a6d7040e5170b3e9c9b5ccd4e0e4..aa9ed0c4f06e9763860fc7c8e4be6918b3c92557 100644 (file)
@@ -1 +1 @@
-fd0a50f0797d154fefff724624f00548b5320566
\ No newline at end of file
+8b4f5080621a8c23d9d32bf578bb83edc43de5c3
\ No newline at end of file
index f8b8e9e77f7a38dbc69375c2cf112cb657cafbc3..85f8518cf1c38f0cc49dc159a726dfef1a204540 100644 (file)
@@ -54,6 +54,7 @@ struct SortCtx {
   int regReturn;        /* Register holding block-output return address */
   int labelBkOut;       /* Start label for the block-output subroutine */
   int addrSortIndex;    /* Address of the OP_SorterOpen or OP_OpenEphemeral */
+  int labelDone;        /* Jump here when done, ex: LIMIT reached */
   u8 sortFlags;         /* Zero or more SORTFLAG_* bits */
 };
 #define SORTFLAG_UseSorter  0x01   /* Use SorterOpen instead of OpenEphemeral */
@@ -508,6 +509,7 @@ static void pushOntoSorter(
   int regRecord = ++pParse->nMem;                  /* Assembled sorter record */
   int nOBSat = pSort->nOBSat;                      /* ORDER BY terms to skip */
   int op;                            /* Opcode to add sorter record to sorter */
+  int iLimit;                        /* LIMIT counter */
 
   assert( bSeq==0 || bSeq==1 );
   assert( nData==1 || regData==regOrigData );
@@ -518,6 +520,9 @@ static void pushOntoSorter(
     regBase = pParse->nMem + 1;
     pParse->nMem += nBase;
   }
+  assert( pSelect->iOffset==0 || pSelect->iLimit!=0 );
+  iLimit = pSelect->iOffset ? pSelect->iOffset+1 : pSelect->iLimit;
+  pSort->labelDone = sqlite3VdbeMakeLabel(v);
   sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, regOrigData,
                           SQLITE_ECEL_DUP|SQLITE_ECEL_REF);
   if( bSeq ){
@@ -526,7 +531,6 @@ static void pushOntoSorter(
   if( nPrefixReg==0 ){
     sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+bSeq, nData);
   }
-
   sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord);
   if( nOBSat>0 ){
     int regPrevKey;   /* The first nOBSat columns of the previous row */
@@ -561,6 +565,10 @@ static void pushOntoSorter(
     pSort->regReturn = ++pParse->nMem;
     sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
     sqlite3VdbeAddOp1(v, OP_ResetSorter, pSort->iECursor);
+    if( iLimit ){
+      sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, pSort->labelDone);
+      VdbeCoverage(v);
+    }
     sqlite3VdbeJumpHere(v, addrFirst);
     sqlite3ExprCodeMove(pParse, regBase, regPrevKey, pSort->nOBSat);
     sqlite3VdbeJumpHere(v, addrJmp);
@@ -571,14 +579,8 @@ static void pushOntoSorter(
     op = OP_IdxInsert;
   }
   sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord);
-  if( pSelect->iLimit ){
+  if( iLimit ){
     int addr;
-    int iLimit;
-    if( pSelect->iOffset ){
-      iLimit = pSelect->iOffset+1;
-    }else{
-      iLimit = pSelect->iLimit;
-    }
     addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, 1); VdbeCoverage(v);
     sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
     sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor);
@@ -1182,7 +1184,7 @@ static void generateSortTail(
   SelectDest *pDest /* Write the sorted results here */
 ){
   Vdbe *v = pParse->pVdbe;                     /* The prepared statement */
-  int addrBreak = sqlite3VdbeMakeLabel(v);     /* Jump here to exit loop */
+  int addrBreak = pSort->labelDone;            /* Jump here to exit loop */
   int addrContinue = sqlite3VdbeMakeLabel(v);  /* Jump here for next cycle */
   int addr;
   int addrOnce = 0;
@@ -1201,6 +1203,7 @@ static void generateSortTail(
   struct ExprList_item *aOutEx = p->pEList->a;
 #endif
 
+  assert( addrBreak<0 );
   if( pSort->labelBkOut ){
     sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
     sqlite3VdbeGoto(v, addrBreak);
index 3e785c54e4ed79b7128ac944675d93f05ad610dc..831936ae9680997a08a8803bd545355a44e8b144 100644 (file)
@@ -528,4 +528,21 @@ do_test 8.3 {
   set res
 } 5000
 
+#---------------------------------------------------------------------------
+# https://www.sqlite.org/src/tktview/cb3aa0641d9a413841c004293a4fc06cdc122029
+#
+# Adverse interaction between scalar subqueries and the partial-sorting
+# logic.
+#
+do_execsql_test 9.0 {
+  DROP TABLE IF EXISTS t1;
+  CREATE TABLE t1(x INTEGER PRIMARY KEY);
+  INSERT INTO t1 VALUES(1),(2);
+  DROP TABLE IF EXISTS t2;
+  CREATE TABLE t2(y);
+  INSERT INTO t2 VALUES(9),(8),(3),(4);
+  SELECT (SELECT x||y FROM t2, t1 ORDER BY x, y);
+} {13}
+
+
 finish_test