aboutsummaryrefslogtreecommitdiff
path: root/src/select.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2016-01-14 14:48:17 +0000
committerdrh <drh@noemail.net>2016-01-14 14:48:17 +0000
commitcb75bff3f7fe12fd3d5dd94acd2832ef1e0dcb65 (patch)
treeda3eeb2fcab166e7e3b9e23526184dc84e286352 /src/select.c
parent604ce70448d0572477ad25bb3510b1dc3f2ad967 (diff)
parent0ea94db612e0f2348b45dafcedf21d9a8f68c60b (diff)
downloadsqlite-cb75bff3f7fe12fd3d5dd94acd2832ef1e0dcb65.tar.gz
sqlite-cb75bff3f7fe12fd3d5dd94acd2832ef1e0dcb65.zip
Merge the latest fixes and enhancements from trunk.
FossilOrigin-Name: 007e5c6df60f9743ac6914332f59925e4a7a861c
Diffstat (limited to 'src/select.c')
-rw-r--r--src/select.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/src/select.c b/src/select.c
index b1db07d09..fd094d05d 100644
--- a/src/select.c
+++ b/src/select.c
@@ -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 */
@@ -124,6 +125,9 @@ Select *sqlite3SelectNew(
pNew->selFlags = selFlags;
pNew->iLimit = 0;
pNew->iOffset = 0;
+#if SELECTTRACE_ENABLED
+ pNew->zSelName[0] = 0;
+#endif
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->nSelectRow = 0;
@@ -513,6 +517,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 );
@@ -523,6 +528,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 ){
@@ -531,7 +539,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 */
@@ -566,6 +573,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);
@@ -576,14 +587,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);
@@ -1187,7 +1192,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;
@@ -1206,6 +1211,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);