mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Fix for the sqlite3AbortOtherActiveVdbes() problem. (CVS 4328)
FossilOrigin-Name: e40d40a5d41c491bef852a92e5846b273b206909
This commit is contained in:
30
manifest
30
manifest
@@ -1,5 +1,5 @@
|
||||
C Fix\sminor\sproblems\son\svarious\stests.\s\sThis\sis\sa\ssnapshot\sprior\sto\spossible\nmajor\schanges\sin\sorder\sto\sfix\sthe\ssqlite3AbortOtherActiveVdbes\sproblem.\s(CVS\s4327)
|
||||
D 2007-08-29T19:15:08
|
||||
C Fix\sfor\sthe\ssqlite3AbortOtherActiveVdbes()\sproblem.\s(CVS\s4328)
|
||||
D 2007-08-30T01:19:59
|
||||
F Makefile.in bfcc303429a5d9dcd552d807ee016c77427418c3
|
||||
F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499
|
||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||
@@ -80,11 +80,11 @@ F src/alter.c c9f30b4d6fbf7eff7c5518b002a217d4ecd13bcf
|
||||
F src/analyze.c 49b4bd45eb286d833793ed6bf72355a5c1974865
|
||||
F src/attach.c a52225c75b107be8c5bc144a2b6d20201be3f8f8
|
||||
F src/auth.c 083c1205b45e3f52291ec539d396b4fc557856b3
|
||||
F src/btmutex.c abc2eda085ff7729c4093db8b4e5357e932f082c
|
||||
F src/btree.c 91b362f7366f1c3f3c62458c4367fbf4e1ee7b16
|
||||
F src/btree.h a90328ee4d7aa49a1ec4309c94a9fae65f39d969
|
||||
F src/btreeInt.h 1fa6510aa8601dc0358a5240d191335236d3cf76
|
||||
F src/build.c 830d1a6b2de157fc4d4dd08d4433066ad83f8b72
|
||||
F src/btmutex.c 442be6f068d77ca9ffd69899cf0a3943c244548c
|
||||
F src/btree.c f22955f6d04f045d72882c10f70f1a2fb9d21f54
|
||||
F src/btree.h 32fad0f06a280e007c31b089a0e1c63e858084ce
|
||||
F src/btreeInt.h 4330c19b8314545fdb209cc77e2a57f6a5290e9c
|
||||
F src/build.c f8eeec5c71e8bab41b6cfcac79d56c9103a26a91
|
||||
F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
|
||||
F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
|
||||
F src/date.c af235f38f50809abd0a96da3bb3e0cc32be6226e
|
||||
@@ -123,7 +123,7 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
|
||||
F src/pager.c f9830adfd3752c860a4024da5b871df5af4ed8a4
|
||||
F src/pager.h 1ac4468049348ec72df09d138fc1d7e3a9d0d3a6
|
||||
F src/parse.y 2d2ce439dc6184621fb0b86f4fc5aca7f391a590
|
||||
F src/pragma.c 9b989506a1b7c8aecd6befb8235e2f57a4aba7e5
|
||||
F src/pragma.c 65109b3d6a62f9a0d64e739653b76afa1122a00d
|
||||
F src/prepare.c 1506fd279824b1f4bac97514966d0370101f9a6b
|
||||
F src/printf.c e8cb99691b8370d0b721e2618db0ad01550e9b98
|
||||
F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da
|
||||
@@ -162,12 +162,12 @@ F src/update.c e89b980b443d44b68bfc0b1746cdb6308e049ac9
|
||||
F src/utf.c 4af6259d5906b5a1bf3035cc387c4d7907bdd56e
|
||||
F src/util.c 3f9c0387b54f977726790f52ab92cd3d9379b367
|
||||
F src/vacuum.c 38745037c63246d1b0669038257890cf89fc4578
|
||||
F src/vdbe.c 9f2ef520614425016881234965b8146ac771d7dc
|
||||
F src/vdbe.h 498e9ddade4baf70f2fc39e585670131dde07caa
|
||||
F src/vdbe.c 9d22f69c813e5a2a4c14c33cb89b7fd4edc0f462
|
||||
F src/vdbe.h 03a0fa17f6753a24d6cb585d7a362944a2c115aa
|
||||
F src/vdbeInt.h 630145b9bfaa19190ab491f52658a7db550f2247
|
||||
F src/vdbeapi.c 9c2d681b75e4b90c28b9dd01a3f2e5905267f884
|
||||
F src/vdbeaux.c 77db89679834d55ff026c6311c34d2964bf46431
|
||||
F src/vdbeblob.c 4da667be7dff5e197b3b986d6f2095cf97a22917
|
||||
F src/vdbeaux.c 0e92ed38fe905131f1a95011d67cea67cd973ff2
|
||||
F src/vdbeblob.c 82f51cdf9b0c0af729732fde48c824e498c0a1ca
|
||||
F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
|
||||
F src/vdbemem.c 246d434fa60bde6553490eb686adfd86adcd6712
|
||||
F src/vtab.c ace9b41a088f6ad55d2e39084d92180a2bee3276
|
||||
@@ -567,7 +567,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
|
||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||
P 5201fa4f8310ffc8b6881d96b152581d74e2df6b
|
||||
R 562e94af4a79ce02beef7330814d555d
|
||||
P 35cb63ecfd9d8ca7304aae1b150ee5d1c3498bde
|
||||
R 29b78abcd06801b9626610a433b86a61
|
||||
U drh
|
||||
Z 261f9a43e26799d1b991384722e003d4
|
||||
Z 1ee4e75dc5784f54890a8213aed8fba0
|
||||
|
@@ -1 +1 @@
|
||||
35cb63ecfd9d8ca7304aae1b150ee5d1c3498bde
|
||||
e40d40a5d41c491bef852a92e5846b273b206909
|
@@ -10,7 +10,7 @@
|
||||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** $Id: btmutex.c,v 1.6 2007/08/29 17:43:20 drh Exp $
|
||||
** $Id: btmutex.c,v 1.7 2007/08/30 01:19:59 drh Exp $
|
||||
**
|
||||
** This file contains code used to implement mutexes on Btree objects.
|
||||
** This code really belongs in btree.c. But btree.c is getting too
|
||||
@@ -239,7 +239,7 @@ int sqlite3BtreeHoldsAllMutexes(sqlite3 *db){
|
||||
void sqlite3BtreeMutexArrayInsert(BtreeMutexArray *pArray, Btree *pBtree){
|
||||
int i, j;
|
||||
BtShared *pBt;
|
||||
if( pBtree->sharable==0 ) return;
|
||||
if( pBtree==0 || pBtree->sharable==0 ) return;
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
for(i=0; i<pArray->nMutex; i++){
|
||||
|
76
src/btree.c
76
src/btree.c
@@ -9,7 +9,7 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** $Id: btree.c,v 1.419 2007/08/29 19:15:08 drh Exp $
|
||||
** $Id: btree.c,v 1.420 2007/08/30 01:19:59 drh Exp $
|
||||
**
|
||||
** This file implements a external (disk-based) database using BTrees.
|
||||
** See the header comment on "btreeInt.h" for additional information.
|
||||
@@ -356,7 +356,10 @@ static void clearCursorPosition(BtCursor *pCur){
|
||||
int sqlite3BtreeRestoreOrClearCursorPosition(BtCursor *pCur){
|
||||
int rc;
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
assert( pCur->eState==CURSOR_REQUIRESEEK );
|
||||
assert( pCur->eState>=CURSOR_REQUIRESEEK );
|
||||
if( pCur->eState==CURSOR_FAULT ){
|
||||
return pCur->skip;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_INCRBLOB
|
||||
if( pCur->isIncrblobHandle ){
|
||||
return SQLITE_ABORT;
|
||||
@@ -373,7 +376,7 @@ int sqlite3BtreeRestoreOrClearCursorPosition(BtCursor *pCur){
|
||||
}
|
||||
|
||||
#define restoreOrClearCursorPosition(p) \
|
||||
(p->eState==CURSOR_REQUIRESEEK ? \
|
||||
(p->eState>=CURSOR_REQUIRESEEK ? \
|
||||
sqlite3BtreeRestoreOrClearCursorPosition(p) : \
|
||||
SQLITE_OK)
|
||||
|
||||
@@ -2394,17 +2397,50 @@ int sqlite3BtreeCommit(Btree *p){
|
||||
** Return the number of write-cursors open on this handle. This is for use
|
||||
** in assert() expressions, so it is only compiled if NDEBUG is not
|
||||
** defined.
|
||||
**
|
||||
** For the purposes of this routine, a write-cursor is any cursor that
|
||||
** is capable of writing to the databse. That means the cursor was
|
||||
** originally opened for writing and the cursor has not be disabled
|
||||
** by having its state changed to CURSOR_FAULT.
|
||||
*/
|
||||
static int countWriteCursors(BtShared *pBt){
|
||||
BtCursor *pCur;
|
||||
int r = 0;
|
||||
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
|
||||
if( pCur->wrFlag ) r++;
|
||||
if( pCur->wrFlag && pCur->eState!=CURSOR_FAULT ) r++;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This routine sets the state to CURSOR_FAULT and the error
|
||||
** code to errCode for every cursor on BtShared that pBtree
|
||||
** references.
|
||||
**
|
||||
** Every cursor is tripped, including cursors that belong
|
||||
** to other database connections that happen to be sharing
|
||||
** the cache with pBtree.
|
||||
**
|
||||
** This routine gets called when a rollback occurs.
|
||||
** All cursors using the same cache must be tripped
|
||||
** to prevent them from trying to use the btree after
|
||||
** the rollback. The rollback may have deleted tables
|
||||
** or moved root pages, so it is not sufficient to
|
||||
** save the state of the cursor. The cursor must be
|
||||
** invalidated.
|
||||
*/
|
||||
void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){
|
||||
BtCursor *p;
|
||||
sqlite3BtreeEnter(pBtree);
|
||||
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
|
||||
clearCursorPosition(p);
|
||||
p->eState = CURSOR_FAULT;
|
||||
p->skip = errCode;
|
||||
}
|
||||
sqlite3BtreeLeave(pBtree);
|
||||
}
|
||||
|
||||
/*
|
||||
** Rollback the transaction in progress. All cursors will be
|
||||
** invalided by this operation. Any attempt to use a cursor
|
||||
@@ -2430,15 +2466,7 @@ int sqlite3BtreeRollback(Btree *p){
|
||||
** we cannot simply return the error to the caller. Instead, abort
|
||||
** all queries that may be using any of the cursors that failed to save.
|
||||
*/
|
||||
while( pBt->pCursor ){
|
||||
sqlite3 *db = pBt->pCursor->pBtree->pSqlite;
|
||||
if( db ){
|
||||
/**** FIX ME: This can deadlock ****/
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
sqlite3AbortOtherActiveVdbes(db, 0);
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
}
|
||||
}
|
||||
sqlite3BtreeTripAllCursors(p, rc);
|
||||
}
|
||||
#endif
|
||||
btreeIntegrity(p);
|
||||
@@ -3343,7 +3371,13 @@ static int moveToRoot(BtCursor *pCur){
|
||||
BtShared *pBt = p->pBt;
|
||||
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
if( pCur->eState==CURSOR_REQUIRESEEK ){
|
||||
assert( CURSOR_INVALID < CURSOR_REQUIRESEEK );
|
||||
assert( CURSOR_VALID < CURSOR_REQUIRESEEK );
|
||||
assert( CURSOR_FAULT > CURSOR_REQUIRESEEK );
|
||||
if( pCur->eState>=CURSOR_REQUIRESEEK ){
|
||||
if( pCur->eState==CURSOR_FAULT ){
|
||||
return pCur->skip;
|
||||
}
|
||||
clearCursorPosition(pCur);
|
||||
}
|
||||
pRoot = pCur->pPage;
|
||||
@@ -5514,6 +5548,9 @@ int sqlite3BtreeInsert(
|
||||
if( checkReadLocks(pCur->pBtree, pCur->pgnoRoot, pCur) ){
|
||||
return SQLITE_LOCKED; /* The table pCur points to has a read lock */
|
||||
}
|
||||
if( pCur->eState==CURSOR_FAULT ){
|
||||
return pCur->skip;
|
||||
}
|
||||
|
||||
/* Save the positions of any other cursors open on this table */
|
||||
clearCursorPosition(pCur);
|
||||
@@ -5592,6 +5629,9 @@ int sqlite3BtreeDelete(BtCursor *pCur){
|
||||
return rc;
|
||||
}
|
||||
assert( !pBt->readOnly );
|
||||
if( pCur->eState==CURSOR_FAULT ){
|
||||
return pCur->skip;
|
||||
}
|
||||
if( pCur->idx >= pPage->nCell ){
|
||||
return SQLITE_ERROR; /* The cursor is not pointing to anything */
|
||||
}
|
||||
@@ -6789,8 +6829,12 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
|
||||
assert( cursorHoldsMutex(pCsr) );
|
||||
assert( sqlite3_mutex_held(pCsr->pBtree->pSqlite->mutex) );
|
||||
assert(pCsr->isIncrblobHandle);
|
||||
if( pCsr->eState==CURSOR_REQUIRESEEK ){
|
||||
return SQLITE_ABORT;
|
||||
if( pCsr->eState>=CURSOR_REQUIRESEEK ){
|
||||
if( pCsr->eState==CURSOR_FAULT ){
|
||||
return pCsr->skip;
|
||||
}else{
|
||||
return SQLITE_ABORT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check some preconditions:
|
||||
|
@@ -13,7 +13,7 @@
|
||||
** subsystem. See comments in the source code for a detailed description
|
||||
** of what each interface routine does.
|
||||
**
|
||||
** @(#) $Id: btree.h,v 1.91 2007/08/29 17:43:20 drh Exp $
|
||||
** @(#) $Id: btree.h,v 1.92 2007/08/30 01:19:59 drh Exp $
|
||||
*/
|
||||
#ifndef _BTREE_H_
|
||||
#define _BTREE_H_
|
||||
@@ -125,6 +125,7 @@ int sqlite3BtreeDropTable(Btree*, int, int*);
|
||||
int sqlite3BtreeClearTable(Btree*, int);
|
||||
int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue);
|
||||
int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
|
||||
void sqlite3BtreeTripAllCursors(Btree*, int);
|
||||
|
||||
int sqlite3BtreeCursor(
|
||||
Btree*, /* BTree containing table to open */
|
||||
|
@@ -9,7 +9,7 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** $Id: btreeInt.h,v 1.12 2007/08/29 00:33:07 drh Exp $
|
||||
** $Id: btreeInt.h,v 1.13 2007/08/30 01:19:59 drh Exp $
|
||||
**
|
||||
** This file implements a external (disk-based) database using BTrees.
|
||||
** For a detailed discussion of BTrees, refer to
|
||||
@@ -466,10 +466,18 @@ struct BtCursor {
|
||||
** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in
|
||||
** this state, restoreOrClearCursorPosition() can be called to attempt to
|
||||
** seek the cursor to the saved position.
|
||||
**
|
||||
** CURSOR_FAULT:
|
||||
** A unrecoverable error (an I/O error or a malloc failure) has occurred
|
||||
** on a different connection that shares the BtShared cache with this
|
||||
** cursor. The error has left the cache in an inconsistent state.
|
||||
** Do nothing else with this cursor. Any attempt to use the cursor
|
||||
** should return the error code stored in BtCursor.skip
|
||||
*/
|
||||
#define CURSOR_INVALID 0
|
||||
#define CURSOR_VALID 1
|
||||
#define CURSOR_REQUIRESEEK 2
|
||||
#define CURSOR_FAULT 3
|
||||
|
||||
/*
|
||||
** The TRACE macro will print high-level status information about the
|
||||
|
@@ -22,7 +22,7 @@
|
||||
** COMMIT
|
||||
** ROLLBACK
|
||||
**
|
||||
** $Id: build.c,v 1.442 2007/08/29 14:06:23 danielk1977 Exp $
|
||||
** $Id: build.c,v 1.443 2007/08/30 01:19:59 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@@ -164,7 +164,7 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
sqlite3VdbeJumpHere(v, pParse->cookieGoto-1);
|
||||
for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){
|
||||
if( (mask & pParse->cookieMask)==0 ) continue;
|
||||
sqlite3VdbeUsesBtree(v, iDb, db->aDb[iDb].pBt);
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
sqlite3VdbeAddOp(v, OP_Transaction, iDb, (mask & pParse->writeMask)!=0);
|
||||
sqlite3VdbeAddOp(v, OP_VerifyCookie, iDb, pParse->cookieValue[iDb]);
|
||||
}
|
||||
@@ -847,6 +847,7 @@ void sqlite3StartTable(
|
||||
** set them now.
|
||||
*/
|
||||
sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1); /* file_format */
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
lbl = sqlite3VdbeMakeLabel(v);
|
||||
sqlite3VdbeAddOp(v, OP_If, 0, lbl);
|
||||
fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ?
|
||||
@@ -2693,6 +2694,7 @@ void sqlite3MinimumFileFormat(Parse *pParse, int iDb, int minFormat){
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
if( v ){
|
||||
sqlite3VdbeAddOp(v, OP_ReadCookie, iDb, 1);
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
sqlite3VdbeAddOp(v, OP_Integer, minFormat, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Ge, 0, sqlite3VdbeCurrentAddr(v)+3);
|
||||
sqlite3VdbeAddOp(v, OP_Integer, minFormat, 0);
|
||||
@@ -3089,6 +3091,7 @@ void sqlite3BeginTransaction(Parse *pParse, int type){
|
||||
if( type!=TK_DEFERRED ){
|
||||
for(i=0; i<db->nDb; i++){
|
||||
sqlite3VdbeAddOp(v, OP_Transaction, i, (type==TK_EXCLUSIVE)+1);
|
||||
sqlite3VdbeUsesBtree(v, i);
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_AutoCommit, 0, 0);
|
||||
|
@@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** This file contains code used to implement the PRAGMA command.
|
||||
**
|
||||
** $Id: pragma.c,v 1.146 2007/08/21 10:44:16 drh Exp $
|
||||
** $Id: pragma.c,v 1.147 2007/08/30 01:19:59 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@@ -300,6 +300,7 @@ void sqlite3Pragma(
|
||||
};
|
||||
int addr;
|
||||
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
if( !zRight ){
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cache_size", P3_STATIC);
|
||||
@@ -455,6 +456,7 @@ void sqlite3Pragma(
|
||||
sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4);
|
||||
sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1);
|
||||
sqlite3VdbeChangeP1(v, iAddr+5, iDb);
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1043,6 +1045,7 @@ void sqlite3Pragma(
|
||||
){
|
||||
|
||||
int iCookie; /* Cookie index. 0 for schema-cookie, 6 for user-cookie. */
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
switch( zLeft[0] ){
|
||||
case 's': case 'S':
|
||||
iCookie = 0;
|
||||
|
16
src/vdbe.c
16
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.647 2007/08/29 12:31:28 danielk1977 Exp $
|
||||
** $Id: vdbe.c,v 1.648 2007/08/30 01:19:59 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@@ -2421,6 +2421,7 @@ case OP_Statement: { /* no-push */
|
||||
Btree *pBt;
|
||||
if( i>=0 && i<db->nDb && (pBt = db->aDb[i].pBt)!=0 && !(db->autoCommit) ){
|
||||
assert( sqlite3BtreeIsInTrans(pBt) );
|
||||
assert( (p->btreeMask & (1<<i))!=0 );
|
||||
if( !sqlite3BtreeIsInStmt(pBt) ){
|
||||
rc = sqlite3BtreeBeginStmt(pBt);
|
||||
p->openedStatement = 1;
|
||||
@@ -2511,6 +2512,7 @@ case OP_Transaction: { /* no-push */
|
||||
Btree *pBt;
|
||||
|
||||
assert( i>=0 && i<db->nDb );
|
||||
assert( (p->btreeMask & (1<<i))!=0 );
|
||||
pBt = db->aDb[i].pBt;
|
||||
|
||||
if( pBt ){
|
||||
@@ -2557,6 +2559,7 @@ case OP_ReadCookie: {
|
||||
}
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
assert( db->aDb[iDb].pBt!=0 );
|
||||
assert( (p->btreeMask & (1<<iDb))!=0 );
|
||||
/* The indexing of meta values at the schema layer is off by one from
|
||||
** the indexing in the btree layer. The btree considers meta[0] to
|
||||
** be the number of free pages in the database (a read-only value)
|
||||
@@ -2585,6 +2588,7 @@ case OP_SetCookie: { /* no-push */
|
||||
Db *pDb;
|
||||
assert( pOp->p2<SQLITE_N_BTREE_META );
|
||||
assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
||||
assert( (p->btreeMask & (1<<pOp->p1))!=0 );
|
||||
pDb = &db->aDb[pOp->p1];
|
||||
assert( pDb->pBt!=0 );
|
||||
assert( pTos>=p->aStack );
|
||||
@@ -2629,6 +2633,7 @@ case OP_VerifyCookie: { /* no-push */
|
||||
int iMeta;
|
||||
Btree *pBt;
|
||||
assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
||||
assert( (p->btreeMask & (1<<pOp->p1))!=0 );
|
||||
pBt = db->aDb[pOp->p1].pBt;
|
||||
if( pBt ){
|
||||
rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&iMeta);
|
||||
@@ -2720,6 +2725,7 @@ case OP_OpenWrite: { /* no-push */
|
||||
assert( (pTos->flags & MEM_Dyn)==0 );
|
||||
pTos--;
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
assert( (p->btreeMask & (1<<iDb))!=0 );
|
||||
pDb = &db->aDb[iDb];
|
||||
pX = pDb->pBt;
|
||||
assert( pX!=0 );
|
||||
@@ -4075,6 +4081,7 @@ case OP_Destroy: {
|
||||
rc = SQLITE_LOCKED;
|
||||
}else{
|
||||
assert( iCnt==1 );
|
||||
assert( (p->btreeMask & (1<<pOp->p2))!=0 );
|
||||
rc = sqlite3BtreeDropTable(db->aDb[pOp->p2].pBt, pOp->p1, &iMoved);
|
||||
pTos++;
|
||||
pTos->flags = MEM_Int;
|
||||
@@ -4136,6 +4143,7 @@ case OP_Clear: { /* no-push */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
assert( (p->btreeMask & (1<<pOp->p2))!=0 );
|
||||
rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, pOp->p1);
|
||||
break;
|
||||
}
|
||||
@@ -4166,6 +4174,7 @@ case OP_CreateTable: {
|
||||
int flags;
|
||||
Db *pDb;
|
||||
assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
||||
assert( (p->btreeMask & (1<<pOp->p1))!=0 );
|
||||
pDb = &db->aDb[pOp->p1];
|
||||
assert( pDb->pBt!=0 );
|
||||
if( pOp->opcode==OP_CreateTable ){
|
||||
@@ -4327,6 +4336,8 @@ case OP_IntegrityCk: {
|
||||
aRoot[j] = 0;
|
||||
popStack(&pTos, nRoot);
|
||||
pTos++;
|
||||
assert( pOp->p2>=0 && pOp->p2<db->nDb );
|
||||
assert( (p->btreeMask & (1<<pOp->p2))!=0 );
|
||||
z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p2].pBt, aRoot, nRoot,
|
||||
pnErr->u.i, &nErr);
|
||||
pnErr->u.i -= nErr;
|
||||
@@ -4701,6 +4712,7 @@ case OP_IncrVacuum: { /* no-push */
|
||||
Btree *pBt;
|
||||
|
||||
assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
||||
assert( (p->btreeMask & (1<<pOp->p1))!=0 );
|
||||
pBt = db->aDb[pOp->p1].pBt;
|
||||
rc = sqlite3BtreeIncrVacuum(pBt);
|
||||
if( rc==SQLITE_DONE ){
|
||||
@@ -4752,6 +4764,8 @@ case OP_TableLock: { /* no-push */
|
||||
if( isWriteLock ){
|
||||
p1 = (-1*p1)-1;
|
||||
}
|
||||
assert( p1>=0 && p1<db->nDb );
|
||||
assert( (p->btreeMask & (1<<p1))!=0 );
|
||||
rc = sqlite3BtreeLockTable(db->aDb[p1].pBt, pOp->p2, isWriteLock);
|
||||
if( rc==SQLITE_LOCKED ){
|
||||
const char *z = (const char *)pOp->p3;
|
||||
|
@@ -15,7 +15,7 @@
|
||||
** or VDBE. The VDBE implements an abstract machine that runs a
|
||||
** simple program to access and modify the underlying database.
|
||||
**
|
||||
** $Id: vdbe.h,v 1.112 2007/08/28 22:24:35 drh Exp $
|
||||
** $Id: vdbe.h,v 1.113 2007/08/30 01:19:59 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITE_VDBE_H_
|
||||
#define _SQLITE_VDBE_H_
|
||||
@@ -120,7 +120,7 @@ void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
|
||||
void sqlite3VdbeJumpHere(Vdbe*, int addr);
|
||||
void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N);
|
||||
void sqlite3VdbeChangeP3(Vdbe*, int addr, const char *zP1, int N);
|
||||
void sqlite3VdbeUsesBtree(Vdbe*, int, Btree*);
|
||||
void sqlite3VdbeUsesBtree(Vdbe*, int);
|
||||
VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
|
||||
int sqlite3VdbeMakeLabel(Vdbe*);
|
||||
void sqlite3VdbeDelete(Vdbe*);
|
||||
|
@@ -660,12 +660,15 @@ static char *displayP3(Op *pOp, char *zTemp, int nTemp){
|
||||
** Declare to the Vdbe that the BTree object at db->aDb[i] is used.
|
||||
**
|
||||
*/
|
||||
void sqlite3VdbeUsesBtree(Vdbe *p, int i, Btree *pBtree){
|
||||
void sqlite3VdbeUsesBtree(Vdbe *p, int i){
|
||||
int mask;
|
||||
assert( i>=0 && i<p->db->nDb );
|
||||
assert( i<sizeof(p->btreeMask)*8 );
|
||||
assert( p->db->aDb[i].pBt==pBtree );
|
||||
p->btreeMask |= 1<<i;
|
||||
sqlite3BtreeMutexArrayInsert(&p->aMutex, pBtree);
|
||||
mask = 1<<i;
|
||||
if( (p->btreeMask & mask)==0 ){
|
||||
p->btreeMask |= mask;
|
||||
sqlite3BtreeMutexArrayInsert(&p->aMutex, p->db->aDb[i].pBt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1301,21 +1304,28 @@ static void checkActiveVdbeCnt(sqlite3 *db){
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Find every active VM other than pVdbe and change its status to
|
||||
** aborted. This happens when one VM causes a rollback due to an
|
||||
** ON CONFLICT ROLLBACK clause (for example). The other VMs must be
|
||||
** aborted so that they do not have data rolled out from underneath
|
||||
** them leading to a segfault.
|
||||
** For every Btree that in database connection db which
|
||||
** has been modified, "trip" or invalidate each cursor in
|
||||
** that Btree might have been modified so that the cursor
|
||||
** can never be used again. This happens when a rollback
|
||||
*** occurs. We have to trip all the other cursors, even
|
||||
** cursor from other VMs in different database connections,
|
||||
** so that none of them try to use the data at which they
|
||||
** were pointing and which now may have been changed due
|
||||
** to the rollback.
|
||||
**
|
||||
** Remember that a rollback can delete tables complete and
|
||||
** reorder rootpages. So it is not sufficient just to save
|
||||
** the state of the cursor. We have to invalidate the cursor
|
||||
** so that it is never used again.
|
||||
*/
|
||||
void sqlite3AbortOtherActiveVdbes(sqlite3 *db, Vdbe *pExcept){
|
||||
Vdbe *pOther;
|
||||
for(pOther=db->pVdbe; pOther; pOther=pOther->pNext){
|
||||
if( pOther==pExcept ) continue;
|
||||
if( pOther->magic!=VDBE_MAGIC_RUN || pOther->pc<0 ) continue;
|
||||
checkActiveVdbeCnt(db);
|
||||
closeAllCursorsExceptActiveVtabs(pOther);
|
||||
checkActiveVdbeCnt(db);
|
||||
pOther->aborted = 1;
|
||||
void invalidateCursorsOnModifiedBtrees(sqlite3 *db){
|
||||
int i;
|
||||
for(i=0; i<db->nDb; i++){
|
||||
Btree *p = db->aDb[i].pBt;
|
||||
if( p && sqlite3BtreeIsInTrans(p) ){
|
||||
sqlite3BtreeTripAllCursors(p, SQLITE_ABORT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1440,7 +1450,7 @@ int sqlite3VdbeHalt(Vdbe *p){
|
||||
/* We are forced to roll back the active transaction. Before doing
|
||||
** so, abort any other statements this handle currently has active.
|
||||
*/
|
||||
sqlite3AbortOtherActiveVdbes(db, p);
|
||||
invalidateCursorsOnModifiedBtrees(db);
|
||||
sqlite3RollbackAll(db);
|
||||
db->autoCommit = 1;
|
||||
}
|
||||
@@ -1480,7 +1490,7 @@ int sqlite3VdbeHalt(Vdbe *p){
|
||||
}else if( p->errorAction==OE_Abort ){
|
||||
xFunc = sqlite3BtreeRollbackStmt;
|
||||
}else{
|
||||
sqlite3AbortOtherActiveVdbes(db, p);
|
||||
invalidateCursorsOnModifiedBtrees(db);
|
||||
sqlite3RollbackAll(db);
|
||||
db->autoCommit = 1;
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@
|
||||
**
|
||||
** This file contains code used to implement incremental BLOB I/O.
|
||||
**
|
||||
** $Id: vdbeblob.c,v 1.15 2007/08/29 17:43:20 drh Exp $
|
||||
** $Id: vdbeblob.c,v 1.16 2007/08/30 01:19:59 drh Exp $
|
||||
*/
|
||||
|
||||
#include "sqliteInt.h"
|
||||
@@ -164,7 +164,7 @@ int sqlite3_blob_open(
|
||||
sqlite3VdbeChangeP2(v, 1, pTab->pSchema->schema_cookie);
|
||||
|
||||
/* Make sure a mutex is held on the table to be accessed */
|
||||
sqlite3VdbeUsesBtree(v, iDb, db->aDb[iDb].pBt);
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
|
||||
/* Configure the db number pushed onto the stack */
|
||||
sqlite3VdbeChangeP1(v, 2, iDb);
|
||||
|
Reference in New Issue
Block a user