Invalidate all VDBE cursor row caches in between calls to sqlite3_step()
since the emphemeral content that those caches point to might change if the statement is READ UNCOMMITTED. (CVS 2886) FossilOrigin-Name: 0ae461313c1642a49a9f6cda608c42c7c0053ce4
This commit is contained in:
parent
4bddfd2f6e
commit
76873ab240
16
manifest
16
manifest
@ -1,5 +1,5 @@
|
||||
C Continued\sprogress\stoward\sa\sworking\swince\sbackend.\s(CVS\s2885)
|
||||
D 2006-01-07T18:14:48
|
||||
C Invalidate\sall\sVDBE\scursor\srow\scaches\sin\sbetween\scalls\sto\ssqlite3_step()\nsince\sthe\semphemeral\scontent\sthat\sthose\scaches\spoint\sto\smight\schange\sif\nthe\sstatement\sis\sREAD\sUNCOMMITTED.\s(CVS\s2886)
|
||||
D 2006-01-07T18:48:26
|
||||
F Makefile.in c79fbdaa264c6afcd435f2fb492551de5a8cf80d
|
||||
F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092
|
||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||
@ -84,11 +84,11 @@ F src/update.c 29ba0385c8639803cd8e6e616e99096a0bc10443
|
||||
F src/utf.c b7bffac4260177ae7f83c01d025fe0f5ed70ce71
|
||||
F src/util.c 8a3ef3c1b345cdadcee33ce4537c63bb0fda0ed8
|
||||
F src/vacuum.c a7301804d4f849da0ce9d869219c71c6d621c34e
|
||||
F src/vdbe.c b0617790673c64b78740b7c1fc9c3e247e05612a
|
||||
F src/vdbe.c 87a796e2889283b681be71076fa6b6318561f2bd
|
||||
F src/vdbe.h 8729a4ee16ff9aeab2af9667df3cf300ff978e13
|
||||
F src/vdbeInt.h 9b78ba00cc006bff17e04a54ba3ded9fc7810a10
|
||||
F src/vdbeInt.h 5451cf71f229e366ac543607c0a17f36e5737ea9
|
||||
F src/vdbeapi.c 7335569b1bad946ba53892384b4b1534e877b1ee
|
||||
F src/vdbeaux.c a4eea656afebc6161771ddfa7a9c91186a5d7888
|
||||
F src/vdbeaux.c cb57a0b6aef5ff002b42baf366c85e389509b2d7
|
||||
F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5
|
||||
F src/vdbemem.c deba8d6e3727643924b210a8c531a496c2b8d386
|
||||
F src/where.c de22a3a84c595ca1ad206dd19818f65f950e79f8
|
||||
@ -335,7 +335,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
|
||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
|
||||
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
|
||||
P 19f71a6d1982e986f5436bff71ef38b1bcc2e11d
|
||||
R 90bcf273c8a689d05bbbb1a9b9eb146b
|
||||
P 15fda14ee0c0524d3064d767f48edd689c090d95
|
||||
R 8b6ba0a7cf083b8ec0fb5215eb91310f
|
||||
U drh
|
||||
Z fc0de77c4da0e5b5eb0148bbd35f7f04
|
||||
Z c1686b0c208bc7bdd63ff2b9442034c8
|
||||
|
@ -1 +1 @@
|
||||
15fda14ee0c0524d3064d767f48edd689c090d95
|
||||
0ae461313c1642a49a9f6cda608c42c7c0053ce4
|
37
src/vdbe.c
37
src/vdbe.c
@ -43,7 +43,7 @@
|
||||
** in this file for details. If in doubt, do not deviate from existing
|
||||
** commenting and indentation practices when changing or adding code.
|
||||
**
|
||||
** $Id: vdbe.c,v 1.515 2006/01/07 18:10:33 drh Exp $
|
||||
** $Id: vdbe.c,v 1.516 2006/01/07 18:48:26 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@ -879,6 +879,9 @@ case OP_Callback: { /* no-push */
|
||||
Deephemeralize(pMem);
|
||||
}
|
||||
|
||||
/* Invalidate all ephemeral cursor row caches */
|
||||
p->cacheCtr = (p->cacheCtr + 2)|1;
|
||||
|
||||
/* Make sure the results of the current row are \000 terminated
|
||||
** and have an assigned type. The results are deephemeralized as
|
||||
** as side effect.
|
||||
@ -1908,7 +1911,7 @@ case OP_Column: {
|
||||
pCrsr = pC->pCursor;
|
||||
if( pC->nullRow ){
|
||||
payloadSize = 0;
|
||||
}else if( pC->cacheValid ){
|
||||
}else if( pC->cacheStatus==p->cacheCtr ){
|
||||
payloadSize = pC->payloadSize;
|
||||
zRec = (char*)pC->aRow;
|
||||
}else if( pC->isIndex ){
|
||||
@ -1924,7 +1927,7 @@ case OP_Column: {
|
||||
/* The record is the sole entry of a pseudo-table */
|
||||
payloadSize = pC->nData;
|
||||
zRec = pC->pData;
|
||||
pC->cacheValid = 0;
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
assert( payloadSize==0 || zRec!=0 );
|
||||
nField = pC->nField;
|
||||
pCrsr = 0;
|
||||
@ -1947,7 +1950,7 @@ case OP_Column: {
|
||||
/* Read and parse the table header. Store the results of the parse
|
||||
** into the record header cache fields of the cursor.
|
||||
*/
|
||||
if( pC && pC->cacheValid ){
|
||||
if( pC && pC->cacheStatus==p->cacheCtr ){
|
||||
aType = pC->aType;
|
||||
aOffset = pC->aOffset;
|
||||
}else{
|
||||
@ -2042,7 +2045,7 @@ case OP_Column: {
|
||||
pC->payloadSize = payloadSize;
|
||||
pC->aType = aType;
|
||||
pC->aOffset = aOffset;
|
||||
pC->cacheValid = 1;
|
||||
pC->cacheStatus = p->cacheCtr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2805,7 +2808,7 @@ case OP_MoveGt: { /* no-push */
|
||||
pC->rowidIsValid = 0;
|
||||
}
|
||||
pC->deferredMoveto = 0;
|
||||
pC->cacheValid = 0;
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
*pC->pIncrKey = 0;
|
||||
sqlite3_search_count++;
|
||||
if( oc==OP_MoveGe || oc==OP_MoveGt ){
|
||||
@ -2906,7 +2909,7 @@ case OP_Found: { /* no-push */
|
||||
rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
|
||||
alreadyExists = rx==SQLITE_OK && res==0;
|
||||
pC->deferredMoveto = 0;
|
||||
pC->cacheValid = 0;
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
}
|
||||
if( pOp->opcode==OP_Found ){
|
||||
if( alreadyExists ) pc = pOp->p2 - 1;
|
||||
@ -2980,7 +2983,7 @@ case OP_IsUnique: { /* no-push */
|
||||
** If there is no such entry, jump immediately to P2.
|
||||
*/
|
||||
assert( pCx->deferredMoveto==0 );
|
||||
pCx->cacheValid = 0;
|
||||
pCx->cacheStatus = CACHE_STALE;
|
||||
rc = sqlite3BtreeMoveto(pCrsr, zKey, len, &res);
|
||||
if( rc!=SQLITE_OK ) goto abort_due_to_error;
|
||||
if( res<0 ){
|
||||
@ -3053,7 +3056,7 @@ case OP_NotExists: { /* no-push */
|
||||
pC->lastRowid = pTos->i;
|
||||
pC->rowidIsValid = res==0;
|
||||
pC->nullRow = 0;
|
||||
pC->cacheValid = 0;
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
if( res!=0 ){
|
||||
pc = pOp->p2 - 1;
|
||||
pC->rowidIsValid = 0;
|
||||
@ -3229,7 +3232,7 @@ case OP_NewRowid: {
|
||||
}
|
||||
pC->rowidIsValid = 0;
|
||||
pC->deferredMoveto = 0;
|
||||
pC->cacheValid = 0;
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
}
|
||||
pTos++;
|
||||
pTos->i = v;
|
||||
@ -3303,7 +3306,7 @@ case OP_Insert: { /* no-push */
|
||||
|
||||
pC->rowidIsValid = 0;
|
||||
pC->deferredMoveto = 0;
|
||||
pC->cacheValid = 0;
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
|
||||
/* Invoke the update-hook if required. */
|
||||
if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p3 ){
|
||||
@ -3363,7 +3366,7 @@ case OP_Delete: { /* no-push */
|
||||
if( rc ) goto abort_due_to_error;
|
||||
rc = sqlite3BtreeDelete(pC->pCursor);
|
||||
pC->nextRowidValid = 0;
|
||||
pC->cacheValid = 0;
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
|
||||
/* Invoke the update-hook if required. */
|
||||
if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p3 ){
|
||||
@ -3541,7 +3544,7 @@ case OP_Last: { /* no-push */
|
||||
rc = sqlite3BtreeLast(pCrsr, &res);
|
||||
pC->nullRow = res;
|
||||
pC->deferredMoveto = 0;
|
||||
pC->cacheValid = 0;
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
if( res && pOp->p2>0 ){
|
||||
pc = pOp->p2 - 1;
|
||||
}
|
||||
@ -3590,7 +3593,7 @@ case OP_Rewind: { /* no-push */
|
||||
rc = sqlite3BtreeFirst(pCrsr, &res);
|
||||
pC->atFirst = res==0;
|
||||
pC->deferredMoveto = 0;
|
||||
pC->cacheValid = 0;
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
}else{
|
||||
res = 1;
|
||||
}
|
||||
@ -3635,7 +3638,7 @@ case OP_Next: { /* no-push */
|
||||
rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(pCrsr, &res) :
|
||||
sqlite3BtreePrevious(pCrsr, &res);
|
||||
pC->nullRow = res;
|
||||
pC->cacheValid = 0;
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
}
|
||||
if( res==0 ){
|
||||
pc = pOp->p2 - 1;
|
||||
@ -3672,7 +3675,7 @@ case OP_IdxInsert: { /* no-push */
|
||||
assert( pC->isTable==0 );
|
||||
rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0);
|
||||
assert( pC->deferredMoveto==0 );
|
||||
pC->cacheValid = 0;
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
}
|
||||
Release(pTos);
|
||||
pTos--;
|
||||
@ -3699,7 +3702,7 @@ case OP_IdxDelete: { /* no-push */
|
||||
rc = sqlite3BtreeDelete(pCrsr);
|
||||
}
|
||||
assert( pC->deferredMoveto==0 );
|
||||
pC->cacheValid = 0;
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
}
|
||||
Release(pTos);
|
||||
pTos--;
|
||||
|
@ -86,9 +86,10 @@ struct Cursor {
|
||||
|
||||
/* Cached information about the header for the data record that the
|
||||
** cursor is currently pointing to. Only valid if cacheValid is true.
|
||||
** zRow might point to (ephemeral) data for the current row, or it might
|
||||
** be NULL. */
|
||||
Bool cacheValid; /* True if the cache is valid */
|
||||
** aRow might point to (ephemeral) data for the current row, or it might
|
||||
** be NULL.
|
||||
*/
|
||||
int cacheStatus; /* Cache is valid if this matches Vdbe.cacheCtr */
|
||||
int payloadSize; /* Total number of bytes in the record */
|
||||
u32 *aType; /* Type values for all entries in the record */
|
||||
u32 *aOffset; /* Cached offsets to the start of each columns data */
|
||||
@ -103,6 +104,11 @@ typedef struct Cursor Cursor;
|
||||
*/
|
||||
#define NBFS 32
|
||||
|
||||
/*
|
||||
** A value for Cursor.cacheValid that means the cache is always invalid.
|
||||
*/
|
||||
#define CACHE_STALE 0
|
||||
|
||||
/*
|
||||
** Internally, the vdbe manipulates nearly all SQL values as Mem
|
||||
** structures. Each Mem struct may cache multiple representations (string,
|
||||
@ -287,6 +293,7 @@ struct Vdbe {
|
||||
int nMem; /* Number of memory locations currently allocated */
|
||||
Mem *aMem; /* The memory locations */
|
||||
int nCallback; /* Number of callbacks invoked so far */
|
||||
int cacheCtr; /* Cursor row cache generation counter */
|
||||
Fifo sFifo; /* A list of ROWIDs */
|
||||
int contextStackTop; /* Index of top element in the context stack */
|
||||
int contextStackDepth; /* The size of the "context" stack */
|
||||
|
@ -782,6 +782,7 @@ void sqlite3VdbeMakeReady(
|
||||
p->explain |= isExplain;
|
||||
p->magic = VDBE_MAGIC_RUN;
|
||||
p->nChange = 0;
|
||||
p->cacheCtr = 1;
|
||||
p->minWriteFileFormat = 255;
|
||||
#ifdef VDBE_PROFILE
|
||||
{
|
||||
@ -1453,7 +1454,7 @@ int sqlite3VdbeCursorMoveto(Cursor *p){
|
||||
}
|
||||
sqlite3_search_count++;
|
||||
p->deferredMoveto = 0;
|
||||
p->cacheValid = 0;
|
||||
p->cacheStatus = CACHE_STALE;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user