Experimental changes to improve the performance of OP_Next.
FossilOrigin-Name: 1a249845251199c00817893add300a1a654b4df9
This commit is contained in:
parent
3d4435b234
commit
a205a486d2
23
manifest
23
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\sseveral\sharmless\scompiler\swarnings\sand\sa\sdocumentation\sbug.
|
||||
D 2011-08-26T20:55:50.529
|
||||
C Experimental\schanges\sto\simprove\sthe\sperformance\sof\sOP_Next.
|
||||
D 2011-08-27T18:48:57.573
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 8c930e7b493d59099ea1304bd0f2aed152eb3315
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -124,7 +124,7 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
||||
F src/backup.c 28a4fe55327ff708bfaf9d4326d02686f7a553c3
|
||||
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
|
||||
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||
F src/btree.c ed13fdefdbe671d5777773dcfb3a162ddb4623ae
|
||||
F src/btree.c bd89d604a532063da8ed1a095f1805db49896325
|
||||
F src/btree.h 9ddf04226eac592d4cc3709c5a8b33b2351ff5f7
|
||||
F src/btreeInt.h 67978c014fa4f7cc874032dd3aacadd8db656bc3
|
||||
F src/build.c 2d5de52df616a3bf5a659cbca85211c46e2ba9bd
|
||||
@ -238,11 +238,11 @@ F src/update.c 74a6cfb34e9732c1e2a86278b229913b4b51eeec
|
||||
F src/utf.c c53eb7404b3eb5c1cbb5655c6a7a0e0ce6bd50f0
|
||||
F src/util.c 06302ffd2b80408d4f6c7af71f7090e0cf8d8ff7
|
||||
F src/vacuum.c 05513dca036a1e7848fe18d5ed1265ac0b32365e
|
||||
F src/vdbe.c 4a7191c0f8e918b74e8c84cbdd77746d6b7e3bcf
|
||||
F src/vdbe.h 2bf6ec77d8b9980fc19da6e0b0a36d0dbf884ce4
|
||||
F src/vdbe.c d63854aef07d036987f768dae7ca5c852881ce28
|
||||
F src/vdbe.h c1eeedacab6bcf1e7c2cf8203ba9763a616f9a86
|
||||
F src/vdbeInt.h f9250326f264ca5f100acc19e9c07096bb889096
|
||||
F src/vdbeapi.c 11dc47987abacb76ad016dcf5abc0dc422482a98
|
||||
F src/vdbeaux.c 11b0df8822ecf61e543562247207df75e2ebb617
|
||||
F src/vdbeaux.c dd5d10ae523bbc6ed55ac73daa28a9ea1f2fa42a
|
||||
F src/vdbeblob.c f024f0bf420f36b070143c32b15cc7287341ffd3
|
||||
F src/vdbemem.c 0498796b6ffbe45e32960d6a1f5adfb6e419883b
|
||||
F src/vdbesort.c 8a61a6d731cbe612217edf9eece6197f37c9489e
|
||||
@ -961,7 +961,10 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5
|
||||
F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
F tool/warnings.sh b7fdb2cc525f5ef4fa43c80e771636dd3690f9d2
|
||||
P 1dada5158215d1816edb69ff2610f9d2259ce19d
|
||||
R 16e082a02686bfb3de55c1b850240992
|
||||
U drh
|
||||
Z 9f47e5dd82da8bb114d554ebcb62232c
|
||||
P 5454d0fe227b7c1f0e7715b6c08f97019628fc4c
|
||||
R 06eac31c16dc3f7f5b4649f86c063bf4
|
||||
T *branch * experimental
|
||||
T *sym-experimental *
|
||||
T -sym-trunk *
|
||||
U dan
|
||||
Z 50e65d7380a3dc463f2c091e8241574b
|
||||
|
@ -1 +1 @@
|
||||
5454d0fe227b7c1f0e7715b6c08f97019628fc4c
|
||||
1a249845251199c00817893add300a1a654b4df9
|
23
src/btree.c
23
src/btree.c
@ -3479,7 +3479,8 @@ static int btreeCursor(
|
||||
return SQLITE_READONLY;
|
||||
}
|
||||
if( iTable==1 && btreePagecount(pBt)==0 ){
|
||||
return SQLITE_EMPTY;
|
||||
assert( wrFlag==0 );
|
||||
iTable = 0;
|
||||
}
|
||||
|
||||
/* Now that no other errors can occur, finish filling in the BtCursor
|
||||
@ -4233,6 +4234,9 @@ static int moveToRoot(BtCursor *pCur){
|
||||
releasePage(pCur->apPage[i]);
|
||||
}
|
||||
pCur->iPage = 0;
|
||||
}else if( pCur->pgnoRoot==0 ){
|
||||
pCur->eState = CURSOR_INVALID;
|
||||
return SQLITE_OK;
|
||||
}else{
|
||||
rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]);
|
||||
if( rc!=SQLITE_OK ){
|
||||
@ -4342,7 +4346,7 @@ int sqlite3BtreeFirst(BtCursor *pCur, int *pRes){
|
||||
rc = moveToRoot(pCur);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( pCur->eState==CURSOR_INVALID ){
|
||||
assert( pCur->apPage[pCur->iPage]->nCell==0 );
|
||||
assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
|
||||
*pRes = 1;
|
||||
}else{
|
||||
assert( pCur->apPage[pCur->iPage]->nCell>0 );
|
||||
@ -4381,7 +4385,7 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
|
||||
rc = moveToRoot(pCur);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( CURSOR_INVALID==pCur->eState ){
|
||||
assert( pCur->apPage[pCur->iPage]->nCell==0 );
|
||||
assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
|
||||
*pRes = 1;
|
||||
}else{
|
||||
assert( pCur->eState==CURSOR_VALID );
|
||||
@ -4454,12 +4458,12 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
if( rc ){
|
||||
return rc;
|
||||
}
|
||||
assert( pCur->apPage[pCur->iPage] );
|
||||
assert( pCur->apPage[pCur->iPage]->isInit );
|
||||
assert( pCur->apPage[pCur->iPage]->nCell>0 || pCur->eState==CURSOR_INVALID );
|
||||
assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage] );
|
||||
assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->isInit );
|
||||
assert( pCur->eState==CURSOR_INVALID || pCur->apPage[pCur->iPage]->nCell>0 );
|
||||
if( pCur->eState==CURSOR_INVALID ){
|
||||
*pRes = -1;
|
||||
assert( pCur->apPage[pCur->iPage]->nCell==0 );
|
||||
assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
|
||||
return SQLITE_OK;
|
||||
}
|
||||
assert( pCur->apPage[0]->intKey || pIdxKey );
|
||||
@ -7376,6 +7380,11 @@ int sqlite3BtreeUpdateMeta(Btree *p, int idx, u32 iMeta){
|
||||
int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
|
||||
i64 nEntry = 0; /* Value to return in *pnEntry */
|
||||
int rc; /* Return code */
|
||||
|
||||
if( pCur->pgnoRoot==0 ){
|
||||
*pnEntry = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
rc = moveToRoot(pCur);
|
||||
|
||||
/* Unless an error occurs, the following loop runs one iteration for each
|
||||
|
45
src/vdbe.c
45
src/vdbe.c
@ -2550,7 +2550,7 @@ case OP_Count: { /* out2-prerelease */
|
||||
BtCursor *pCrsr;
|
||||
|
||||
pCrsr = p->apCsr[pOp->p1]->pCursor;
|
||||
if( pCrsr ){
|
||||
if( ALWAYS(pCrsr) ){
|
||||
rc = sqlite3BtreeCount(pCrsr, &nEntry);
|
||||
}else{
|
||||
nEntry = 0;
|
||||
@ -3112,15 +3112,9 @@ case OP_OpenWrite: {
|
||||
rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor);
|
||||
pCur->pKeyInfo = pKeyInfo;
|
||||
|
||||
/* Since it performs no memory allocation or IO, the only values that
|
||||
** sqlite3BtreeCursor() may return are SQLITE_EMPTY and SQLITE_OK.
|
||||
** SQLITE_EMPTY is only returned when attempting to open the table
|
||||
** rooted at page 1 of a zero-byte database. */
|
||||
assert( rc==SQLITE_EMPTY || rc==SQLITE_OK );
|
||||
if( rc==SQLITE_EMPTY ){
|
||||
pCur->pCursor = 0;
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
/* Since it performs no memory allocation or IO, the only value that
|
||||
** sqlite3BtreeCursor() may return is SQLITE_OK. */
|
||||
assert( rc==SQLITE_OK );
|
||||
|
||||
/* Set the VdbeCursor.isTable and isIndex variables. Previous versions of
|
||||
** SQLite used to check if the root-page flags were sane at this point
|
||||
@ -3333,7 +3327,7 @@ case OP_SeekGt: { /* jump, in3 */
|
||||
assert( OP_SeekGe == OP_SeekLt+2 );
|
||||
assert( OP_SeekGt == OP_SeekLt+3 );
|
||||
assert( pC->isOrdered );
|
||||
if( pC->pCursor!=0 ){
|
||||
if( ALWAYS(pC->pCursor!=0) ){
|
||||
oc = pOp->opcode;
|
||||
pC->nullRow = 0;
|
||||
if( pC->isTable ){
|
||||
@ -3691,7 +3685,7 @@ case OP_NotExists: { /* jump, in3 */
|
||||
assert( pC->isTable );
|
||||
assert( pC->pseudoTableReg==0 );
|
||||
pCrsr = pC->pCursor;
|
||||
if( pCrsr!=0 ){
|
||||
if( ALWAYS(pCrsr!=0) ){
|
||||
res = 0;
|
||||
iKey = pIn3->u.i;
|
||||
rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
|
||||
@ -4218,6 +4212,7 @@ case OP_NullRow: {
|
||||
assert( pC!=0 );
|
||||
pC->nullRow = 1;
|
||||
pC->rowidIsValid = 0;
|
||||
assert( pC->pCursor || pC->pVtabCursor );
|
||||
if( pC->pCursor ){
|
||||
sqlite3BtreeClearCursor(pC->pCursor);
|
||||
}
|
||||
@ -4241,7 +4236,7 @@ case OP_Last: { /* jump */
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC!=0 );
|
||||
pCrsr = pC->pCursor;
|
||||
if( pCrsr==0 ){
|
||||
if( NEVER(pCrsr==0) ){
|
||||
res = 1;
|
||||
}else{
|
||||
rc = sqlite3BtreeLast(pCrsr, &res);
|
||||
@ -4296,7 +4291,9 @@ case OP_Rewind: { /* jump */
|
||||
res = 1;
|
||||
if( isSorter(pC) ){
|
||||
rc = sqlite3VdbeSorterRewind(db, pC, &res);
|
||||
}else if( (pCrsr = pC->pCursor)!=0 ){
|
||||
}else{
|
||||
pCrsr = pC->pCursor;
|
||||
assert( pCrsr );
|
||||
rc = sqlite3BtreeFirst(pCrsr, &res);
|
||||
pC->atFirst = res==0 ?1:0;
|
||||
pC->deferredMoveto = 0;
|
||||
@ -4311,7 +4308,7 @@ case OP_Rewind: { /* jump */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Next P1 P2 * * P5
|
||||
/* Opcode: Next P1 P2 * P4 P5
|
||||
**
|
||||
** Advance cursor P1 so that it points to the next key/data pair in its
|
||||
** table or index. If there are no more key/value pairs then fall through
|
||||
@ -4320,6 +4317,9 @@ case OP_Rewind: { /* jump */
|
||||
**
|
||||
** The P1 cursor must be for a real table, not a pseudo-table.
|
||||
**
|
||||
** P4 is always of type P4_ADVANCE. The function pointer points to
|
||||
** sqlite3BtreeNext().
|
||||
**
|
||||
** If P5 is positive and the jump is taken, then event counter
|
||||
** number P5-1 in the prepared statement is incremented.
|
||||
**
|
||||
@ -4334,13 +4334,15 @@ case OP_Rewind: { /* jump */
|
||||
**
|
||||
** The P1 cursor must be for a real table, not a pseudo-table.
|
||||
**
|
||||
** P4 is always of type P4_ADVANCE. The function pointer points to
|
||||
** sqlite3BtreePrevious().
|
||||
**
|
||||
** If P5 is positive and the jump is taken, then event counter
|
||||
** number P5-1 in the prepared statement is incremented.
|
||||
*/
|
||||
case OP_Prev: /* jump */
|
||||
case OP_Next: { /* jump */
|
||||
VdbeCursor *pC;
|
||||
BtCursor *pCrsr;
|
||||
int res;
|
||||
|
||||
CHECK_FOR_INTERRUPT;
|
||||
@ -4354,15 +4356,12 @@ case OP_Next: { /* jump */
|
||||
assert( pOp->opcode==OP_Next );
|
||||
rc = sqlite3VdbeSorterNext(db, pC, &res);
|
||||
}else{
|
||||
pCrsr = pC->pCursor;
|
||||
if( pCrsr==0 ){
|
||||
pC->nullRow = 1;
|
||||
break;
|
||||
}
|
||||
res = 1;
|
||||
assert( pC->deferredMoveto==0 );
|
||||
rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(pCrsr, &res) :
|
||||
sqlite3BtreePrevious(pCrsr, &res);
|
||||
assert( pC->pCursor );
|
||||
assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
|
||||
assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
|
||||
rc = pOp->p4.xAdvance(pC->pCursor, &res);
|
||||
}
|
||||
pC->nullRow = (u8)res;
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
|
@ -61,6 +61,7 @@ struct VdbeOp {
|
||||
KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */
|
||||
int *ai; /* Used when p4type is P4_INTARRAY */
|
||||
SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */
|
||||
int (*xAdvance)(BtCursor *, int *);
|
||||
} p4;
|
||||
#ifdef SQLITE_DEBUG
|
||||
char *zComment; /* Comment to improve readability */
|
||||
@ -116,6 +117,7 @@ typedef struct VdbeOpList VdbeOpList;
|
||||
#define P4_INT32 (-14) /* P4 is a 32-bit signed integer */
|
||||
#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
|
||||
#define P4_SUBPROGRAM (-18) /* P4 is a pointer to a SubProgram structure */
|
||||
#define P4_ADVANCE (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */
|
||||
|
||||
/* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure
|
||||
** is made. That copy is freed when the Vdbe is finalized. But if the
|
||||
|
@ -433,6 +433,12 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
|
||||
n = pOp[-1].p1;
|
||||
if( n>nMaxArgs ) nMaxArgs = n;
|
||||
#endif
|
||||
}else if( opcode==OP_Next ){
|
||||
pOp->p4.xAdvance = sqlite3BtreeNext;
|
||||
pOp->p4type = P4_ADVANCE;
|
||||
}else if( opcode==OP_Prev ){
|
||||
pOp->p4.xAdvance = sqlite3BtreePrevious;
|
||||
pOp->p4type = P4_ADVANCE;
|
||||
}
|
||||
|
||||
if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
|
||||
|
Loading…
Reference in New Issue
Block a user