-C Fixup\scomments\son\swctrlFlags\svalue\sdefinitions.
-D 2016-05-19T19:31:30.127
+C In\sa\squery\swith\sboth\sORDER\sBY\sand\sLIMIT,\sif\sthe\sinner\sloop\ssatisfies\sthe\s\nORDER\sBY\sthen\stry\sto\scut\sshort\seach\sinvocation\sof\sthe\sinner\sloop\sonce\sthe\nLIMIT\shas\sbeen\ssatisfied.\s\sThis\scheck-in\sis\sa\spartial\simplementation\sonly.
+D 2016-05-19T22:13:37.318
F Makefile.in f59e0763ff448719fc1bd25513882b0567286317
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 306d73e854b1a92ea06e5d1e637faa5c44de53c7
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
F src/resolve.c cca3aa77b95706df5d635a2141a4d1de60ae6598
F src/rowset.c 49eb91c588a2bab36647368e031dc5b66928149d
-F src/select.c fd4a7ce2937497181063cfedb92058ac89491a5d
+F src/select.c 131eeddfcaf3777c4acd4727bf742b98af8183b5
F src/shell.c 14ff7f660530a52b117d110ba3390b7b2eb719b6
F src/sqlite.h.in 9984129d86243424b765fcb3f147c697bd20bb54
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 98f72cbfe00169c39089115427d06ea05fe4b4a2
-F src/sqliteInt.h 19de316bfce65ff074b379a67b493a446f3cf8ee
+F src/sqliteInt.h 863cf0d421611ccfa30541ee5ffe761c896ffa5b
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
F src/status.c 70912d7be68e9e2dbc4010c93d344af61d4c59ba
F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
F src/wal.c 4db22ed7e77bcf672b1a685d6ddeffba8d5be302
F src/wal.h 2f7c831cf3b071fa548bf2d5cac640846a7ff19c
F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354
-F src/where.c 72fd2e1258625c1aee8e33a529914aea2d487422
-F src/whereInt.h 3b1fc240e322613ba4e9dc857ca9c7c3390acc74
+F src/where.c a7454e62ca13f1ff54892339022f8cb0a8bb3728
+F src/whereInt.h 6e18240be400bef8e4dbafea605251707c5dbf49
F src/wherecode.c e3f18fcda2d7f8218a09dc33cf495dca0efa6e3e
F src/whereexpr.c eacc0e60d029a082b4fc0cc42ea98544add1319e
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P d01305841da94b2d47e32744802f69525bf590df
-R be830660ecf90ba00189952af638cb97
+P 58b516e8c0b00a41bc0364eab267bc2ecb9efeff
+R 766495aa6109f75a3c3b0e829e8d3b47
+T *branch * orderby-limit
+T *sym-orderby-limit *
+T -sym-trunk *
U drh
-Z 54bddff0ee366139e2fb13081e6cf75a
+Z 1f191cc43f073ab10b6b672b5a12f950
-58b516e8c0b00a41bc0364eab267bc2ecb9efeff
\ No newline at end of file
+852d1eda6ecca1171f6ed800b06f5b4854672002
\ No newline at end of file
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 */
+ u8 bOrderedInnerLoop; /* ORDER BY correctly sorts the inner loop */
};
#define SORTFLAG_UseSorter 0x01 /* Use SorterOpen instead of OpenEphemeral */
sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord);
if( iLimit ){
int addr;
+ int r1 = 0;
+ /* Fill the sorter until it contains LIMIT+OFFSET entries. (The iLimit
+ ** register is initialized with value of LIMIT+OFFSET.) After the sorter
+ ** fills up, delete the least entry in the sorter after each insert.
+ ** Thus we never hold more than the LIMIT+OFFSET rows in memory at once */
addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, 1); VdbeCoverage(v);
sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
+ if( pSort->bOrderedInnerLoop ){
+ r1 = ++pParse->nMem;
+ sqlite3VdbeAddOp3(v, OP_Column, pSort->iECursor, nExpr, r1);
+ VdbeComment((v, "seq"));
+ }
sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor);
+ if( pSort->bOrderedInnerLoop ){
+ /* If the inner loop is driven by an index such that values from
+ ** the same iteration of the inner loop are in sorted order, then
+ ** immediately jump to the next iteration of an inner loop if the
+ ** entry from the current iteration does not fit into the top
+ ** LIMIT+OFFSET entries of the sorter. */
+ int iBrk = sqlite3VdbeCurrentAddr(v) + 2;
+ sqlite3VdbeAddOp3(v, OP_Eq, regBase+nExpr, iBrk, r1);
+ VdbeCoverage(v);
+ }
sqlite3VdbeJumpHere(v, addr);
}
}
}
if( sSort.pOrderBy ){
sSort.nOBSat = sqlite3WhereIsOrdered(pWInfo);
+ sSort.bOrderedInnerLoop = sqlite3WhereOrderedInnerLoop(pWInfo);
if( sSort.nOBSat==sSort.pOrderBy->nExpr ){
sSort.pOrderBy = 0;
}
LogEst sqlite3WhereOutputRowCount(WhereInfo*);
int sqlite3WhereIsDistinct(WhereInfo*);
int sqlite3WhereIsOrdered(WhereInfo*);
+int sqlite3WhereOrderedInnerLoop(WhereInfo*);
int sqlite3WhereIsSorted(WhereInfo*);
int sqlite3WhereContinueLabel(WhereInfo*);
int sqlite3WhereBreakLabel(WhereInfo*);
return pWInfo->nOBSat;
}
+/*
+** Return TRUE if the innermost loop of the WHERE clause implementation
+** returns rows in ORDER BY order for complete run of the inner loop.
+**
+** Across multiple iterations of outer loops, the output rows need not be
+** sorted. As long as rows are sorted for just the innermost loop, this
+** routine can return TRUE.
+*/
+int sqlite3WhereOrderedInnerLoop(WhereInfo *pWInfo){
+ return pWInfo->bOrderedInnerLoop;
+}
+
/*
** Return the VDBE address or label to jump to in order to continue
** immediately with the next row of a WHERE clause.
}
}else{
pWInfo->nOBSat = pFrom->isOrdered;
- if( pWInfo->nOBSat<0 ) pWInfo->nOBSat = 0;
pWInfo->revMask = pFrom->revLoop;
+ if( pWInfo->nOBSat<=0 ){
+ pWInfo->nOBSat = 0;
+ }
}
if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)
&& pWInfo->nOBSat==pWInfo->pOrderBy->nExpr && nLoop>0
u8 sorted; /* True if really sorted (not just grouped) */
u8 eOnePass; /* ONEPASS_OFF, or _SINGLE, or _MULTI */
u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
- u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
+ u8 eDistinct; /* One of the WHERE_DISTINCT_* values */
u8 nLevel; /* Number of nested loop */
+ u8 bOrderedInnerLoop; /* True if only the inner-most loop is ordered */
int iTop; /* The very beginning of the WHERE loop */
int iContinue; /* Jump here to continue with next record */
int iBreak; /* Jump here to break out of the loop */