Simplifications to the VDBE bytecode that handles LIMIT and OFFSET.
FossilOrigin-Name: 041df7c2f14b95868a08090354ebb3308050790e
This commit is contained in:
parent
a2507137f3
commit
8b0cf38a12
18
manifest
18
manifest
@ -1,5 +1,5 @@
|
|||||||
C Optimizations\sfor\sfts5\sexpressions\sthat\sfilter\son\scolumn.\sMore\sstill\sto\scome.
|
C Simplifications\sto\sthe\sVDBE\sbytecode\sthat\shandles\sLIMIT\sand\sOFFSET.
|
||||||
D 2015-10-06T20:53:26.753
|
D 2015-10-06T21:07:06.319
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412
|
F Makefile.in 2143eeef6d0cc26006ae5fc4bb242a4a8b973412
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@ -335,14 +335,14 @@ F src/parse.y f599aa5e871a493330d567ced93de696f61f48f7
|
|||||||
F src/pcache.c 24be750c79272e0ca7b6e007bc94999700f3e5ef
|
F src/pcache.c 24be750c79272e0ca7b6e007bc94999700f3e5ef
|
||||||
F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9
|
F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9
|
||||||
F src/pcache1.c e822007159d53a7ea7aa040d6e28964ddb6de083
|
F src/pcache1.c e822007159d53a7ea7aa040d6e28964ddb6de083
|
||||||
F src/pragma.c 234814978bcd35bce6e2874dfb2f5b5e28e7fb38
|
F src/pragma.c dcfe3a35d2de935feeaba1455528b4a5c4f1208c
|
||||||
F src/pragma.h 631a91c8b0e6ca8f051a1d8a4a0da4150e04620a
|
F src/pragma.h 631a91c8b0e6ca8f051a1d8a4a0da4150e04620a
|
||||||
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
|
F src/prepare.c 82e5db1013846a819f198336fed72c44c974e7b1
|
||||||
F src/printf.c 0c4bcdd1c2e2521024f0a69cb5eb334f86b3652a
|
F src/printf.c 0c4bcdd1c2e2521024f0a69cb5eb334f86b3652a
|
||||||
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
||||||
F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91
|
F src/resolve.c 1954a0f01bf65d78d7d559aea3d5c67f33376d91
|
||||||
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e
|
||||||
F src/select.c 8fb8cb0230aed9b12b3582ddc366ffbc549041d7
|
F src/select.c 2c4bfdf7c797df9b43121ed7850bf939b6f27405
|
||||||
F src/shell.c dfd18e56fcb88dd79378774e9bc3246a9bd52243
|
F src/shell.c dfd18e56fcb88dd79378774e9bc3246a9bd52243
|
||||||
F src/sqlite.h.in 4b76d74d69af48c534c58fb723137dc6944bdedc
|
F src/sqlite.h.in 4b76d74d69af48c534c58fb723137dc6944bdedc
|
||||||
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
|
||||||
@ -405,7 +405,7 @@ F src/update.c a134027f59c7eb6e63ed18e2d5dd8ef0ce7f8ff8
|
|||||||
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
|
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
|
||||||
F src/util.c fc612367108b74573c5fd13a85d0a23027f438bd
|
F src/util.c fc612367108b74573c5fd13a85d0a23027f438bd
|
||||||
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
|
F src/vacuum.c 2ddd5cad2a7b9cef7f9e431b8c7771634c6b1701
|
||||||
F src/vdbe.c 5048103aa6bc9c01bf1a4620729256d1e873bb6c
|
F src/vdbe.c d263ec6b29d8e8e8178235b8403a00ccb48748d0
|
||||||
F src/vdbe.h 4bc88bd0e06f8046ee6ab7487c0015e85ad949ad
|
F src/vdbe.h 4bc88bd0e06f8046ee6ab7487c0015e85ad949ad
|
||||||
F src/vdbeInt.h 8b867eac234e28627ffcace3cd4b4b79bbec664b
|
F src/vdbeInt.h 8b867eac234e28627ffcace3cd4b4b79bbec664b
|
||||||
F src/vdbeapi.c 020681b943e77766b32ae1cddf86d7831b7374ca
|
F src/vdbeapi.c 020681b943e77766b32ae1cddf86d7831b7374ca
|
||||||
@ -1392,7 +1392,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
|
F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b
|
||||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||||
P 4b631364354068af95a01630469cb6fbfe8b52fd
|
P bf1607ac155018573ca40fb58aca62c5fea7e60b
|
||||||
R 8d25a208807a117d422df371476abd9e
|
R f75f4370adf88bb173a9ed2d414ba858
|
||||||
U dan
|
U drh
|
||||||
Z f7ba9c7b6fd75653c93e200489a4e473
|
Z 3f5b7bfbaf5afcf9be7e111589aea155
|
||||||
|
@ -1 +1 @@
|
|||||||
bf1607ac155018573ca40fb58aca62c5fea7e60b
|
041df7c2f14b95868a08090354ebb3308050790e
|
11
src/pragma.c
11
src/pragma.c
@ -1361,8 +1361,9 @@ void sqlite3Pragma(
|
|||||||
*/
|
*/
|
||||||
static const int iLn = VDBE_OFFSET_LINENO(2);
|
static const int iLn = VDBE_OFFSET_LINENO(2);
|
||||||
static const VdbeOpList endCode[] = {
|
static const VdbeOpList endCode[] = {
|
||||||
{ OP_IfNeg, 1, 0, 0}, /* 0 */
|
{ OP_AddImm, 1, 0, 0}, /* 0 */
|
||||||
{ OP_String8, 0, 3, 0}, /* 1 */
|
{ OP_If, 1, 0, 0}, /* 1 */
|
||||||
|
{ OP_String8, 0, 3, 0}, /* 2 */
|
||||||
{ OP_ResultRow, 3, 1, 0},
|
{ OP_ResultRow, 3, 1, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1563,9 +1564,9 @@ void sqlite3Pragma(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
|
addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
|
||||||
sqlite3VdbeChangeP3(v, addr, -mxErr);
|
sqlite3VdbeChangeP2(v, addr, -mxErr);
|
||||||
sqlite3VdbeJumpHere(v, addr);
|
sqlite3VdbeJumpHere(v, addr+1);
|
||||||
sqlite3VdbeChangeP4(v, addr+1, "ok", P4_STATIC);
|
sqlite3VdbeChangeP4(v, addr+2, "ok", P4_STATIC);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
|
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
|
||||||
|
28
src/select.c
28
src/select.c
@ -579,7 +579,7 @@ static void pushOntoSorter(
|
|||||||
}else{
|
}else{
|
||||||
iLimit = pSelect->iLimit;
|
iLimit = pSelect->iLimit;
|
||||||
}
|
}
|
||||||
addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, -1); VdbeCoverage(v);
|
addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, 1); VdbeCoverage(v);
|
||||||
sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
|
sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
|
||||||
sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor);
|
sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor);
|
||||||
sqlite3VdbeJumpHere(v, addr);
|
sqlite3VdbeJumpHere(v, addr);
|
||||||
@ -595,11 +595,8 @@ static void codeOffset(
|
|||||||
int iContinue /* Jump here to skip the current record */
|
int iContinue /* Jump here to skip the current record */
|
||||||
){
|
){
|
||||||
if( iOffset>0 ){
|
if( iOffset>0 ){
|
||||||
int addr;
|
sqlite3VdbeAddOp3(v, OP_IfPos, iOffset, iContinue, 1); VdbeCoverage(v);
|
||||||
addr = sqlite3VdbeAddOp3(v, OP_IfNeg, iOffset, 0, -1); VdbeCoverage(v);
|
VdbeComment((v, "OFFSET"));
|
||||||
sqlite3VdbeGoto(v, iContinue);
|
|
||||||
VdbeComment((v, "skip OFFSET records"));
|
|
||||||
sqlite3VdbeJumpHere(v, addr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1815,7 +1812,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
|
|||||||
Vdbe *v = 0;
|
Vdbe *v = 0;
|
||||||
int iLimit = 0;
|
int iLimit = 0;
|
||||||
int iOffset;
|
int iOffset;
|
||||||
int addr1, n;
|
int n;
|
||||||
if( p->iLimit ) return;
|
if( p->iLimit ) return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1850,14 +1847,10 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
|
|||||||
sqlite3ExprCode(pParse, p->pOffset, iOffset);
|
sqlite3ExprCode(pParse, p->pOffset, iOffset);
|
||||||
sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v);
|
sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset); VdbeCoverage(v);
|
||||||
VdbeComment((v, "OFFSET counter"));
|
VdbeComment((v, "OFFSET counter"));
|
||||||
addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset); VdbeCoverage(v);
|
sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iOffset, iOffset, 0);
|
||||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset);
|
|
||||||
sqlite3VdbeJumpHere(v, addr1);
|
|
||||||
sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1);
|
sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1);
|
||||||
VdbeComment((v, "LIMIT+OFFSET"));
|
VdbeComment((v, "LIMIT+OFFSET"));
|
||||||
addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit); VdbeCoverage(v);
|
sqlite3VdbeAddOp3(v, OP_SetIfNotPos, iLimit, iOffset+1, -1);
|
||||||
sqlite3VdbeAddOp2(v, OP_Integer, -1, iOffset+1);
|
|
||||||
sqlite3VdbeJumpHere(v, addr1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2274,14 +2267,9 @@ static int multiSelect(
|
|||||||
addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
|
addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
|
||||||
VdbeComment((v, "Jump ahead if LIMIT reached"));
|
VdbeComment((v, "Jump ahead if LIMIT reached"));
|
||||||
if( p->iOffset ){
|
if( p->iOffset ){
|
||||||
int addr2;
|
sqlite3VdbeAddOp3(v, OP_SetIfNotPos, p->iOffset, p->iOffset, 0);
|
||||||
sqlite3VdbeAddOp3(v, OP_Add, p->iLimit, p->iOffset, p->iOffset+1);
|
sqlite3VdbeAddOp3(v, OP_Add, p->iLimit, p->iOffset, p->iOffset+1);
|
||||||
addr2 = sqlite3VdbeAddOp1(v, OP_IfPos, p->iOffset); VdbeCoverage(v);
|
sqlite3VdbeAddOp3(v, OP_SetIfNotPos, p->iLimit, p->iOffset+1, -1);
|
||||||
sqlite3VdbeAddOp2(v, OP_SCopy, p->iLimit, p->iOffset+1);
|
|
||||||
sqlite3VdbeJumpHere(v, addr2);
|
|
||||||
addr2 = sqlite3VdbeAddOp1(v, OP_IfPos, p->iLimit); VdbeCoverage(v);
|
|
||||||
sqlite3VdbeAddOp2(v, OP_Integer, -1, p->iOffset+1);
|
|
||||||
sqlite3VdbeJumpHere(v, addr2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
explainSetInteger(iSub2, pParse->iNextSelectId);
|
explainSetInteger(iSub2, pParse->iNextSelectId);
|
||||||
|
40
src/vdbe.c
40
src/vdbe.c
@ -5671,12 +5671,12 @@ case OP_MemMax: { /* in2 */
|
|||||||
}
|
}
|
||||||
#endif /* SQLITE_OMIT_AUTOINCREMENT */
|
#endif /* SQLITE_OMIT_AUTOINCREMENT */
|
||||||
|
|
||||||
/* Opcode: IfPos P1 P2 * * *
|
/* Opcode: IfPos P1 P2 P3 * *
|
||||||
** Synopsis: if r[P1]>0 goto P2
|
** Synopsis: if r[P1]>0 then r[P1]-=P3, goto P2
|
||||||
**
|
**
|
||||||
** Register P1 must contain an integer.
|
** Register P1 must contain an integer.
|
||||||
** If the value of register P1 is 1 or greater, jump to P2 and
|
** If the value of register P1 is 1 or greater, subtrace P3 from the
|
||||||
** add the literal value P3 to register P1.
|
** value in P1 and jump to P2.
|
||||||
**
|
**
|
||||||
** If the initial value of register P1 is less than 1, then the
|
** If the initial value of register P1 is less than 1, then the
|
||||||
** value is unchanged and control passes through to the next instruction.
|
** value is unchanged and control passes through to the next instruction.
|
||||||
@ -5685,38 +5685,44 @@ case OP_IfPos: { /* jump, in1 */
|
|||||||
pIn1 = &aMem[pOp->p1];
|
pIn1 = &aMem[pOp->p1];
|
||||||
assert( pIn1->flags&MEM_Int );
|
assert( pIn1->flags&MEM_Int );
|
||||||
VdbeBranchTaken( pIn1->u.i>0, 2);
|
VdbeBranchTaken( pIn1->u.i>0, 2);
|
||||||
if( pIn1->u.i>0 ) goto jump_to_p2;
|
if( pIn1->u.i>0 ){
|
||||||
|
pIn1->u.i -= pOp->p3;
|
||||||
|
goto jump_to_p2;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Opcode: IfNeg P1 P2 P3 * *
|
/* Opcode: SetIfNotPos P1 P2 P3 * *
|
||||||
** Synopsis: r[P1]+=P3, if r[P1]<0 goto P2
|
** Synopsis: if r[P1]<=0 then r[P2]=P3
|
||||||
**
|
**
|
||||||
** Register P1 must contain an integer. Add literal P3 to the value in
|
** Register P1 must contain an integer.
|
||||||
** register P1 then if the value of register P1 is less than zero, jump to P2.
|
** If the value of register P1 is not positive (if it is less than 1) then
|
||||||
|
** set the value of register P2 to be the integer P3.
|
||||||
*/
|
*/
|
||||||
case OP_IfNeg: { /* jump, in1 */
|
case OP_SetIfNotPos: { /* in1, in2 */
|
||||||
pIn1 = &aMem[pOp->p1];
|
pIn1 = &aMem[pOp->p1];
|
||||||
assert( pIn1->flags&MEM_Int );
|
assert( pIn1->flags&MEM_Int );
|
||||||
pIn1->u.i += pOp->p3;
|
if( pIn1->u.i<=0 ){
|
||||||
VdbeBranchTaken(pIn1->u.i<0, 2);
|
pOut = out2Prerelease(p, pOp);
|
||||||
if( pIn1->u.i<0 ) goto jump_to_p2;
|
pOut->u.i = pOp->p3;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Opcode: IfNotZero P1 P2 P3 * *
|
/* Opcode: IfNotZero P1 P2 P3 * *
|
||||||
** Synopsis: if r[P1]!=0 then r[P1]+=P3, goto P2
|
** Synopsis: if r[P1]!=0 then r[P1]-=P3, goto P2
|
||||||
**
|
**
|
||||||
** Register P1 must contain an integer. If the content of register P1 is
|
** Register P1 must contain an integer. If the content of register P1 is
|
||||||
** initially nonzero, then add P3 to P1 and jump to P2. If register P1 is
|
** initially nonzero, then subtrace P3 from the value in register P1 and
|
||||||
** initially zero, leave it unchanged and fall through.
|
** jump to P2. If register P1 is initially zero, leave it unchanged
|
||||||
|
** and fall through.
|
||||||
*/
|
*/
|
||||||
case OP_IfNotZero: { /* jump, in1 */
|
case OP_IfNotZero: { /* jump, in1 */
|
||||||
pIn1 = &aMem[pOp->p1];
|
pIn1 = &aMem[pOp->p1];
|
||||||
assert( pIn1->flags&MEM_Int );
|
assert( pIn1->flags&MEM_Int );
|
||||||
VdbeBranchTaken(pIn1->u.i<0, 2);
|
VdbeBranchTaken(pIn1->u.i<0, 2);
|
||||||
if( pIn1->u.i ){
|
if( pIn1->u.i ){
|
||||||
pIn1->u.i += pOp->p3;
|
pIn1->u.i -= pOp->p3;
|
||||||
goto jump_to_p2;
|
goto jump_to_p2;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user