Improvements to mutex asserts. The quick test runs to completion without
assertion faults. (CVS 4324) FossilOrigin-Name: 2732af0ec77dbc90c0439b6a61d893d9ea3b5697
This commit is contained in:
parent
26783a58e2
commit
ff0587c632
28
manifest
28
manifest
@ -1,5 +1,5 @@
|
|||||||
C Use\sthe\sDbMalloc()\sand\sDbRealloc()\sfunctions\smore\sconsistently.\s(CVS\s4323)
|
C Improvements\sto\smutex\sasserts.\s\sThe\squick\stest\sruns\sto\scompletion\swithout\nassertion\sfaults.\s(CVS\s4324)
|
||||||
D 2007-08-29T14:06:23
|
D 2007-08-29T17:43:20
|
||||||
F Makefile.in bfcc303429a5d9dcd552d807ee016c77427418c3
|
F Makefile.in bfcc303429a5d9dcd552d807ee016c77427418c3
|
||||||
F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499
|
F Makefile.linux-gcc 65241babba6faf1152bf86574477baab19190499
|
||||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||||
@ -77,12 +77,12 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
|||||||
F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4
|
F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4
|
||||||
F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a
|
F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a
|
||||||
F src/alter.c c9f30b4d6fbf7eff7c5518b002a217d4ecd13bcf
|
F src/alter.c c9f30b4d6fbf7eff7c5518b002a217d4ecd13bcf
|
||||||
F src/analyze.c a28b43a5f79bfa7616ab506bb917077242098469
|
F src/analyze.c 49b4bd45eb286d833793ed6bf72355a5c1974865
|
||||||
F src/attach.c a52225c75b107be8c5bc144a2b6d20201be3f8f8
|
F src/attach.c a52225c75b107be8c5bc144a2b6d20201be3f8f8
|
||||||
F src/auth.c 083c1205b45e3f52291ec539d396b4fc557856b3
|
F src/auth.c 083c1205b45e3f52291ec539d396b4fc557856b3
|
||||||
F src/btmutex.c c04e67d99d949a12beb17209f307950f21313980
|
F src/btmutex.c abc2eda085ff7729c4093db8b4e5357e932f082c
|
||||||
F src/btree.c 7079a423e0da7eec5147d102202e2b51038002cd
|
F src/btree.c ff821439edf1fdf85fee7cc7b475b02cacceb2ae
|
||||||
F src/btree.h 7391b9e78ae441fe0fb3a6d3ae772770d35a4375
|
F src/btree.h a90328ee4d7aa49a1ec4309c94a9fae65f39d969
|
||||||
F src/btreeInt.h 1fa6510aa8601dc0358a5240d191335236d3cf76
|
F src/btreeInt.h 1fa6510aa8601dc0358a5240d191335236d3cf76
|
||||||
F src/build.c 830d1a6b2de157fc4d4dd08d4433066ad83f8b72
|
F src/build.c 830d1a6b2de157fc4d4dd08d4433066ad83f8b72
|
||||||
F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
|
F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
|
||||||
@ -138,7 +138,7 @@ F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4
|
|||||||
F src/tclsqlite.c d76af53f45c9e9f7f7d39531fa4c7bee7d0adad6
|
F src/tclsqlite.c d76af53f45c9e9f7f7d39531fa4c7bee7d0adad6
|
||||||
F src/test1.c 8b20d1f05777ac480d3caf8d5f79ab7a543513fc
|
F src/test1.c 8b20d1f05777ac480d3caf8d5f79ab7a543513fc
|
||||||
F src/test2.c 4ab230fbdc0decfa7422f6a052b609ba54f4dfac
|
F src/test2.c 4ab230fbdc0decfa7422f6a052b609ba54f4dfac
|
||||||
F src/test3.c de8f2a245d0adf4215487af8267c11ccca31e750
|
F src/test3.c 09098991c3a94a1c7f54d28888fca2951d459585
|
||||||
F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071
|
F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071
|
||||||
F src/test5.c 3a6a5717a149d7ca2e6d14f5be72cf7555d54dc4
|
F src/test5.c 3a6a5717a149d7ca2e6d14f5be72cf7555d54dc4
|
||||||
F src/test6.c a6223d9d938aba83f20611a2c01680d8043cd2f7
|
F src/test6.c a6223d9d938aba83f20611a2c01680d8043cd2f7
|
||||||
@ -166,8 +166,8 @@ F src/vdbe.c 9f2ef520614425016881234965b8146ac771d7dc
|
|||||||
F src/vdbe.h 498e9ddade4baf70f2fc39e585670131dde07caa
|
F src/vdbe.h 498e9ddade4baf70f2fc39e585670131dde07caa
|
||||||
F src/vdbeInt.h 630145b9bfaa19190ab491f52658a7db550f2247
|
F src/vdbeInt.h 630145b9bfaa19190ab491f52658a7db550f2247
|
||||||
F src/vdbeapi.c 9c2d681b75e4b90c28b9dd01a3f2e5905267f884
|
F src/vdbeapi.c 9c2d681b75e4b90c28b9dd01a3f2e5905267f884
|
||||||
F src/vdbeaux.c 7cc1e0b33e4d5b8259fd12b7bd28c2180903146c
|
F src/vdbeaux.c 77db89679834d55ff026c6311c34d2964bf46431
|
||||||
F src/vdbeblob.c d12ed95dac0992e1e372d079d76af047cc42f7c7
|
F src/vdbeblob.c 4da667be7dff5e197b3b986d6f2095cf97a22917
|
||||||
F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
|
F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
|
||||||
F src/vdbemem.c 246d434fa60bde6553490eb686adfd86adcd6712
|
F src/vdbemem.c 246d434fa60bde6553490eb686adfd86adcd6712
|
||||||
F src/vtab.c ace9b41a088f6ad55d2e39084d92180a2bee3276
|
F src/vtab.c ace9b41a088f6ad55d2e39084d92180a2bee3276
|
||||||
@ -182,7 +182,7 @@ F test/altermalloc.test b341e6515fa6cd9f0ac5d19153c556c9add70be9
|
|||||||
F test/analyze.test 2f55535aa335785db1a2f97d3f3831c16c09f8b0
|
F test/analyze.test 2f55535aa335785db1a2f97d3f3831c16c09f8b0
|
||||||
F test/async.test 464dc7c7ccb144e8c82ecca429e6d7cd1c96bd6e
|
F test/async.test 464dc7c7ccb144e8c82ecca429e6d7cd1c96bd6e
|
||||||
F test/async2.test 8f2c70b831dac7292450d0a42580cf2dab497dbb
|
F test/async2.test 8f2c70b831dac7292450d0a42580cf2dab497dbb
|
||||||
F test/attach.test cf289abdb120053136649efd1306ab9d47fa41b2
|
F test/attach.test b849e1baae863c3a6132ff8b9b1baf356ab6c178
|
||||||
F test/attach2.test 78bc1a25ea8785c7571b44f5947ada2bd5d78127
|
F test/attach2.test 78bc1a25ea8785c7571b44f5947ada2bd5d78127
|
||||||
F test/attach3.test eafcafb107585aecc2ed1569a77914138eef46a9
|
F test/attach3.test eafcafb107585aecc2ed1569a77914138eef46a9
|
||||||
F test/attachmalloc.test fdbfd9dc0b600db14f9189690c6c12511cc3a56f
|
F test/attachmalloc.test fdbfd9dc0b600db14f9189690c6c12511cc3a56f
|
||||||
@ -567,7 +567,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
|
|||||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||||
P d8ef7024172fffee049cfda6707220af2577e9a1
|
P c790c234c369c6b7610e67dcaaa9eee347df729c
|
||||||
R 02e243d6b7b8198a44d4e659876a4584
|
R 673cf3ccb79c2542ccd493ed4a5e1538
|
||||||
U danielk1977
|
U drh
|
||||||
Z e737eb1ddcb93155a8d9637fcf24015b
|
Z a367643531757313c52ae724bb0d4a7f
|
||||||
|
@ -1 +1 @@
|
|||||||
c790c234c369c6b7610e67dcaaa9eee347df729c
|
2732af0ec77dbc90c0439b6a61d893d9ea3b5697
|
@ -11,7 +11,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
** This file contains code associated with the ANALYZE command.
|
** This file contains code associated with the ANALYZE command.
|
||||||
**
|
**
|
||||||
** @(#) $Id: analyze.c,v 1.22 2007/08/29 04:00:58 drh Exp $
|
** @(#) $Id: analyze.c,v 1.23 2007/08/29 17:43:20 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef SQLITE_OMIT_ANALYZE
|
#ifndef SQLITE_OMIT_ANALYZE
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
@ -386,7 +386,9 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
|
|||||||
char *zSql;
|
char *zSql;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
assert( sqlite3BtreeHoldsAllMutexes(db) );
|
assert( iDb>=0 && iDb<db->nDb );
|
||||||
|
assert( db->aDb[iDb].pBt!=0 );
|
||||||
|
assert( sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
|
||||||
|
|
||||||
/* Clear any prior statistics */
|
/* Clear any prior statistics */
|
||||||
for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
|
for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
**
|
**
|
||||||
*************************************************************************
|
*************************************************************************
|
||||||
**
|
**
|
||||||
** $Id: btmutex.c,v 1.5 2007/08/29 04:00:58 drh Exp $
|
** $Id: btmutex.c,v 1.6 2007/08/29 17:43:20 drh Exp $
|
||||||
**
|
**
|
||||||
** This file contains code used to implement mutexes on Btree objects.
|
** This file contains code used to implement mutexes on Btree objects.
|
||||||
** This code really belongs in btree.c. But btree.c is getting too
|
** This code really belongs in btree.c. But btree.c is getting too
|
||||||
@ -111,18 +111,35 @@ void sqlite3BtreeLeave(Btree *p){
|
|||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
/*
|
/*
|
||||||
** Return true if a mutex is held on the btree.
|
** Return true if the BtShared mutex is held on the btree.
|
||||||
|
**
|
||||||
|
** This routine makes no determination one why or another if the
|
||||||
|
** database connection mutex is held.
|
||||||
**
|
**
|
||||||
** This routine is used only from within assert() statements.
|
** This routine is used only from within assert() statements.
|
||||||
*/
|
*/
|
||||||
int sqlite3BtreeHoldsMutex(Btree *p){
|
int sqlite3BtreeHoldsMutex(Btree *p){
|
||||||
return sqlite3_mutex_held(p->pSqlite->mutex) &&
|
return (p->sharable==0 ||
|
||||||
(p->sharable==0 ||
|
|
||||||
(p->locked && p->wantToLock && sqlite3_mutex_held(p->pBt->mutex)));
|
(p->locked && p->wantToLock && sqlite3_mutex_held(p->pBt->mutex)));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_INCRBLOB
|
||||||
|
/*
|
||||||
|
** Enter and leave a mutex on a Btree given a cursor owned by that
|
||||||
|
** Btree. These entry points are used by incremental I/O and can be
|
||||||
|
** omitted if that module is not used.
|
||||||
|
*/
|
||||||
|
void sqlite3BtreeEnterCursor(BtCursor *pCur){
|
||||||
|
sqlite3BtreeEnter(pCur->pBtree);
|
||||||
|
}
|
||||||
|
void sqlite3BtreeLeaveCursor(BtCursor *pCur){
|
||||||
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
|
}
|
||||||
|
#endif /* SQLITE_OMIT_INCRBLOB */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Enter the mutex on every Btree associated with a database
|
** Enter the mutex on every Btree associated with a database
|
||||||
** connection. This is needed (for example) prior to parsing
|
** connection. This is needed (for example) prior to parsing
|
||||||
|
74
src/btree.c
74
src/btree.c
@ -9,7 +9,7 @@
|
|||||||
** May you share freely, never taking more than you give.
|
** May you share freely, never taking more than you give.
|
||||||
**
|
**
|
||||||
*************************************************************************
|
*************************************************************************
|
||||||
** $Id: btree.c,v 1.417 2007/08/29 12:31:26 danielk1977 Exp $
|
** $Id: btree.c,v 1.418 2007/08/29 17:43:20 drh Exp $
|
||||||
**
|
**
|
||||||
** This file implements a external (disk-based) database using BTrees.
|
** This file implements a external (disk-based) database using BTrees.
|
||||||
** See the header comment on "btreeInt.h" for additional information.
|
** See the header comment on "btreeInt.h" for additional information.
|
||||||
@ -236,7 +236,7 @@ static void releasePage(MemPage *pPage); /* Forward reference */
|
|||||||
*/
|
*/
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
static int cursorHoldsMutex(BtCursor *p){
|
static int cursorHoldsMutex(BtCursor *p){
|
||||||
return sqlite3BtreeHoldsMutex(p->pBtree);
|
return sqlite3_mutex_held(p->pBt->mutex);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1150,32 +1150,43 @@ int sqlite3BtreeOpen(
|
|||||||
&& isMemdb==0
|
&& isMemdb==0
|
||||||
&& (pSqlite->flags & SQLITE_Vtab)==0
|
&& (pSqlite->flags & SQLITE_Vtab)==0
|
||||||
&& zFilename && zFilename[0]
|
&& zFilename && zFilename[0]
|
||||||
&& sqlite3SharedCacheEnabled
|
|
||||||
){
|
){
|
||||||
char *zFullPathname = (char *)sqlite3_malloc(pVfs->mxPathname);
|
if( sqlite3SharedCacheEnabled ){
|
||||||
sqlite3_mutex *mutexShared;
|
char *zFullPathname = (char *)sqlite3_malloc(pVfs->mxPathname);
|
||||||
p->sharable = 1;
|
sqlite3_mutex *mutexShared;
|
||||||
if( pSqlite ){
|
p->sharable = 1;
|
||||||
pSqlite->flags |= SQLITE_SharedCache;
|
if( pSqlite ){
|
||||||
}
|
pSqlite->flags |= SQLITE_SharedCache;
|
||||||
if( !zFullPathname ){
|
|
||||||
sqlite3_free(p);
|
|
||||||
return SQLITE_NOMEM;
|
|
||||||
}
|
|
||||||
sqlite3OsFullPathname(pVfs, zFilename, zFullPathname);
|
|
||||||
mutexShared = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
|
|
||||||
sqlite3_mutex_enter(mutexShared);
|
|
||||||
for(pBt=sqlite3SharedCacheList; pBt; pBt=pBt->pNext){
|
|
||||||
assert( pBt->nRef>0 );
|
|
||||||
if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager))
|
|
||||||
&& sqlite3PagerVfs(pBt->pPager)==pVfs ){
|
|
||||||
p->pBt = pBt;
|
|
||||||
pBt->nRef++;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
if( !zFullPathname ){
|
||||||
|
sqlite3_free(p);
|
||||||
|
return SQLITE_NOMEM;
|
||||||
|
}
|
||||||
|
sqlite3OsFullPathname(pVfs, zFilename, zFullPathname);
|
||||||
|
mutexShared = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
|
||||||
|
sqlite3_mutex_enter(mutexShared);
|
||||||
|
for(pBt=sqlite3SharedCacheList; pBt; pBt=pBt->pNext){
|
||||||
|
assert( pBt->nRef>0 );
|
||||||
|
if( 0==strcmp(zFullPathname, sqlite3PagerFilename(pBt->pPager))
|
||||||
|
&& sqlite3PagerVfs(pBt->pPager)==pVfs ){
|
||||||
|
p->pBt = pBt;
|
||||||
|
pBt->nRef++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sqlite3_mutex_leave(mutexShared);
|
||||||
|
sqlite3_free(zFullPathname);
|
||||||
}
|
}
|
||||||
sqlite3_mutex_leave(mutexShared);
|
#ifdef SQLITE_DEBUG
|
||||||
sqlite3_free(zFullPathname);
|
else{
|
||||||
|
/* In debug mode, we mark all persistent databases as sharable
|
||||||
|
** even when they are not. This exercises the locking code and
|
||||||
|
** gives more opportunity for asserts(sqlite3_mutex_held())
|
||||||
|
** statements to find locking problems.
|
||||||
|
*/
|
||||||
|
p->sharable = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if( pBt==0 ){
|
if( pBt==0 ){
|
||||||
@ -1253,6 +1264,11 @@ int sqlite3BtreeOpen(
|
|||||||
pBt->nRef = 1;
|
pBt->nRef = 1;
|
||||||
mutexShared = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
|
mutexShared = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
|
||||||
pBt->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
|
pBt->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
|
||||||
|
if( pBt->mutex==0 ){
|
||||||
|
rc = SQLITE_NOMEM;
|
||||||
|
pSqlite->mallocFailed = 0;
|
||||||
|
goto btree_open_out;
|
||||||
|
}
|
||||||
sqlite3_mutex_enter(mutexShared);
|
sqlite3_mutex_enter(mutexShared);
|
||||||
pBt->pNext = sqlite3SharedCacheList;
|
pBt->pNext = sqlite3SharedCacheList;
|
||||||
sqlite3SharedCacheList = pBt;
|
sqlite3SharedCacheList = pBt;
|
||||||
@ -2687,9 +2703,9 @@ int sqlite3BtreeCursor(
|
|||||||
*/
|
*/
|
||||||
int sqlite3BtreeCloseCursor(BtCursor *pCur){
|
int sqlite3BtreeCloseCursor(BtCursor *pCur){
|
||||||
BtShared *pBt = pCur->pBt;
|
BtShared *pBt = pCur->pBt;
|
||||||
|
Btree *pBtree = pCur->pBtree;
|
||||||
|
|
||||||
assert( cursorHoldsMutex(pCur) );
|
sqlite3BtreeEnter(pBtree);
|
||||||
assert( sqlite3_mutex_held(pCur->pBtree->pSqlite->mutex) );
|
|
||||||
clearCursorPosition(pCur);
|
clearCursorPosition(pCur);
|
||||||
if( pCur->pPrev ){
|
if( pCur->pPrev ){
|
||||||
pCur->pPrev->pNext = pCur->pNext;
|
pCur->pPrev->pNext = pCur->pNext;
|
||||||
@ -2703,6 +2719,7 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
|
|||||||
unlockBtreeIfUnused(pBt);
|
unlockBtreeIfUnused(pBt);
|
||||||
invalidateOverflowCache(pCur);
|
invalidateOverflowCache(pCur);
|
||||||
sqlite3_free(pCur);
|
sqlite3_free(pCur);
|
||||||
|
sqlite3BtreeLeave(pBtree);
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6578,7 +6595,6 @@ char *sqlite3BtreeIntegrityCheck(
|
|||||||
*/
|
*/
|
||||||
const char *sqlite3BtreeGetFilename(Btree *p){
|
const char *sqlite3BtreeGetFilename(Btree *p){
|
||||||
assert( p->pBt->pPager!=0 );
|
assert( p->pBt->pPager!=0 );
|
||||||
/* assert( sqlite3BtreeHoldsMutex(p) ); */
|
|
||||||
return sqlite3PagerFilename(p->pBt->pPager);
|
return sqlite3PagerFilename(p->pBt->pPager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6590,7 +6606,6 @@ const char *sqlite3BtreeGetFilename(Btree *p){
|
|||||||
*/
|
*/
|
||||||
const char *sqlite3BtreeGetDirname(Btree *p){
|
const char *sqlite3BtreeGetDirname(Btree *p){
|
||||||
assert( p->pBt->pPager!=0 );
|
assert( p->pBt->pPager!=0 );
|
||||||
assert( sqlite3BtreeHoldsMutex(p) );
|
|
||||||
return sqlite3PagerDirname(p->pBt->pPager);
|
return sqlite3PagerDirname(p->pBt->pPager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6604,7 +6619,6 @@ const char *sqlite3BtreeGetDirname(Btree *p){
|
|||||||
*/
|
*/
|
||||||
const char *sqlite3BtreeGetJournalname(Btree *p){
|
const char *sqlite3BtreeGetJournalname(Btree *p){
|
||||||
assert( p->pBt->pPager!=0 );
|
assert( p->pBt->pPager!=0 );
|
||||||
assert( sqlite3BtreeHoldsMutex(p) );
|
|
||||||
return sqlite3PagerJournalname(p->pBt->pPager);
|
return sqlite3PagerJournalname(p->pBt->pPager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
** subsystem. See comments in the source code for a detailed description
|
** subsystem. See comments in the source code for a detailed description
|
||||||
** of what each interface routine does.
|
** of what each interface routine does.
|
||||||
**
|
**
|
||||||
** @(#) $Id: btree.h,v 1.90 2007/08/29 04:00:58 drh Exp $
|
** @(#) $Id: btree.h,v 1.91 2007/08/29 17:43:20 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _BTREE_H_
|
#ifndef _BTREE_H_
|
||||||
#define _BTREE_H_
|
#define _BTREE_H_
|
||||||
@ -176,6 +176,8 @@ int sqlite3BtreePageDump(Btree*, int, int recursive);
|
|||||||
void sqlite3BtreeEnter(Btree*);
|
void sqlite3BtreeEnter(Btree*);
|
||||||
void sqlite3BtreeLeave(Btree*);
|
void sqlite3BtreeLeave(Btree*);
|
||||||
int sqlite3BtreeHoldsMutex(Btree*);
|
int sqlite3BtreeHoldsMutex(Btree*);
|
||||||
|
void sqlite3BtreeEnterCursor(BtCursor*);
|
||||||
|
void sqlite3BtreeLeaveCursor(BtCursor*);
|
||||||
void sqlite3BtreeEnterAll(sqlite3*);
|
void sqlite3BtreeEnterAll(sqlite3*);
|
||||||
void sqlite3BtreeLeaveAll(sqlite3*);
|
void sqlite3BtreeLeaveAll(sqlite3*);
|
||||||
int sqlite3BtreeHoldsAllMutexes(sqlite3*);
|
int sqlite3BtreeHoldsAllMutexes(sqlite3*);
|
||||||
@ -186,6 +188,8 @@ int sqlite3BtreePageDump(Btree*, int, int recursive);
|
|||||||
# define sqlite3BtreeEnter(X)
|
# define sqlite3BtreeEnter(X)
|
||||||
# define sqlite3BtreeLeave(X)
|
# define sqlite3BtreeLeave(X)
|
||||||
# define sqlite3BtreeHoldsMutex(X) 1
|
# define sqlite3BtreeHoldsMutex(X) 1
|
||||||
|
# define sqlite3BtreeEnterCursor(X)
|
||||||
|
# define sqlite3BtreeLeaveCursor(X)
|
||||||
# define sqlite3BtreeEnterAll(X)
|
# define sqlite3BtreeEnterAll(X)
|
||||||
# define sqlite3BtreeLeaveAll(X)
|
# define sqlite3BtreeLeaveAll(X)
|
||||||
# define sqlite3BtreeHoldsAllMutexes(X) 1
|
# define sqlite3BtreeHoldsAllMutexes(X) 1
|
||||||
|
94
src/test3.c
94
src/test3.c
@ -13,7 +13,7 @@
|
|||||||
** is not included in the SQLite library. It is used for automated
|
** is not included in the SQLite library. It is used for automated
|
||||||
** testing of the SQLite library.
|
** testing of the SQLite library.
|
||||||
**
|
**
|
||||||
** $Id: test3.c,v 1.83 2007/08/29 12:31:28 danielk1977 Exp $
|
** $Id: test3.c,v 1.84 2007/08/29 17:43:20 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include "btreeInt.h"
|
#include "btreeInt.h"
|
||||||
@ -146,7 +146,9 @@ static int btree_begin_transaction(
|
|||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
pBt = sqlite3TextToPtr(argv[1]);
|
pBt = sqlite3TextToPtr(argv[1]);
|
||||||
|
sqlite3BtreeEnter(pBt);
|
||||||
rc = sqlite3BtreeBeginTrans(pBt, 1);
|
rc = sqlite3BtreeBeginTrans(pBt, 1);
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -173,7 +175,9 @@ static int btree_rollback(
|
|||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
pBt = sqlite3TextToPtr(argv[1]);
|
pBt = sqlite3TextToPtr(argv[1]);
|
||||||
|
sqlite3BtreeEnter(pBt);
|
||||||
rc = sqlite3BtreeRollback(pBt);
|
rc = sqlite3BtreeRollback(pBt);
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -200,7 +204,9 @@ static int btree_commit(
|
|||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
pBt = sqlite3TextToPtr(argv[1]);
|
pBt = sqlite3TextToPtr(argv[1]);
|
||||||
|
sqlite3BtreeEnter(pBt);
|
||||||
rc = sqlite3BtreeCommit(pBt);
|
rc = sqlite3BtreeCommit(pBt);
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -227,7 +233,9 @@ static int btree_begin_statement(
|
|||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
pBt = sqlite3TextToPtr(argv[1]);
|
pBt = sqlite3TextToPtr(argv[1]);
|
||||||
|
sqlite3BtreeEnter(pBt);
|
||||||
rc = sqlite3BtreeBeginStmt(pBt);
|
rc = sqlite3BtreeBeginStmt(pBt);
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -254,7 +262,9 @@ static int btree_rollback_statement(
|
|||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
pBt = sqlite3TextToPtr(argv[1]);
|
pBt = sqlite3TextToPtr(argv[1]);
|
||||||
|
sqlite3BtreeEnter(pBt);
|
||||||
rc = sqlite3BtreeRollbackStmt(pBt);
|
rc = sqlite3BtreeRollbackStmt(pBt);
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -281,7 +291,9 @@ static int btree_commit_statement(
|
|||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
pBt = sqlite3TextToPtr(argv[1]);
|
pBt = sqlite3TextToPtr(argv[1]);
|
||||||
|
sqlite3BtreeEnter(pBt);
|
||||||
rc = sqlite3BtreeCommitStmt(pBt);
|
rc = sqlite3BtreeCommitStmt(pBt);
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -310,7 +322,9 @@ static int btree_create_table(
|
|||||||
}
|
}
|
||||||
pBt = sqlite3TextToPtr(argv[1]);
|
pBt = sqlite3TextToPtr(argv[1]);
|
||||||
if( Tcl_GetInt(interp, argv[2], &flags) ) return TCL_ERROR;
|
if( Tcl_GetInt(interp, argv[2], &flags) ) return TCL_ERROR;
|
||||||
|
sqlite3BtreeEnter(pBt);
|
||||||
rc = sqlite3BtreeCreateTable(pBt, &iTable, flags);
|
rc = sqlite3BtreeCreateTable(pBt, &iTable, flags);
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -342,7 +356,9 @@ static int btree_drop_table(
|
|||||||
}
|
}
|
||||||
pBt = sqlite3TextToPtr(argv[1]);
|
pBt = sqlite3TextToPtr(argv[1]);
|
||||||
if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
|
if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
|
||||||
|
sqlite3BtreeEnter(pBt);
|
||||||
rc = sqlite3BtreeDropTable(pBt, iTable, ¬Used1);
|
rc = sqlite3BtreeDropTable(pBt, iTable, ¬Used1);
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -371,7 +387,9 @@ static int btree_clear_table(
|
|||||||
}
|
}
|
||||||
pBt = sqlite3TextToPtr(argv[1]);
|
pBt = sqlite3TextToPtr(argv[1]);
|
||||||
if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
|
if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
|
||||||
|
sqlite3BtreeEnter(pBt);
|
||||||
rc = sqlite3BtreeClearTable(pBt, iTable);
|
rc = sqlite3BtreeClearTable(pBt, iTable);
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -402,7 +420,9 @@ static int btree_get_meta(
|
|||||||
for(i=0; i<SQLITE_N_BTREE_META; i++){
|
for(i=0; i<SQLITE_N_BTREE_META; i++){
|
||||||
char zBuf[30];
|
char zBuf[30];
|
||||||
unsigned int v;
|
unsigned int v;
|
||||||
|
sqlite3BtreeEnter(pBt);
|
||||||
rc = sqlite3BtreeGetMeta(pBt, i, &v);
|
rc = sqlite3BtreeGetMeta(pBt, i, &v);
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -441,7 +461,9 @@ static int btree_update_meta(
|
|||||||
if( Tcl_GetInt(interp, argv[i+2], &aMeta[i]) ) return TCL_ERROR;
|
if( Tcl_GetInt(interp, argv[i+2], &aMeta[i]) ) return TCL_ERROR;
|
||||||
}
|
}
|
||||||
for(i=1; i<SQLITE_N_BTREE_META; i++){
|
for(i=1; i<SQLITE_N_BTREE_META; i++){
|
||||||
|
sqlite3BtreeEnter(pBt);
|
||||||
rc = sqlite3BtreeUpdateMeta(pBt, i, aMeta[i]);
|
rc = sqlite3BtreeUpdateMeta(pBt, i, aMeta[i]);
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -472,7 +494,9 @@ static int btree_page_dump(
|
|||||||
}
|
}
|
||||||
pBt = sqlite3TextToPtr(argv[1]);
|
pBt = sqlite3TextToPtr(argv[1]);
|
||||||
if( Tcl_GetInt(interp, argv[2], &iPage) ) return TCL_ERROR;
|
if( Tcl_GetInt(interp, argv[2], &iPage) ) return TCL_ERROR;
|
||||||
|
sqlite3BtreeEnter(pBt);
|
||||||
rc = sqlite3BtreePageDump(pBt, iPage, 0);
|
rc = sqlite3BtreePageDump(pBt, iPage, 0);
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -502,7 +526,9 @@ static int btree_tree_dump(
|
|||||||
}
|
}
|
||||||
pBt = sqlite3TextToPtr(argv[1]);
|
pBt = sqlite3TextToPtr(argv[1]);
|
||||||
if( Tcl_GetInt(interp, argv[2], &iPage) ) return TCL_ERROR;
|
if( Tcl_GetInt(interp, argv[2], &iPage) ) return TCL_ERROR;
|
||||||
|
sqlite3BtreeEnter(pBt);
|
||||||
rc = sqlite3BtreePageDump(pBt, iPage, 1);
|
rc = sqlite3BtreePageDump(pBt, iPage, 1);
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -531,7 +557,6 @@ static int btree_pager_stats(
|
|||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
pBt = sqlite3TextToPtr(argv[1]);
|
pBt = sqlite3TextToPtr(argv[1]);
|
||||||
sqlite3_mutex_enter(pBt->pSqlite->mutex);
|
|
||||||
sqlite3BtreeEnter(pBt);
|
sqlite3BtreeEnter(pBt);
|
||||||
a = sqlite3PagerStats(sqlite3BtreePager(pBt));
|
a = sqlite3PagerStats(sqlite3BtreePager(pBt));
|
||||||
for(i=0; i<11; i++){
|
for(i=0; i<11; i++){
|
||||||
@ -545,7 +570,6 @@ static int btree_pager_stats(
|
|||||||
Tcl_AppendElement(interp, zBuf);
|
Tcl_AppendElement(interp, zBuf);
|
||||||
}
|
}
|
||||||
sqlite3BtreeLeave(pBt);
|
sqlite3BtreeLeave(pBt);
|
||||||
sqlite3_mutex_leave(pBt->pSqlite->mutex);
|
|
||||||
return TCL_OK;
|
return TCL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -569,7 +593,9 @@ static int btree_pager_ref_dump(
|
|||||||
}
|
}
|
||||||
pBt = sqlite3TextToPtr(argv[1]);
|
pBt = sqlite3TextToPtr(argv[1]);
|
||||||
#ifdef SQLITE_DEBUG
|
#ifdef SQLITE_DEBUG
|
||||||
|
sqlite3BtreeEnter(pBt);
|
||||||
sqlite3PagerRefdump(sqlite3BtreePager(pBt));
|
sqlite3PagerRefdump(sqlite3BtreePager(pBt));
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
#endif
|
#endif
|
||||||
return TCL_OK;
|
return TCL_OK;
|
||||||
}
|
}
|
||||||
@ -606,7 +632,9 @@ static int btree_integrity_check(
|
|||||||
if( Tcl_GetInt(interp, argv[i+2], &aRoot[i]) ) return TCL_ERROR;
|
if( Tcl_GetInt(interp, argv[i+2], &aRoot[i]) ) return TCL_ERROR;
|
||||||
}
|
}
|
||||||
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
|
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
|
||||||
|
sqlite3BtreeEnter(pBt);
|
||||||
zResult = sqlite3BtreeIntegrityCheck(pBt, aRoot, nRoot, 10000, &nErr);
|
zResult = sqlite3BtreeIntegrityCheck(pBt, aRoot, nRoot, 10000, &nErr);
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
#else
|
#else
|
||||||
zResult = 0;
|
zResult = 0;
|
||||||
#endif
|
#endif
|
||||||
@ -637,7 +665,9 @@ static int btree_cursor_list(
|
|||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
pBt = sqlite3TextToPtr(argv[1]);
|
pBt = sqlite3TextToPtr(argv[1]);
|
||||||
|
sqlite3BtreeEnter(pBt);
|
||||||
sqlite3BtreeCursorList(pBt);
|
sqlite3BtreeCursorList(pBt);
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -667,7 +697,9 @@ static int btree_cursor(
|
|||||||
pBt = sqlite3TextToPtr(argv[1]);
|
pBt = sqlite3TextToPtr(argv[1]);
|
||||||
if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
|
if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
|
||||||
if( Tcl_GetBoolean(interp, argv[3], &wrFlag) ) return TCL_ERROR;
|
if( Tcl_GetBoolean(interp, argv[3], &wrFlag) ) return TCL_ERROR;
|
||||||
|
sqlite3BtreeEnter(pBt);
|
||||||
rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, 0, &pCur);
|
rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, 0, &pCur);
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
if( rc ){
|
if( rc ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -689,6 +721,7 @@ static int btree_close_cursor(
|
|||||||
const char **argv /* Text of each argument */
|
const char **argv /* Text of each argument */
|
||||||
){
|
){
|
||||||
BtCursor *pCur;
|
BtCursor *pCur;
|
||||||
|
Btree *pBt;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if( argc!=2 ){
|
if( argc!=2 ){
|
||||||
@ -697,7 +730,10 @@ static int btree_close_cursor(
|
|||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
pCur = sqlite3TextToPtr(argv[1]);
|
pCur = sqlite3TextToPtr(argv[1]);
|
||||||
|
pBt = pCur->pBtree;
|
||||||
|
sqlite3BtreeEnter(pBt);
|
||||||
rc = sqlite3BtreeCloseCursor(pCur);
|
rc = sqlite3BtreeCloseCursor(pCur);
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
if( rc ){
|
if( rc ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -727,13 +763,18 @@ static int btree_move_to(
|
|||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
pCur = sqlite3TextToPtr(argv[1]);
|
pCur = sqlite3TextToPtr(argv[1]);
|
||||||
|
sqlite3BtreeEnter(pCur->pBtree);
|
||||||
if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){
|
if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){
|
||||||
int iKey;
|
int iKey;
|
||||||
if( Tcl_GetInt(interp, argv[2], &iKey) ) return TCL_ERROR;
|
if( Tcl_GetInt(interp, argv[2], &iKey) ){
|
||||||
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
|
return TCL_ERROR;
|
||||||
|
}
|
||||||
rc = sqlite3BtreeMoveto(pCur, 0, iKey, 0, &res);
|
rc = sqlite3BtreeMoveto(pCur, 0, iKey, 0, &res);
|
||||||
}else{
|
}else{
|
||||||
rc = sqlite3BtreeMoveto(pCur, argv[2], strlen(argv[2]), 0, &res);
|
rc = sqlite3BtreeMoveto(pCur, argv[2], strlen(argv[2]), 0, &res);
|
||||||
}
|
}
|
||||||
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
if( rc ){
|
if( rc ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -765,7 +806,9 @@ static int btree_delete(
|
|||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
pCur = sqlite3TextToPtr(argv[1]);
|
pCur = sqlite3TextToPtr(argv[1]);
|
||||||
|
sqlite3BtreeEnter(pCur->pBtree);
|
||||||
rc = sqlite3BtreeDelete(pCur);
|
rc = sqlite3BtreeDelete(pCur);
|
||||||
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
if( rc ){
|
if( rc ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -799,11 +842,15 @@ static int btree_insert(
|
|||||||
}else{
|
}else{
|
||||||
nZero = 0;
|
nZero = 0;
|
||||||
}
|
}
|
||||||
|
sqlite3BtreeEnter(pCur->pBtree);
|
||||||
if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){
|
if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){
|
||||||
i64 iKey;
|
i64 iKey;
|
||||||
int len;
|
int len;
|
||||||
unsigned char *pBuf;
|
unsigned char *pBuf;
|
||||||
if( Tcl_GetWideIntFromObj(interp, objv[2], &iKey) ) return TCL_ERROR;
|
if( Tcl_GetWideIntFromObj(interp, objv[2], &iKey) ){
|
||||||
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
|
return TCL_ERROR;
|
||||||
|
}
|
||||||
pBuf = Tcl_GetByteArrayFromObj(objv[3], &len);
|
pBuf = Tcl_GetByteArrayFromObj(objv[3], &len);
|
||||||
rc = sqlite3BtreeInsert(pCur, 0, iKey, pBuf, len, nZero, 0);
|
rc = sqlite3BtreeInsert(pCur, 0, iKey, pBuf, len, nZero, 0);
|
||||||
}else{
|
}else{
|
||||||
@ -815,6 +862,7 @@ static int btree_insert(
|
|||||||
pDBuf = Tcl_GetByteArrayFromObj(objv[3], &dlen);
|
pDBuf = Tcl_GetByteArrayFromObj(objv[3], &dlen);
|
||||||
rc = sqlite3BtreeInsert(pCur, pKBuf, keylen, pDBuf, dlen, nZero, 0);
|
rc = sqlite3BtreeInsert(pCur, pKBuf, keylen, pDBuf, dlen, nZero, 0);
|
||||||
}
|
}
|
||||||
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
if( rc ){
|
if( rc ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -846,7 +894,9 @@ static int btree_next(
|
|||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
pCur = sqlite3TextToPtr(argv[1]);
|
pCur = sqlite3TextToPtr(argv[1]);
|
||||||
|
sqlite3BtreeEnter(pCur->pBtree);
|
||||||
rc = sqlite3BtreeNext(pCur, &res);
|
rc = sqlite3BtreeNext(pCur, &res);
|
||||||
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
if( rc ){
|
if( rc ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -880,7 +930,9 @@ static int btree_prev(
|
|||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
pCur = sqlite3TextToPtr(argv[1]);
|
pCur = sqlite3TextToPtr(argv[1]);
|
||||||
|
sqlite3BtreeEnter(pCur->pBtree);
|
||||||
rc = sqlite3BtreePrevious(pCur, &res);
|
rc = sqlite3BtreePrevious(pCur, &res);
|
||||||
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
if( rc ){
|
if( rc ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -913,7 +965,9 @@ static int btree_first(
|
|||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
pCur = sqlite3TextToPtr(argv[1]);
|
pCur = sqlite3TextToPtr(argv[1]);
|
||||||
|
sqlite3BtreeEnter(pCur->pBtree);
|
||||||
rc = sqlite3BtreeFirst(pCur, &res);
|
rc = sqlite3BtreeFirst(pCur, &res);
|
||||||
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
if( rc ){
|
if( rc ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -946,7 +1000,9 @@ static int btree_last(
|
|||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
pCur = sqlite3TextToPtr(argv[1]);
|
pCur = sqlite3TextToPtr(argv[1]);
|
||||||
|
sqlite3BtreeEnter(pCur->pBtree);
|
||||||
rc = sqlite3BtreeLast(pCur, &res);
|
rc = sqlite3BtreeLast(pCur, &res);
|
||||||
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
if( rc ){
|
if( rc ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
@ -969,6 +1025,7 @@ static int btree_eof(
|
|||||||
const char **argv /* Text of each argument */
|
const char **argv /* Text of each argument */
|
||||||
){
|
){
|
||||||
BtCursor *pCur;
|
BtCursor *pCur;
|
||||||
|
int rc;
|
||||||
char zBuf[50];
|
char zBuf[50];
|
||||||
|
|
||||||
if( argc!=2 ){
|
if( argc!=2 ){
|
||||||
@ -977,7 +1034,10 @@ static int btree_eof(
|
|||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
pCur = sqlite3TextToPtr(argv[1]);
|
pCur = sqlite3TextToPtr(argv[1]);
|
||||||
sqlite3_snprintf(sizeof(zBuf),zBuf, "%d", sqlite3BtreeEof(pCur));
|
sqlite3BtreeEnter(pCur->pBtree);
|
||||||
|
rc = sqlite3BtreeEof(pCur);
|
||||||
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
|
sqlite3_snprintf(sizeof(zBuf),zBuf, "%d", rc);
|
||||||
Tcl_AppendResult(interp, zBuf, 0);
|
Tcl_AppendResult(interp, zBuf, 0);
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
@ -1004,7 +1064,9 @@ static int btree_keysize(
|
|||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
pCur = sqlite3TextToPtr(argv[1]);
|
pCur = sqlite3TextToPtr(argv[1]);
|
||||||
|
sqlite3BtreeEnter(pCur->pBtree);
|
||||||
sqlite3BtreeKeySize(pCur, (i64*)&n);
|
sqlite3BtreeKeySize(pCur, (i64*)&n);
|
||||||
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
sqlite3_snprintf(sizeof(zBuf),zBuf, "%llu", n);
|
sqlite3_snprintf(sizeof(zBuf),zBuf, "%llu", n);
|
||||||
Tcl_AppendResult(interp, zBuf, 0);
|
Tcl_AppendResult(interp, zBuf, 0);
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
@ -1032,6 +1094,7 @@ static int btree_key(
|
|||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
pCur = sqlite3TextToPtr(argv[1]);
|
pCur = sqlite3TextToPtr(argv[1]);
|
||||||
|
sqlite3BtreeEnter(pCur->pBtree);
|
||||||
sqlite3BtreeKeySize(pCur, (i64*)&n);
|
sqlite3BtreeKeySize(pCur, (i64*)&n);
|
||||||
if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){
|
if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){
|
||||||
char zBuf2[60];
|
char zBuf2[60];
|
||||||
@ -1041,6 +1104,7 @@ static int btree_key(
|
|||||||
zBuf = sqlite3_malloc( n+1 );
|
zBuf = sqlite3_malloc( n+1 );
|
||||||
rc = sqlite3BtreeKey(pCur, 0, n, zBuf);
|
rc = sqlite3BtreeKey(pCur, 0, n, zBuf);
|
||||||
if( rc ){
|
if( rc ){
|
||||||
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
@ -1048,6 +1112,7 @@ static int btree_key(
|
|||||||
Tcl_AppendResult(interp, zBuf, 0);
|
Tcl_AppendResult(interp, zBuf, 0);
|
||||||
sqlite3_free(zBuf);
|
sqlite3_free(zBuf);
|
||||||
}
|
}
|
||||||
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1073,6 +1138,7 @@ static int btree_data(
|
|||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
pCur = sqlite3TextToPtr(argv[1]);
|
pCur = sqlite3TextToPtr(argv[1]);
|
||||||
|
sqlite3BtreeEnter(pCur->pBtree);
|
||||||
if( argc==2 ){
|
if( argc==2 ){
|
||||||
sqlite3BtreeDataSize(pCur, &n);
|
sqlite3BtreeDataSize(pCur, &n);
|
||||||
}else{
|
}else{
|
||||||
@ -1080,6 +1146,7 @@ static int btree_data(
|
|||||||
}
|
}
|
||||||
zBuf = sqlite3_malloc( n+1 );
|
zBuf = sqlite3_malloc( n+1 );
|
||||||
rc = sqlite3BtreeData(pCur, 0, n, zBuf);
|
rc = sqlite3BtreeData(pCur, 0, n, zBuf);
|
||||||
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
if( rc ){
|
if( rc ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
sqlite3_free(zBuf);
|
sqlite3_free(zBuf);
|
||||||
@ -1117,6 +1184,7 @@ static int btree_fetch_key(
|
|||||||
}
|
}
|
||||||
pCur = sqlite3TextToPtr(argv[1]);
|
pCur = sqlite3TextToPtr(argv[1]);
|
||||||
if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR;
|
if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR;
|
||||||
|
sqlite3BtreeEnter(pCur->pBtree);
|
||||||
sqlite3BtreeKeySize(pCur, (i64*)&nKey);
|
sqlite3BtreeKeySize(pCur, (i64*)&nKey);
|
||||||
zBuf = sqlite3BtreeKeyFetch(pCur, &amt);
|
zBuf = sqlite3BtreeKeyFetch(pCur, &amt);
|
||||||
if( zBuf && amt>=n ){
|
if( zBuf && amt>=n ){
|
||||||
@ -1126,6 +1194,7 @@ static int btree_fetch_key(
|
|||||||
zStatic[nKey] = 0;
|
zStatic[nKey] = 0;
|
||||||
Tcl_AppendResult(interp, zStatic, 0);
|
Tcl_AppendResult(interp, zStatic, 0);
|
||||||
}
|
}
|
||||||
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
return TCL_OK;
|
return TCL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1155,6 +1224,7 @@ static int btree_fetch_data(
|
|||||||
}
|
}
|
||||||
pCur = sqlite3TextToPtr(argv[1]);
|
pCur = sqlite3TextToPtr(argv[1]);
|
||||||
if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR;
|
if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR;
|
||||||
|
sqlite3BtreeEnter(pCur->pBtree);
|
||||||
sqlite3BtreeDataSize(pCur, &nData);
|
sqlite3BtreeDataSize(pCur, &nData);
|
||||||
zBuf = sqlite3BtreeDataFetch(pCur, &amt);
|
zBuf = sqlite3BtreeDataFetch(pCur, &amt);
|
||||||
if( zBuf && amt>=n ){
|
if( zBuf && amt>=n ){
|
||||||
@ -1164,6 +1234,7 @@ static int btree_fetch_data(
|
|||||||
zStatic[nData] = 0;
|
zStatic[nData] = 0;
|
||||||
Tcl_AppendResult(interp, zStatic, 0);
|
Tcl_AppendResult(interp, zStatic, 0);
|
||||||
}
|
}
|
||||||
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
return TCL_OK;
|
return TCL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1189,12 +1260,14 @@ static int btree_payload_size(
|
|||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
pCur = sqlite3TextToPtr(argv[1]);
|
pCur = sqlite3TextToPtr(argv[1]);
|
||||||
|
sqlite3BtreeEnter(pCur->pBtree);
|
||||||
if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){
|
if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){
|
||||||
n1 = 0;
|
n1 = 0;
|
||||||
}else{
|
}else{
|
||||||
sqlite3BtreeKeySize(pCur, (i64*)&n1);
|
sqlite3BtreeKeySize(pCur, (i64*)&n1);
|
||||||
}
|
}
|
||||||
sqlite3BtreeDataSize(pCur, (u32*)&n2);
|
sqlite3BtreeDataSize(pCur, (u32*)&n2);
|
||||||
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
sqlite3_snprintf(sizeof(zBuf),zBuf, "%d", (int)(n1+n2));
|
sqlite3_snprintf(sizeof(zBuf),zBuf, "%d", (int)(n1+n2));
|
||||||
Tcl_AppendResult(interp, zBuf, 0);
|
Tcl_AppendResult(interp, zBuf, 0);
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
@ -1242,9 +1315,11 @@ static int btree_cursor_info(
|
|||||||
}else{
|
}else{
|
||||||
up = 0;
|
up = 0;
|
||||||
}
|
}
|
||||||
|
sqlite3BtreeEnter(pCur->pBtree);
|
||||||
rc = sqlite3BtreeCursorInfo(pCur, aResult, up);
|
rc = sqlite3BtreeCursorInfo(pCur, aResult, up);
|
||||||
if( rc ){
|
if( rc ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
j = 0;
|
j = 0;
|
||||||
@ -1252,6 +1327,7 @@ static int btree_cursor_info(
|
|||||||
sqlite3_snprintf(40,&zBuf[j]," %d", aResult[i]);
|
sqlite3_snprintf(40,&zBuf[j]," %d", aResult[i]);
|
||||||
j += strlen(&zBuf[j]);
|
j += strlen(&zBuf[j]);
|
||||||
}
|
}
|
||||||
|
sqlite3BtreeLeave(pCur->pBtree);
|
||||||
Tcl_AppendResult(interp, &zBuf[1], 0);
|
Tcl_AppendResult(interp, &zBuf[1], 0);
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
@ -1300,10 +1376,12 @@ static int btree_ovfl_info(
|
|||||||
argv[1], 0);
|
argv[1], 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
|
sqlite3BtreeEnter(pBt);
|
||||||
pPager = sqlite3BtreePager(pBt);
|
pPager = sqlite3BtreePager(pBt);
|
||||||
rc = sqlite3BtreeCursorInfo(pCur, aResult, 0);
|
rc = sqlite3BtreeCursorInfo(pCur, aResult, 0);
|
||||||
if( rc ){
|
if( rc ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
dataSize = sqlite3BtreeGetPageSize(pBt) - sqlite3BtreeGetReserve(pBt);
|
dataSize = sqlite3BtreeGetPageSize(pBt) - sqlite3BtreeGetReserve(pBt);
|
||||||
@ -1318,12 +1396,14 @@ static int btree_ovfl_info(
|
|||||||
if( sqlite3PagerGet(pPager, pgno, &pDbPage)!=SQLITE_OK ){
|
if( sqlite3PagerGet(pPager, pgno, &pDbPage)!=SQLITE_OK ){
|
||||||
Tcl_DStringFree(&str);
|
Tcl_DStringFree(&str);
|
||||||
Tcl_AppendResult(interp, "unable to get page ", zElem, 0);
|
Tcl_AppendResult(interp, "unable to get page ", zElem, 0);
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
}
|
}
|
||||||
pPage = sqlite3PagerGetData(pDbPage);
|
pPage = sqlite3PagerGetData(pDbPage);
|
||||||
pgno = t4Get4byte((unsigned char*)pPage);
|
pgno = t4Get4byte((unsigned char*)pPage);
|
||||||
sqlite3PagerUnref(pDbPage);
|
sqlite3PagerUnref(pDbPage);
|
||||||
}
|
}
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
Tcl_DStringResult(interp, &str);
|
Tcl_DStringResult(interp, &str);
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
@ -1498,7 +1578,9 @@ static int btree_set_cache_size(
|
|||||||
if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR;
|
if( Tcl_GetInt(interp, argv[2], &nCache) ) return TCL_ERROR;
|
||||||
|
|
||||||
sqlite3_mutex_enter(pBt->pSqlite->mutex);
|
sqlite3_mutex_enter(pBt->pSqlite->mutex);
|
||||||
|
sqlite3BtreeEnter(pBt);
|
||||||
sqlite3BtreeSetCacheSize(pBt, nCache);
|
sqlite3BtreeSetCacheSize(pBt, nCache);
|
||||||
|
sqlite3BtreeLeave(pBt);
|
||||||
sqlite3_mutex_leave(pBt->pSqlite->mutex);
|
sqlite3_mutex_leave(pBt->pSqlite->mutex);
|
||||||
|
|
||||||
return TCL_OK;
|
return TCL_OK;
|
||||||
|
@ -936,7 +936,7 @@ void sqlite3VdbeMakeReady(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Close a cursor and release all the resources that cursor happens
|
** Close a VDBE cursor and release all the resources that cursor happens
|
||||||
** to hold.
|
** to hold.
|
||||||
*/
|
*/
|
||||||
void sqlite3VdbeFreeCursor(Vdbe *p, Cursor *pCx){
|
void sqlite3VdbeFreeCursor(Vdbe *p, Cursor *pCx){
|
||||||
@ -966,14 +966,16 @@ void sqlite3VdbeFreeCursor(Vdbe *p, Cursor *pCx){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Close all cursors
|
** Close all cursors except for VTab cursors that are currently
|
||||||
|
** in use.
|
||||||
*/
|
*/
|
||||||
static void closeAllCursors(Vdbe *p){
|
static void closeAllCursorsExceptActiveVtabs(Vdbe *p){
|
||||||
int i;
|
int i;
|
||||||
if( p->apCsr==0 ) return;
|
if( p->apCsr==0 ) return;
|
||||||
for(i=0; i<p->nCursor; i++){
|
for(i=0; i<p->nCursor; i++){
|
||||||
if( !p->inVtabMethod || (p->apCsr[i] && !p->apCsr[i]->pVtabCursor) ){
|
Cursor *pC = p->apCsr[i];
|
||||||
sqlite3VdbeFreeCursor(p, p->apCsr[i]);
|
if( pC && (!p->inVtabMethod || !pC->pVtabCursor) ){
|
||||||
|
sqlite3VdbeFreeCursor(p, pC);
|
||||||
p->apCsr[i] = 0;
|
p->apCsr[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -992,7 +994,7 @@ static void Cleanup(Vdbe *p){
|
|||||||
releaseMemArray(p->aStack, 1 + (p->pTos - p->aStack));
|
releaseMemArray(p->aStack, 1 + (p->pTos - p->aStack));
|
||||||
p->pTos = &p->aStack[-1];
|
p->pTos = &p->aStack[-1];
|
||||||
}
|
}
|
||||||
closeAllCursors(p);
|
closeAllCursorsExceptActiveVtabs(p);
|
||||||
releaseMemArray(p->aMem, p->nMem);
|
releaseMemArray(p->aMem, p->nMem);
|
||||||
sqlite3VdbeFifoClear(&p->sFifo);
|
sqlite3VdbeFifoClear(&p->sFifo);
|
||||||
if( p->contextStack ){
|
if( p->contextStack ){
|
||||||
@ -1311,7 +1313,7 @@ void sqlite3AbortOtherActiveVdbes(sqlite3 *db, Vdbe *pExcept){
|
|||||||
if( pOther==pExcept ) continue;
|
if( pOther==pExcept ) continue;
|
||||||
if( pOther->magic!=VDBE_MAGIC_RUN || pOther->pc<0 ) continue;
|
if( pOther->magic!=VDBE_MAGIC_RUN || pOther->pc<0 ) continue;
|
||||||
checkActiveVdbeCnt(db);
|
checkActiveVdbeCnt(db);
|
||||||
closeAllCursors(pOther);
|
closeAllCursorsExceptActiveVtabs(pOther);
|
||||||
checkActiveVdbeCnt(db);
|
checkActiveVdbeCnt(db);
|
||||||
pOther->aborted = 1;
|
pOther->aborted = 1;
|
||||||
}
|
}
|
||||||
@ -1323,13 +1325,14 @@ void sqlite3AbortOtherActiveVdbes(sqlite3 *db, Vdbe *pExcept){
|
|||||||
** changes. If a rollback is needed, then do the rollback.
|
** changes. If a rollback is needed, then do the rollback.
|
||||||
**
|
**
|
||||||
** This routine is the only way to move the state of a VM from
|
** This routine is the only way to move the state of a VM from
|
||||||
** SQLITE_MAGIC_RUN to SQLITE_MAGIC_HALT.
|
** SQLITE_MAGIC_RUN to SQLITE_MAGIC_HALT. It is harmless to
|
||||||
|
** call this on a VM that is in the SQLITE_MAGIC_HALT state.
|
||||||
**
|
**
|
||||||
** Return an error code. If the commit could not complete because of
|
** Return an error code. If the commit could not complete because of
|
||||||
** lock contention, return SQLITE_BUSY. If SQLITE_BUSY is returned, it
|
** lock contention, return SQLITE_BUSY. If SQLITE_BUSY is returned, it
|
||||||
** means the close did not happen and needs to be repeated.
|
** means the close did not happen and needs to be repeated.
|
||||||
*/
|
*/
|
||||||
static int sqlite3VdbeHaltLocked(Vdbe *p){
|
int sqlite3VdbeHalt(Vdbe *p){
|
||||||
sqlite3 *db = p->db;
|
sqlite3 *db = p->db;
|
||||||
int i;
|
int i;
|
||||||
int (*xFunc)(Btree *pBt) = 0; /* Function to call on each btree backend */
|
int (*xFunc)(Btree *pBt) = 0; /* Function to call on each btree backend */
|
||||||
@ -1366,20 +1369,19 @@ static int sqlite3VdbeHaltLocked(Vdbe *p){
|
|||||||
if( p->db->mallocFailed ){
|
if( p->db->mallocFailed ){
|
||||||
p->rc = SQLITE_NOMEM;
|
p->rc = SQLITE_NOMEM;
|
||||||
}
|
}
|
||||||
|
closeAllCursorsExceptActiveVtabs(p);
|
||||||
if( p->magic!=VDBE_MAGIC_RUN ){
|
if( p->magic!=VDBE_MAGIC_RUN ){
|
||||||
/* Already halted. Nothing to do. */
|
|
||||||
assert( p->magic==VDBE_MAGIC_HALT );
|
|
||||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
||||||
closeAllCursors(p);
|
|
||||||
#endif
|
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
closeAllCursors(p);
|
|
||||||
checkActiveVdbeCnt(db);
|
checkActiveVdbeCnt(db);
|
||||||
|
|
||||||
/* No commit or rollback needed if the program never started */
|
/* No commit or rollback needed if the program never started */
|
||||||
if( p->pc>=0 ){
|
if( p->pc>=0 ){
|
||||||
int mrc; /* Primary error code from p->rc */
|
int mrc; /* Primary error code from p->rc */
|
||||||
|
|
||||||
|
/* Lock all btrees used by the statement */
|
||||||
|
sqlite3BtreeMutexArrayEnter(&p->aMutex);
|
||||||
|
|
||||||
/* Check for one of the special errors - SQLITE_NOMEM or SQLITE_IOERR */
|
/* Check for one of the special errors - SQLITE_NOMEM or SQLITE_IOERR */
|
||||||
mrc = p->rc & 0xff;
|
mrc = p->rc & 0xff;
|
||||||
isSpecialError = (
|
isSpecialError = (
|
||||||
@ -1423,7 +1425,8 @@ static int sqlite3VdbeHaltLocked(Vdbe *p){
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* If the query was read-only, we need do no rollback at all. Otherwise,
|
/* If the query was read-only, we need do no rollback at all. Otherwise,
|
||||||
** proceed with the special handling.
|
** proceed with the special handling.
|
||||||
*/
|
*/
|
||||||
@ -1458,6 +1461,7 @@ static int sqlite3VdbeHaltLocked(Vdbe *p){
|
|||||||
*/
|
*/
|
||||||
int rc = vdbeCommit(db);
|
int rc = vdbeCommit(db);
|
||||||
if( rc==SQLITE_BUSY ){
|
if( rc==SQLITE_BUSY ){
|
||||||
|
sqlite3BtreeMutexArrayLeave(&p->aMutex);
|
||||||
return SQLITE_BUSY;
|
return SQLITE_BUSY;
|
||||||
}else if( rc!=SQLITE_OK ){
|
}else if( rc!=SQLITE_OK ){
|
||||||
p->rc = rc;
|
p->rc = rc;
|
||||||
@ -1520,6 +1524,9 @@ static int sqlite3VdbeHaltLocked(Vdbe *p){
|
|||||||
sqlite3ResetInternalSchema(db, 0);
|
sqlite3ResetInternalSchema(db, 0);
|
||||||
db->flags = (db->flags | SQLITE_InternChanges);
|
db->flags = (db->flags | SQLITE_InternChanges);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Release the locks */
|
||||||
|
sqlite3BtreeMutexArrayLeave(&p->aMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have successfully halted and closed the VM. Record this fact. */
|
/* We have successfully halted and closed the VM. Record this fact. */
|
||||||
@ -1528,16 +1535,13 @@ static int sqlite3VdbeHaltLocked(Vdbe *p){
|
|||||||
}
|
}
|
||||||
p->magic = VDBE_MAGIC_HALT;
|
p->magic = VDBE_MAGIC_HALT;
|
||||||
checkActiveVdbeCnt(db);
|
checkActiveVdbeCnt(db);
|
||||||
|
if( p->db->mallocFailed ){
|
||||||
|
p->rc = SQLITE_NOMEM;
|
||||||
|
}
|
||||||
|
checkActiveVdbeCnt(db);
|
||||||
|
|
||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
int sqlite3VdbeHalt(Vdbe *p){
|
|
||||||
int rc;
|
|
||||||
sqlite3BtreeMutexArrayEnter(&p->aMutex);
|
|
||||||
rc = sqlite3VdbeHaltLocked(p);
|
|
||||||
sqlite3BtreeMutexArrayLeave(&p->aMutex);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
**
|
**
|
||||||
** This file contains code used to implement incremental BLOB I/O.
|
** This file contains code used to implement incremental BLOB I/O.
|
||||||
**
|
**
|
||||||
** $Id: vdbeblob.c,v 1.14 2007/08/21 19:33:57 drh Exp $
|
** $Id: vdbeblob.c,v 1.15 2007/08/29 17:43:20 drh Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
@ -102,6 +102,7 @@ int sqlite3_blob_open(
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sqlite3BtreeEnterAll(db);
|
||||||
pTab = sqlite3LocateTable(&sParse, zTable, zDb);
|
pTab = sqlite3LocateTable(&sParse, zTable, zDb);
|
||||||
if( !pTab ){
|
if( !pTab ){
|
||||||
if( sParse.zErrMsg ){
|
if( sParse.zErrMsg ){
|
||||||
@ -110,6 +111,7 @@ int sqlite3_blob_open(
|
|||||||
sqlite3_free(sParse.zErrMsg);
|
sqlite3_free(sParse.zErrMsg);
|
||||||
rc = SQLITE_ERROR;
|
rc = SQLITE_ERROR;
|
||||||
sqlite3SafetyOff(db);
|
sqlite3SafetyOff(db);
|
||||||
|
sqlite3BtreeLeaveAll(db);
|
||||||
goto blob_open_out;
|
goto blob_open_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,6 +125,7 @@ int sqlite3_blob_open(
|
|||||||
sqlite3_snprintf(sizeof(zErr), zErr, "no such column: \"%s\"", zColumn);
|
sqlite3_snprintf(sizeof(zErr), zErr, "no such column: \"%s\"", zColumn);
|
||||||
rc = SQLITE_ERROR;
|
rc = SQLITE_ERROR;
|
||||||
sqlite3SafetyOff(db);
|
sqlite3SafetyOff(db);
|
||||||
|
sqlite3BtreeLeaveAll(db);
|
||||||
goto blob_open_out;
|
goto blob_open_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,6 +143,7 @@ int sqlite3_blob_open(
|
|||||||
"cannot open indexed column for writing");
|
"cannot open indexed column for writing");
|
||||||
rc = SQLITE_ERROR;
|
rc = SQLITE_ERROR;
|
||||||
sqlite3SafetyOff(db);
|
sqlite3SafetyOff(db);
|
||||||
|
sqlite3BtreeLeaveAll(db);
|
||||||
goto blob_open_out;
|
goto blob_open_out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -159,6 +163,9 @@ int sqlite3_blob_open(
|
|||||||
sqlite3VdbeChangeP1(v, 1, iDb);
|
sqlite3VdbeChangeP1(v, 1, iDb);
|
||||||
sqlite3VdbeChangeP2(v, 1, pTab->pSchema->schema_cookie);
|
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);
|
||||||
|
|
||||||
/* Configure the db number pushed onto the stack */
|
/* Configure the db number pushed onto the stack */
|
||||||
sqlite3VdbeChangeP1(v, 2, iDb);
|
sqlite3VdbeChangeP1(v, 2, iDb);
|
||||||
|
|
||||||
@ -180,7 +187,8 @@ int sqlite3_blob_open(
|
|||||||
sqlite3VdbeMakeReady(v, 1, 0, 1, 0);
|
sqlite3VdbeMakeReady(v, 1, 0, 1, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sqlite3BtreeLeaveAll(db);
|
||||||
rc = sqlite3SafetyOff(db);
|
rc = sqlite3SafetyOff(db);
|
||||||
if( rc!=SQLITE_OK || db->mallocFailed ){
|
if( rc!=SQLITE_OK || db->mallocFailed ){
|
||||||
goto blob_open_out;
|
goto blob_open_out;
|
||||||
@ -218,7 +226,9 @@ int sqlite3_blob_open(
|
|||||||
}
|
}
|
||||||
pBlob->flags = flags;
|
pBlob->flags = flags;
|
||||||
pBlob->pCsr = v->apCsr[0]->pCursor;
|
pBlob->pCsr = v->apCsr[0]->pCursor;
|
||||||
|
sqlite3BtreeEnterCursor(pBlob->pCsr);
|
||||||
sqlite3BtreeCacheOverflow(pBlob->pCsr);
|
sqlite3BtreeCacheOverflow(pBlob->pCsr);
|
||||||
|
sqlite3BtreeLeaveCursor(pBlob->pCsr);
|
||||||
pBlob->pStmt = (sqlite3_stmt *)v;
|
pBlob->pStmt = (sqlite3_stmt *)v;
|
||||||
pBlob->iOffset = v->apCsr[0]->aOffset[iCol];
|
pBlob->iOffset = v->apCsr[0]->aOffset[iCol];
|
||||||
pBlob->nByte = sqlite3VdbeSerialTypeLen(type);
|
pBlob->nByte = sqlite3VdbeSerialTypeLen(type);
|
||||||
@ -247,12 +257,9 @@ blob_open_out:
|
|||||||
*/
|
*/
|
||||||
int sqlite3_blob_close(sqlite3_blob *pBlob){
|
int sqlite3_blob_close(sqlite3_blob *pBlob){
|
||||||
Incrblob *p = (Incrblob *)pBlob;
|
Incrblob *p = (Incrblob *)pBlob;
|
||||||
sqlite3_mutex *mutex = p->db->mutex;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
sqlite3_mutex_enter(mutex);
|
|
||||||
rc = sqlite3_finalize(p->pStmt);
|
rc = sqlite3_finalize(p->pStmt);
|
||||||
sqlite3_mutex_leave(mutex);
|
|
||||||
sqlite3_free(p);
|
sqlite3_free(p);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@ -289,7 +296,9 @@ static int blobReadWrite(
|
|||||||
** returned, clean-up the statement handle.
|
** returned, clean-up the statement handle.
|
||||||
*/
|
*/
|
||||||
assert( db == v->db );
|
assert( db == v->db );
|
||||||
|
sqlite3BtreeEnterCursor(p->pCsr);
|
||||||
rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
|
rc = xCall(p->pCsr, iOffset+p->iOffset, n, z);
|
||||||
|
sqlite3BtreeLeaveCursor(p->pCsr);
|
||||||
if( rc==SQLITE_ABORT ){
|
if( rc==SQLITE_ABORT ){
|
||||||
sqlite3VdbeFinalize(v);
|
sqlite3VdbeFinalize(v);
|
||||||
p->pStmt = 0;
|
p->pStmt = 0;
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
# focus of this script is testing the ATTACH and DETACH commands
|
# focus of this script is testing the ATTACH and DETACH commands
|
||||||
# and related functionality.
|
# and related functionality.
|
||||||
#
|
#
|
||||||
# $Id: attach.test,v 1.44 2007/05/09 20:31:30 drh Exp $
|
# $Id: attach.test,v 1.45 2007/08/29 17:43:20 drh Exp $
|
||||||
#
|
#
|
||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
@ -53,6 +53,7 @@ do_test attach-1.4 {
|
|||||||
}
|
}
|
||||||
} {1 x 2 y}
|
} {1 x 2 y}
|
||||||
do_test attach-1.5 {
|
do_test attach-1.5 {
|
||||||
|
btree_breakpoint
|
||||||
execsql {
|
execsql {
|
||||||
DETACH DATABASE two;
|
DETACH DATABASE two;
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
|
Loading…
Reference in New Issue
Block a user