mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Performance optimizations in the VDBE and especially to the OP_Next and
related opcodes and in the sqlite3BtreeNext() and sqlite3BtreePrevious() routines. This is a cherrypick of [6f99b54aedeb], [d2efea1682a7], and [d78c5d89de4b]. FossilOrigin-Name: 7f72fc4f47445a2c01910b268335873de9f75059
This commit is contained in:
23
manifest
23
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Performance\simprovement\sin\ssqlite3BtreeNext()\sand\ssqlite3BtreePrevious()\nfor\sthe\scommon\scase\sof\sa\svalid\scursor.
|
C Performance\soptimizations\sin\sthe\sVDBE\sand\sespecially\sto\sthe\sOP_Next\sand\nrelated\sopcodes\sand\sin\sthe\ssqlite3BtreeNext()\sand\ssqlite3BtreePrevious()\nroutines.\s\sThis\sis\sa\scherrypick\sof\s[6f99b54aedeb],\s[d2efea1682a7],\sand\n[d78c5d89de4b].
|
||||||
D 2013-08-19T20:04:10.623
|
D 2013-08-20T03:13:51.513
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
|
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@@ -163,9 +163,9 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
|||||||
F src/backup.c 43b348822db3e4cef48b2ae5a445fbeb6c73a165
|
F src/backup.c 43b348822db3e4cef48b2ae5a445fbeb6c73a165
|
||||||
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
|
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
|
||||||
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||||
F src/btree.c 78287b3012fe65fd5e38927d40c01e01a783e016
|
F src/btree.c adea13e65d6c7b969bcd74cea6ae79b2d3c393fa
|
||||||
F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf
|
F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf
|
||||||
F src/btreeInt.h eecc84f02375b2bb7a44abbcbbe3747dde73edb2
|
F src/btreeInt.h 51cf220a9b9223354770883e93a859dc377aa27f
|
||||||
F src/build.c f99a715ff9290996b579d5e1ec8e94239dc9ae5e
|
F src/build.c f99a715ff9290996b579d5e1ec8e94239dc9ae5e
|
||||||
F src/callback.c d7e46f40c3cf53c43550b7da7a1d0479910b62cc
|
F src/callback.c d7e46f40c3cf53c43550b7da7a1d0479910b62cc
|
||||||
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||||
@@ -277,10 +277,10 @@ F src/update.c 7f3fe64d8f3b44c44a1eac293f0f85f87c355b7a
|
|||||||
F src/utf.c 8d819e2e5104a430fc2005f018db14347c95a38f
|
F src/utf.c 8d819e2e5104a430fc2005f018db14347c95a38f
|
||||||
F src/util.c f566b5138099a2df8533b190d0dcc74b7dfbe0c9
|
F src/util.c f566b5138099a2df8533b190d0dcc74b7dfbe0c9
|
||||||
F src/vacuum.c d9c5759f4c5a438bb43c2086f72c5d2edabc36c8
|
F src/vacuum.c d9c5759f4c5a438bb43c2086f72c5d2edabc36c8
|
||||||
F src/vdbe.c 0fbe7a904a1187dc6c8a2dbe2f594f0ce8d01401
|
F src/vdbe.c 938feb53407dee2234849aad0f103ae9b941595e
|
||||||
F src/vdbe.h 4f554b5627f26710c4c36d919110a3fc611ca5c4
|
F src/vdbe.h 4f554b5627f26710c4c36d919110a3fc611ca5c4
|
||||||
F src/vdbeInt.h e9b7c6b165a31a4715c5aa97223d20d265515231
|
F src/vdbeInt.h cbe71b8b36d8b3bba5709cc3f436c7e3b47b7b08
|
||||||
F src/vdbeapi.c 4d13580bd058b39623e8fcfc233b7df4b8191e8b
|
F src/vdbeapi.c 96b24b946cf21894f63d9393e821baa2f0a80979
|
||||||
F src/vdbeaux.c a6ea36a9dc714e1128a0173249a0532ddcab0489
|
F src/vdbeaux.c a6ea36a9dc714e1128a0173249a0532ddcab0489
|
||||||
F src/vdbeblob.c 5dc79627775bd9a9b494dd956e26297946417d69
|
F src/vdbeblob.c 5dc79627775bd9a9b494dd956e26297946417d69
|
||||||
F src/vdbemem.c 833005f1cbbf447289f1973dba2a0c2228c7b8ab
|
F src/vdbemem.c 833005f1cbbf447289f1973dba2a0c2228c7b8ab
|
||||||
@@ -1105,7 +1105,10 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
|||||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||||
F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae
|
F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae
|
||||||
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
|
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
|
||||||
P d6c4d48a002a6d7057fccc30064ce0b049678f0c
|
P dc65ad8c4c67b21e3b042b8df6580d02b634a90b
|
||||||
R 5570190c517979d35e3b41a2553566a9
|
Q +6f99b54aedeb91e46d52f65504d02a9cc61c0062
|
||||||
|
Q +d2efea1682a7e708000c1f5d36370aaf1199b3be
|
||||||
|
Q +d78c5d89de4b840351b026c9db1952fc24e689d0
|
||||||
|
R 539c71750e964e780f11bfb1b59ee716
|
||||||
U drh
|
U drh
|
||||||
Z 8413b4240dd170b2f74e62b701d0cb1c
|
Z feae42d544c0a4532e8cd3cb8461eca6
|
||||||
|
@@ -1 +1 @@
|
|||||||
dc65ad8c4c67b21e3b042b8df6580d02b634a90b
|
7f72fc4f47445a2c01910b268335873de9f75059
|
48
src/btree.c
48
src/btree.c
@@ -724,6 +724,9 @@ static int btreeRestoreCursorPosition(BtCursor *pCur){
|
|||||||
sqlite3_free(pCur->pKey);
|
sqlite3_free(pCur->pKey);
|
||||||
pCur->pKey = 0;
|
pCur->pKey = 0;
|
||||||
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID );
|
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID );
|
||||||
|
if( pCur->skipNext && pCur->eState==CURSOR_VALID ){
|
||||||
|
pCur->eState = CURSOR_SKIPNEXT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -749,7 +752,7 @@ int sqlite3BtreeCursorHasMoved(BtCursor *pCur, int *pHasMoved){
|
|||||||
*pHasMoved = 1;
|
*pHasMoved = 1;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
if( pCur->eState!=CURSOR_VALID || pCur->skipNext!=0 ){
|
if( pCur->eState!=CURSOR_VALID || NEVER(pCur->skipNext!=0) ){
|
||||||
*pHasMoved = 1;
|
*pHasMoved = 1;
|
||||||
}else{
|
}else{
|
||||||
*pHasMoved = 0;
|
*pHasMoved = 0;
|
||||||
@@ -4797,23 +4800,27 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
|
|||||||
|
|
||||||
assert( cursorHoldsMutex(pCur) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
assert( pRes!=0 );
|
assert( pRes!=0 );
|
||||||
|
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
|
||||||
if( pCur->eState!=CURSOR_VALID ){
|
if( pCur->eState!=CURSOR_VALID ){
|
||||||
rc = restoreCursorPosition(pCur);
|
rc = restoreCursorPosition(pCur);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
|
*pRes = 0;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
if( CURSOR_INVALID==pCur->eState ){
|
if( CURSOR_INVALID==pCur->eState ){
|
||||||
*pRes = 1;
|
*pRes = 1;
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
}
|
if( pCur->skipNext ){
|
||||||
if( pCur->skipNext ){
|
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
|
||||||
if( pCur->skipNext>0 ){
|
pCur->eState = CURSOR_VALID;
|
||||||
|
if( pCur->skipNext>0 ){
|
||||||
|
pCur->skipNext = 0;
|
||||||
|
*pRes = 0;
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
pCur->skipNext = 0;
|
pCur->skipNext = 0;
|
||||||
*pRes = 0;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
}
|
||||||
pCur->skipNext = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pPage = pCur->apPage[pCur->iPage];
|
pPage = pCur->apPage[pCur->iPage];
|
||||||
@@ -4832,7 +4839,10 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
|
|||||||
if( idx>=pPage->nCell ){
|
if( idx>=pPage->nCell ){
|
||||||
if( !pPage->leaf ){
|
if( !pPage->leaf ){
|
||||||
rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
|
rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
|
||||||
if( rc ) return rc;
|
if( rc ){
|
||||||
|
*pRes = 0;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
rc = moveToLeftmost(pCur);
|
rc = moveToLeftmost(pCur);
|
||||||
*pRes = 0;
|
*pRes = 0;
|
||||||
return rc;
|
return rc;
|
||||||
@@ -4874,24 +4884,31 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
|
|||||||
MemPage *pPage;
|
MemPage *pPage;
|
||||||
|
|
||||||
assert( cursorHoldsMutex(pCur) );
|
assert( cursorHoldsMutex(pCur) );
|
||||||
|
assert( pRes!=0 );
|
||||||
|
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
|
||||||
pCur->atLast = 0;
|
pCur->atLast = 0;
|
||||||
if( pCur->eState!=CURSOR_VALID ){
|
if( pCur->eState!=CURSOR_VALID ){
|
||||||
if( ALWAYS(pCur->eState>=CURSOR_REQUIRESEEK) ){
|
if( ALWAYS(pCur->eState>=CURSOR_REQUIRESEEK) ){
|
||||||
rc = btreeRestoreCursorPosition(pCur);
|
rc = btreeRestoreCursorPosition(pCur);
|
||||||
if( rc!=SQLITE_OK ) return rc;
|
if( rc!=SQLITE_OK ){
|
||||||
|
*pRes = 0;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if( CURSOR_INVALID==pCur->eState ){
|
if( CURSOR_INVALID==pCur->eState ){
|
||||||
*pRes = 1;
|
*pRes = 1;
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
}
|
if( pCur->skipNext ){
|
||||||
if( pCur->skipNext ){
|
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
|
||||||
if( pCur->skipNext<0 ){
|
pCur->eState = CURSOR_VALID;
|
||||||
|
if( pCur->skipNext<0 ){
|
||||||
|
pCur->skipNext = 0;
|
||||||
|
*pRes = 0;
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
pCur->skipNext = 0;
|
pCur->skipNext = 0;
|
||||||
*pRes = 0;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
}
|
||||||
pCur->skipNext = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pPage = pCur->apPage[pCur->iPage];
|
pPage = pCur->apPage[pCur->iPage];
|
||||||
@@ -4900,6 +4917,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
|
|||||||
int idx = pCur->aiIdx[pCur->iPage];
|
int idx = pCur->aiIdx[pCur->iPage];
|
||||||
rc = moveToChild(pCur, get4byte(findCell(pPage, idx)));
|
rc = moveToChild(pCur, get4byte(findCell(pPage, idx)));
|
||||||
if( rc ){
|
if( rc ){
|
||||||
|
*pRes = 0;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
rc = moveToRightmost(pCur);
|
rc = moveToRightmost(pCur);
|
||||||
|
@@ -520,14 +520,19 @@ struct BtCursor {
|
|||||||
/*
|
/*
|
||||||
** Potential values for BtCursor.eState.
|
** Potential values for BtCursor.eState.
|
||||||
**
|
**
|
||||||
** CURSOR_VALID:
|
|
||||||
** Cursor points to a valid entry. getPayload() etc. may be called.
|
|
||||||
**
|
|
||||||
** CURSOR_INVALID:
|
** CURSOR_INVALID:
|
||||||
** Cursor does not point to a valid entry. This can happen (for example)
|
** Cursor does not point to a valid entry. This can happen (for example)
|
||||||
** because the table is empty or because BtreeCursorFirst() has not been
|
** because the table is empty or because BtreeCursorFirst() has not been
|
||||||
** called.
|
** called.
|
||||||
**
|
**
|
||||||
|
** CURSOR_VALID:
|
||||||
|
** Cursor points to a valid entry. getPayload() etc. may be called.
|
||||||
|
**
|
||||||
|
** CURSOR_SKIPNEXT:
|
||||||
|
** Cursor is valid except that the Cursor.skipNext field is non-zero
|
||||||
|
** indicating that the next sqlite3BtreeNext() or sqlite3BtreePrevious()
|
||||||
|
** operation should be a no-op.
|
||||||
|
**
|
||||||
** CURSOR_REQUIRESEEK:
|
** CURSOR_REQUIRESEEK:
|
||||||
** The table that this cursor was opened on still exists, but has been
|
** The table that this cursor was opened on still exists, but has been
|
||||||
** modified since the cursor was last used. The cursor position is saved
|
** modified since the cursor was last used. The cursor position is saved
|
||||||
@@ -544,8 +549,9 @@ struct BtCursor {
|
|||||||
*/
|
*/
|
||||||
#define CURSOR_INVALID 0
|
#define CURSOR_INVALID 0
|
||||||
#define CURSOR_VALID 1
|
#define CURSOR_VALID 1
|
||||||
#define CURSOR_REQUIRESEEK 2
|
#define CURSOR_SKIPNEXT 2
|
||||||
#define CURSOR_FAULT 3
|
#define CURSOR_REQUIRESEEK 3
|
||||||
|
#define CURSOR_FAULT 4
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** The database page the PENDING_BYTE occupies. This page is never used.
|
** The database page the PENDING_BYTE occupies. This page is never used.
|
||||||
|
34
src/vdbe.c
34
src/vdbe.c
@@ -588,7 +588,7 @@ int sqlite3VdbeExec(
|
|||||||
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||||
if( db->xProgress ){
|
if( db->xProgress ){
|
||||||
assert( 0 < db->nProgressOps );
|
assert( 0 < db->nProgressOps );
|
||||||
nProgressLimit = (unsigned)p->aCounter[SQLITE_STMTSTATUS_VM_STEP-1];
|
nProgressLimit = (unsigned)p->aCounter[SQLITE_STMTSTATUS_VM_STEP];
|
||||||
if( nProgressLimit==0 ){
|
if( nProgressLimit==0 ){
|
||||||
nProgressLimit = db->nProgressOps;
|
nProgressLimit = db->nProgressOps;
|
||||||
}else{
|
}else{
|
||||||
@@ -1449,7 +1449,7 @@ case OP_Function: {
|
|||||||
sqlite3VdbeMemMove(&ctx.s, pOut);
|
sqlite3VdbeMemMove(&ctx.s, pOut);
|
||||||
MemSetTypeFlag(&ctx.s, MEM_Null);
|
MemSetTypeFlag(&ctx.s, MEM_Null);
|
||||||
|
|
||||||
ctx.isError = 0;
|
ctx.fErrorOrAux = 0;
|
||||||
if( ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
|
if( ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
|
||||||
assert( pOp>aOp );
|
assert( pOp>aOp );
|
||||||
assert( pOp[-1].p4type==P4_COLLSEQ );
|
assert( pOp[-1].p4type==P4_COLLSEQ );
|
||||||
@@ -1460,11 +1460,6 @@ case OP_Function: {
|
|||||||
(*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */
|
(*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */
|
||||||
lastRowid = db->lastRowid;
|
lastRowid = db->lastRowid;
|
||||||
|
|
||||||
/* If any auxiliary data functions have been called by this user function,
|
|
||||||
** immediately call the destructor for any non-static values.
|
|
||||||
*/
|
|
||||||
sqlite3VdbeDeleteAuxData(p, pc, pOp->p1);
|
|
||||||
|
|
||||||
if( db->mallocFailed ){
|
if( db->mallocFailed ){
|
||||||
/* Even though a malloc() has failed, the implementation of the
|
/* Even though a malloc() has failed, the implementation of the
|
||||||
** user function may have called an sqlite3_result_XXX() function
|
** user function may have called an sqlite3_result_XXX() function
|
||||||
@@ -1476,9 +1471,12 @@ case OP_Function: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If the function returned an error, throw an exception */
|
/* If the function returned an error, throw an exception */
|
||||||
if( ctx.isError ){
|
if( ctx.fErrorOrAux ){
|
||||||
sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s));
|
if( ctx.isError ){
|
||||||
rc = ctx.isError;
|
sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s));
|
||||||
|
rc = ctx.isError;
|
||||||
|
}
|
||||||
|
sqlite3VdbeDeleteAuxData(p, pc, pOp->p1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the result of the function into register P3 */
|
/* Copy the result of the function into register P3 */
|
||||||
@@ -1850,12 +1848,12 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
|||||||
** then the result is always NULL.
|
** then the result is always NULL.
|
||||||
** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
|
** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
|
||||||
*/
|
*/
|
||||||
if( pOp->p5 & SQLITE_STOREP2 ){
|
if( pOp->p5 & SQLITE_JUMPIFNULL ){
|
||||||
|
pc = pOp->p2-1;
|
||||||
|
}else if( pOp->p5 & SQLITE_STOREP2 ){
|
||||||
pOut = &aMem[pOp->p2];
|
pOut = &aMem[pOp->p2];
|
||||||
MemSetTypeFlag(pOut, MEM_Null);
|
MemSetTypeFlag(pOut, MEM_Null);
|
||||||
REGISTER_TRACE(pOp->p2, pOut);
|
REGISTER_TRACE(pOp->p2, pOut);
|
||||||
}else if( pOp->p5 & SQLITE_JUMPIFNULL ){
|
|
||||||
pc = pOp->p2-1;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -4440,7 +4438,7 @@ case OP_Sort: { /* jump */
|
|||||||
sqlite3_sort_count++;
|
sqlite3_sort_count++;
|
||||||
sqlite3_search_count--;
|
sqlite3_search_count--;
|
||||||
#endif
|
#endif
|
||||||
p->aCounter[SQLITE_STMTSTATUS_SORT-1]++;
|
p->aCounter[SQLITE_STMTSTATUS_SORT]++;
|
||||||
/* Fall through into OP_Rewind */
|
/* Fall through into OP_Rewind */
|
||||||
}
|
}
|
||||||
/* Opcode: Rewind P1 P2 * * *
|
/* Opcode: Rewind P1 P2 * * *
|
||||||
@@ -4519,7 +4517,7 @@ case OP_Next: { /* jump */
|
|||||||
int res;
|
int res;
|
||||||
|
|
||||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||||
assert( pOp->p5<=ArraySize(p->aCounter) );
|
assert( pOp->p5<ArraySize(p->aCounter) );
|
||||||
pC = p->apCsr[pOp->p1];
|
pC = p->apCsr[pOp->p1];
|
||||||
if( pC==0 ){
|
if( pC==0 ){
|
||||||
break; /* See ticket #2273 */
|
break; /* See ticket #2273 */
|
||||||
@@ -4529,7 +4527,7 @@ case OP_Next: { /* jump */
|
|||||||
assert( pOp->opcode==OP_SorterNext );
|
assert( pOp->opcode==OP_SorterNext );
|
||||||
rc = sqlite3VdbeSorterNext(db, pC, &res);
|
rc = sqlite3VdbeSorterNext(db, pC, &res);
|
||||||
}else{
|
}else{
|
||||||
res = 1;
|
/* res = 1; // Always initialized by the xAdvance() call */
|
||||||
assert( pC->deferredMoveto==0 );
|
assert( pC->deferredMoveto==0 );
|
||||||
assert( pC->pCursor );
|
assert( pC->pCursor );
|
||||||
assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
|
assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
|
||||||
@@ -4540,7 +4538,7 @@ case OP_Next: { /* jump */
|
|||||||
pC->cacheStatus = CACHE_STALE;
|
pC->cacheStatus = CACHE_STALE;
|
||||||
if( res==0 ){
|
if( res==0 ){
|
||||||
pc = pOp->p2 - 1;
|
pc = pOp->p2 - 1;
|
||||||
if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
|
p->aCounter[pOp->p5]++;
|
||||||
#ifdef SQLITE_TEST
|
#ifdef SQLITE_TEST
|
||||||
sqlite3_search_count++;
|
sqlite3_search_count++;
|
||||||
#endif
|
#endif
|
||||||
@@ -6243,7 +6241,7 @@ vdbe_error_halt:
|
|||||||
vdbe_return:
|
vdbe_return:
|
||||||
db->lastRowid = lastRowid;
|
db->lastRowid = lastRowid;
|
||||||
testcase( nVmStep>0 );
|
testcase( nVmStep>0 );
|
||||||
p->aCounter[SQLITE_STMTSTATUS_VM_STEP-1] += (int)nVmStep;
|
p->aCounter[SQLITE_STMTSTATUS_VM_STEP] += (int)nVmStep;
|
||||||
sqlite3VdbeLeave(p);
|
sqlite3VdbeLeave(p);
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
@@ -266,10 +266,11 @@ struct sqlite3_context {
|
|||||||
Mem s; /* The return value is stored here */
|
Mem s; /* The return value is stored here */
|
||||||
Mem *pMem; /* Memory cell used to store aggregate context */
|
Mem *pMem; /* Memory cell used to store aggregate context */
|
||||||
CollSeq *pColl; /* Collating sequence */
|
CollSeq *pColl; /* Collating sequence */
|
||||||
int isError; /* Error code returned by the function. */
|
|
||||||
int skipFlag; /* Skip skip accumulator loading if true */
|
|
||||||
int iOp; /* Instruction number of OP_Function */
|
|
||||||
Vdbe *pVdbe; /* The VM that owns this context */
|
Vdbe *pVdbe; /* The VM that owns this context */
|
||||||
|
int iOp; /* Instruction number of OP_Function */
|
||||||
|
int isError; /* Error code returned by the function. */
|
||||||
|
u8 skipFlag; /* Skip skip accumulator loading if true */
|
||||||
|
u8 fErrorOrAux; /* isError!=0 or pVdbe->pAuxData modified */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -345,7 +346,7 @@ struct Vdbe {
|
|||||||
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
|
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
|
||||||
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
|
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
|
||||||
int iStatement; /* Statement number (or 0 if has not opened stmt) */
|
int iStatement; /* Statement number (or 0 if has not opened stmt) */
|
||||||
int aCounter[4]; /* Counters used by sqlite3_stmt_status() */
|
u32 aCounter[5]; /* Counters used by sqlite3_stmt_status() */
|
||||||
#ifndef SQLITE_OMIT_TRACE
|
#ifndef SQLITE_OMIT_TRACE
|
||||||
i64 startTime; /* Time when query started - used for profiling */
|
i64 startTime; /* Time when query started - used for profiling */
|
||||||
#endif
|
#endif
|
||||||
|
@@ -211,12 +211,14 @@ void sqlite3_result_double(sqlite3_context *pCtx, double rVal){
|
|||||||
void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){
|
void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){
|
||||||
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
|
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
|
||||||
pCtx->isError = SQLITE_ERROR;
|
pCtx->isError = SQLITE_ERROR;
|
||||||
|
pCtx->fErrorOrAux = 1;
|
||||||
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, SQLITE_TRANSIENT);
|
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, SQLITE_TRANSIENT);
|
||||||
}
|
}
|
||||||
#ifndef SQLITE_OMIT_UTF16
|
#ifndef SQLITE_OMIT_UTF16
|
||||||
void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){
|
void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){
|
||||||
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
|
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
|
||||||
pCtx->isError = SQLITE_ERROR;
|
pCtx->isError = SQLITE_ERROR;
|
||||||
|
pCtx->fErrorOrAux = 1;
|
||||||
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT);
|
sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -280,6 +282,7 @@ void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){
|
|||||||
}
|
}
|
||||||
void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
|
void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
|
||||||
pCtx->isError = errCode;
|
pCtx->isError = errCode;
|
||||||
|
pCtx->fErrorOrAux = 1;
|
||||||
if( pCtx->s.flags & MEM_Null ){
|
if( pCtx->s.flags & MEM_Null ){
|
||||||
sqlite3VdbeMemSetStr(&pCtx->s, sqlite3ErrStr(errCode), -1,
|
sqlite3VdbeMemSetStr(&pCtx->s, sqlite3ErrStr(errCode), -1,
|
||||||
SQLITE_UTF8, SQLITE_STATIC);
|
SQLITE_UTF8, SQLITE_STATIC);
|
||||||
@@ -290,6 +293,7 @@ void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
|
|||||||
void sqlite3_result_error_toobig(sqlite3_context *pCtx){
|
void sqlite3_result_error_toobig(sqlite3_context *pCtx){
|
||||||
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
|
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
|
||||||
pCtx->isError = SQLITE_TOOBIG;
|
pCtx->isError = SQLITE_TOOBIG;
|
||||||
|
pCtx->fErrorOrAux = 1;
|
||||||
sqlite3VdbeMemSetStr(&pCtx->s, "string or blob too big", -1,
|
sqlite3VdbeMemSetStr(&pCtx->s, "string or blob too big", -1,
|
||||||
SQLITE_UTF8, SQLITE_STATIC);
|
SQLITE_UTF8, SQLITE_STATIC);
|
||||||
}
|
}
|
||||||
@@ -299,6 +303,7 @@ void sqlite3_result_error_nomem(sqlite3_context *pCtx){
|
|||||||
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
|
assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
|
||||||
sqlite3VdbeMemSetNull(&pCtx->s);
|
sqlite3VdbeMemSetNull(&pCtx->s);
|
||||||
pCtx->isError = SQLITE_NOMEM;
|
pCtx->isError = SQLITE_NOMEM;
|
||||||
|
pCtx->fErrorOrAux = 1;
|
||||||
pCtx->s.db->mallocFailed = 1;
|
pCtx->s.db->mallocFailed = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -621,6 +626,10 @@ void sqlite3_set_auxdata(
|
|||||||
pAuxData->iArg = iArg;
|
pAuxData->iArg = iArg;
|
||||||
pAuxData->pNext = pVdbe->pAuxData;
|
pAuxData->pNext = pVdbe->pAuxData;
|
||||||
pVdbe->pAuxData = pAuxData;
|
pVdbe->pAuxData = pAuxData;
|
||||||
|
if( pCtx->fErrorOrAux==0 ){
|
||||||
|
pCtx->isError = 0;
|
||||||
|
pCtx->fErrorOrAux = 1;
|
||||||
|
}
|
||||||
}else if( pAuxData->xDelete ){
|
}else if( pAuxData->xDelete ){
|
||||||
pAuxData->xDelete(pAuxData->pAux);
|
pAuxData->xDelete(pAuxData->pAux);
|
||||||
}
|
}
|
||||||
@@ -1289,7 +1298,7 @@ sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){
|
|||||||
*/
|
*/
|
||||||
int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
|
int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
|
||||||
Vdbe *pVdbe = (Vdbe*)pStmt;
|
Vdbe *pVdbe = (Vdbe*)pStmt;
|
||||||
int v = pVdbe->aCounter[op-1];
|
u32 v = pVdbe->aCounter[op];
|
||||||
if( resetFlag ) pVdbe->aCounter[op-1] = 0;
|
if( resetFlag ) pVdbe->aCounter[op] = 0;
|
||||||
return v;
|
return (int)v;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user