1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

Additional test cases with locking fixes. Also, make the code thread-safe. (CVS 262)

FossilOrigin-Name: bd7d6a64afa03cc64f6537f828d6c94975bf5f02
This commit is contained in:
drh
2001-09-23 19:46:51 +00:00
parent ecdc7530dd
commit 90bfcdace3
9 changed files with 188 additions and 104 deletions

View File

@ -1,5 +1,5 @@
C Fixes\sto\sthe\slocking\sand\srollback\sbehavior.\s(CVS\s261) C Additional\stest\scases\swith\slocking\sfixes.\s\sAlso,\smake\sthe\scode\sthread-safe.\s(CVS\s262)
D 2001-09-23T02:35:53 D 2001-09-23T19:46:52
F Makefile.in 18eea9a3486939fced70aa95b691be766c2c995d F Makefile.in 18eea9a3486939fced70aa95b691be766c2c995d
F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958 F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
F VERSION 6942aa44940d2972bd72f671a631060106e77f7e F VERSION 6942aa44940d2972bd72f671a631060106e77f7e
@ -10,7 +10,7 @@ F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac
F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6 F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6
F src/btree.c da9b60a0b94daac0b7a231f42cb79961bf06531d F src/btree.c da9b60a0b94daac0b7a231f42cb79961bf06531d
F src/btree.h 5e5531869e53623aad5b32c22249c5743039251e F src/btree.h 5e5531869e53623aad5b32c22249c5743039251e
F src/build.c 8dbdcce4b9b9cb15b0d1a7a535af622cccba6f6b F src/build.c 17ba9b8594c0d491c0c4b105f63da5764620a8ce
F src/delete.c 81002d889aae874decf507627207c5d1b3599dc2 F src/delete.c 81002d889aae874decf507627207c5d1b3599dc2
F src/expr.c 343a515a4abaf60e9e26c7412aa8c43fd3eae97d F src/expr.c 343a515a4abaf60e9e26c7412aa8c43fd3eae97d
F src/hash.c bf36fb4cba114015123b0050f137d2c4553778a1 F src/hash.c bf36fb4cba114015123b0050f137d2c4553778a1
@ -18,18 +18,18 @@ F src/hash.h 5f6e7c04c46ed015ab4e01797c2049b4af5b006d
F src/insert.c 061e531d19869e26ba9202c6d069385237b4c102 F src/insert.c 061e531d19869e26ba9202c6d069385237b4c102
F src/main.c 49af06b7327c8b23b9331ce80b7e4bc9536ed2e1 F src/main.c 49af06b7327c8b23b9331ce80b7e4bc9536ed2e1
F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c
F src/os.c faf9f484f3261c7650021cae79294338491f2cfb F src/os.c 45376582c41dc8829330816d56b8e9e6cd1b7972
F src/os.h 0f478e2fef5ec1612f94b59b163d4807d4c77d6d F src/os.h 0f478e2fef5ec1612f94b59b163d4807d4c77d6d
F src/pager.c 0fe02b63a89d8eebb42ad30529d0c7cc918ecb94 F src/pager.c 0fe02b63a89d8eebb42ad30529d0c7cc918ecb94
F src/pager.h a0d4c5ae271914aa07b62aee0707997d6932b6ca F src/pager.h a0d4c5ae271914aa07b62aee0707997d6932b6ca
F src/parse.y 2bcf47bb8e6afd8bc10aebd555fa07b73905bee4 F src/parse.y 2bcf47bb8e6afd8bc10aebd555fa07b73905bee4
F src/printf.c b1e22a47be8cdf707815647239991e08e8cb69f9 F src/printf.c b1e22a47be8cdf707815647239991e08e8cb69f9
F src/random.c b6a57e85288470b013ad584a8813e893b60e62fe F src/random.c 708a23f69f40d6f2ae5ce1a04e6a4055d4a6ecec
F src/select.c 7d90a6464906419fde96c0707a4cf4f3280db318 F src/select.c 7d90a6464906419fde96c0707a4cf4f3280db318
F src/shell.c 8e573138074e0b9526fca59b3eac22bdf18ecc03 F src/shell.c 8e573138074e0b9526fca59b3eac22bdf18ecc03
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
F src/sqlite.h.in dbe7a1b1e1ab9bfce1a6983cfa6f53c5c2499305 F src/sqlite.h.in dbe7a1b1e1ab9bfce1a6983cfa6f53c5c2499305
F src/sqliteInt.h ae90beff6acc510bf98c80908d86b0830933e507 F src/sqliteInt.h 6bcdcfbc2b2ec7bb6ec96b3a31f4a0c74ee14c4f
F src/table.c abd0adbe0fee39d995287b3bcccd908d174dfcac F src/table.c abd0adbe0fee39d995287b3bcccd908d174dfcac
F src/tclsqlite.c 04a35d04f06046acc3944121dc6c36717f7f36d5 F src/tclsqlite.c 04a35d04f06046acc3944121dc6c36717f7f36d5
F src/test1.c 3892caa5372789a6d17329dd595724e1f06cb6de F src/test1.c 3892caa5372789a6d17329dd595724e1f06cb6de
@ -38,7 +38,7 @@ F src/test3.c 4a0d7b882fdae731dbb759f512ad867122452f96
F src/tokenize.c 2ab07b85fde38d8fa2b4e73417b93e94f9cf8f5f F src/tokenize.c 2ab07b85fde38d8fa2b4e73417b93e94f9cf8f5f
F src/update.c 8de22957017e17c5e751ba71c4ea76c60f93aa2f F src/update.c 8de22957017e17c5e751ba71c4ea76c60f93aa2f
F src/util.c 9c888445c1fd7896dab38fa62efc532f2364010a F src/util.c 9c888445c1fd7896dab38fa62efc532f2364010a
F src/vdbe.c 7132265f449b4bb159e77cc548e515b7b8b9398a F src/vdbe.c b36ba796eca369d3dbd9272b277d520af03b9ae4
F src/vdbe.h dc1d441494ba560a1ff464e1c56beb8ca03844fc F src/vdbe.h dc1d441494ba560a1ff464e1c56beb8ca03844fc
F src/where.c cce952b6a2459ac2296e3432876a4252d2fe3b87 F src/where.c cce952b6a2459ac2296e3432876a4252d2fe3b87
F test/all.test a2320eb40b462f25bd3e33115b1cabf3791450dd F test/all.test a2320eb40b462f25bd3e33115b1cabf3791450dd
@ -52,7 +52,7 @@ F test/in.test 9323681388be301dc73f370b4cd62c5a33f79d1e
F test/index.test e43e952b482c2afe938f1f31b71e2b33d43893a9 F test/index.test e43e952b482c2afe938f1f31b71e2b33d43893a9
F test/insert.test a5c122aa726f1cef6f07d6767e8fd6f220994c11 F test/insert.test a5c122aa726f1cef6f07d6767e8fd6f220994c11
F test/insert2.test 252d7130d8cc20f649b31a4f503cd87e660abda8 F test/insert2.test 252d7130d8cc20f649b31a4f503cd87e660abda8
F test/lock.test 3cef6b302ae0826755ccb226fe444be42fe5d391 F test/lock.test a9641cdc282214563a2fb0233735b09cc2fdd8f2
F test/main.test 085ece17913a487caacbc0a392638c958c83a75d F test/main.test 085ece17913a487caacbc0a392638c958c83a75d
F test/malloc.test f1400a8d002eb96f1ca0a34abe56d2ab3e324740 F test/malloc.test f1400a8d002eb96f1ca0a34abe56d2ab3e324740
F test/misc1.test 50a5ca3481fc1f3cd6b978bcd6ed04c06f26a1e6 F test/misc1.test 50a5ca3481fc1f3cd6b978bcd6ed04c06f26a1e6
@ -87,7 +87,7 @@ F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf
F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4 F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4
F www/arch.tcl c1891efdc00cd76eec72bdbf8b446195902932a3 F www/arch.tcl c1891efdc00cd76eec72bdbf8b446195902932a3
F www/c_interface.tcl 52ae81c89bf906b358e04857bd3f76b1a7f61c1b F www/c_interface.tcl 52ae81c89bf906b358e04857bd3f76b1a7f61c1b
F www/changes.tcl bf028a66d00a15a6c6a67a11c89c63bb60d5292b F www/changes.tcl 7e5a04a59a417a9fd4c94ce38543adbca0e01937
F www/crosscompile.tcl c99efacb3aefaa550c6e80d91b240f55eb9fd33e F www/crosscompile.tcl c99efacb3aefaa550c6e80d91b240f55eb9fd33e
F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
F www/index.tcl d65c6eaf66afac5b8a4b0394f691be02a2c3be20 F www/index.tcl d65c6eaf66afac5b8a4b0394f691be02a2c3be20
@ -97,7 +97,7 @@ F www/opcode.tcl 60222aeb57a7855b2582c374b8753cb5bb53c4ab
F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f
F www/tclsqlite.tcl 13d50723f583888fc80ae1a38247c0ab415066fa F www/tclsqlite.tcl 13d50723f583888fc80ae1a38247c0ab415066fa
F www/vdbe.tcl 0c8aaa529dd216ccbf7daaabd80985e413d5f9ad F www/vdbe.tcl 0c8aaa529dd216ccbf7daaabd80985e413d5f9ad
P 9114420dd01d92cc8890046500a8806a297a4e65 P 337b3d3b2a903328d9744c111979909a284b8348
R befae190f48e6ee61c8ee654bf44939d R e078b3cf3fce42ca9d1080ff6c3cabcb
U drh U drh
Z 7d651cd9fc4593916e1eb971a253a3a2 Z f237ccfe6f0011261f7c6612613f9d4f

View File

@ -1 +1 @@
337b3d3b2a903328d9744c111979909a284b8348 bd7d6a64afa03cc64f6537f828d6c94975bf5f02

View File

@ -25,7 +25,7 @@
** ROLLBACK ** ROLLBACK
** PRAGMA ** PRAGMA
** **
** $Id: build.c,v 1.39 2001/09/23 02:35:53 drh Exp $ ** $Id: build.c,v 1.40 2001/09/23 19:46:52 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@ -445,7 +445,7 @@ void sqliteAddDefaultValue(Parse *pParse, Token *pVal, int minusFlag){
*/ */
static void changeCookie(sqlite *db){ static void changeCookie(sqlite *db){
if( db->next_cookie==db->schema_cookie ){ if( db->next_cookie==db->schema_cookie ){
db->next_cookie = db->schema_cookie + sqliteRandomByte() + 1; db->next_cookie = db->schema_cookie + sqliteRandomByte(db) + 1;
db->flags |= SQLITE_InternChanges; db->flags |= SQLITE_InternChanges;
} }
} }

View File

@ -246,7 +246,7 @@ int sqliteOsTempFileName(char *zBuf){
sprintf(zBuf, "%s/sqlite_", zDir); sprintf(zBuf, "%s/sqlite_", zDir);
j = strlen(zBuf); j = strlen(zBuf);
for(i=0; i<15; i++){ for(i=0; i<15; i++){
int n = sqliteRandomByte() % sizeof(zChars); int n = rand() % sizeof(zChars);
zBuf[j++] = zChars[n]; zBuf[j++] = zChars[n];
} }
zBuf[j] = 0; zBuf[j] = 0;
@ -264,7 +264,7 @@ int sqliteOsTempFileName(char *zBuf){
sprintf(zBuf, "%s/sqlite_", zTempPath); sprintf(zBuf, "%s/sqlite_", zTempPath);
j = strlen(zBuf); j = strlen(zBuf);
for(i=0; i<15; i++){ for(i=0; i<15; i++){
int n = sqliteRandomByte() % sizeof(zChars); int n = rand() % sizeof(zChars);
zBuf[j++] = zChars[n]; zBuf[j++] = zChars[n];
} }
zBuf[j] = 0; zBuf[j] = 0;
@ -429,19 +429,23 @@ int sqliteOsUnlock(OsFile id){
** Get information to seed the random number generator. ** Get information to seed the random number generator.
*/ */
int sqliteOsRandomSeed(char *zBuf){ int sqliteOsRandomSeed(char *zBuf){
static int once = 1;
#if OS_UNIX #if OS_UNIX
int pid; int pid;
time((time_t*)zBuf); time((time_t*)zBuf);
zBuf += sizeof(time_t);
pid = getpid(); pid = getpid();
memcpy(zBuf, &pid, sizeof(pid)); memcpy(&zBuf[sizeof(time_t)], &pid, sizeof(pid));
zBuf += pid;
return SQLITE_OK;
#endif #endif
#if OS_WIN #if OS_WIN
GetSystemTime((LPSYSTEMTIME)zBuf); GetSystemTime((LPSYSTEMTIME)zBuf);
#endif
if( once ){
int seed;
memcpy(&seed, zBuf, sizeof(seed));
srand(seed);
once = 0;
}
return SQLITE_OK; return SQLITE_OK;
#endif
} }
/* /*

View File

@ -15,7 +15,7 @@
** Random numbers are used by some of the database backends in order ** Random numbers are used by some of the database backends in order
** to generate random integer keys for tables or random filenames. ** to generate random integer keys for tables or random filenames.
** **
** $Id: random.c,v 1.6 2001/09/19 13:22:40 drh Exp $ ** $Id: random.c,v 1.7 2001/09/23 19:46:52 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include "os.h" #include "os.h"
@ -23,103 +23,58 @@
/* /*
** Get a single 8-bit random value from the RC4 PRNG. ** Get a single 8-bit random value from the RC4 PRNG.
*/ */
int sqliteRandomByte(void){ int sqliteRandomByte(sqlite *db){
int t; int t;
/* /* Initialize the state of the random number generator once,
** The following structure holds the current state of the RC4 algorithm. ** the first time this routine is called. The seed value does
** We use RC4 as a random number generator. Each call to RC4 gives ** not need to contain a lot of randomness since we are not
** a random 8-bit number. ** trying to do secure encryption or anything like that...
** **
** Nothing in this file or anywhere else in SQLite does any kind of ** Nothing in this file or anywhere else in SQLite does any kind of
** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random ** encryption. The RC4 algorithm is being used as a PRNG (pseudo-random
** number generator) not as an encryption device. ** number generator) not as an encryption device.
*/ */
static struct { if( !db->prng.isInit ){
int isInit;
int i, j;
int s[256];
} prng_state;
/* Initialize the state of the random number generator once,
** the first time this routine is called. The seed value does
** not need to contain a lot of randomness since we are not
** trying to do secure encryption or anything like that...
*/
if( !prng_state.isInit ){
int i; int i;
static char seed[] = " sqlite random seed abcdefghijklmnop";
char k[256]; char k[256];
sqliteOsRandomSeed(seed); db->prng.j = 0;
prng_state.j = 0; db->prng.i = 0;
prng_state.i = 0; sqliteOsRandomSeed(k);
for(i=0; i<256; i++){ for(i=0; i<256; i++){
prng_state.s[i] = i; db->prng.s[i] = i;
k[i] = seed[i%sizeof(seed)];
} }
for(i=0; i<256; i++){ for(i=0; i<256; i++){
int t; int t;
prng_state.j = (prng_state.j + prng_state.s[i] + k[i]) & 0xff; db->prng.j = (db->prng.j + db->prng.s[i] + k[i]) & 0xff;
t = prng_state.s[prng_state.j]; t = db->prng.s[db->prng.j];
prng_state.s[prng_state.j] = prng_state.s[i]; db->prng.s[db->prng.j] = db->prng.s[i];
prng_state.s[i] = t; db->prng.s[i] = t;
} }
prng_state.isInit = 1; db->prng.isInit = 1;
} }
/* Generate and return single random byte /* Generate and return single random byte
*/ */
prng_state.i = (prng_state.i + 1) & 0xff; db->prng.i = (db->prng.i + 1) & 0xff;
prng_state.j = (prng_state.j + prng_state.s[prng_state.i]) & 0xff; db->prng.j = (db->prng.j + db->prng.s[db->prng.i]) & 0xff;
t = prng_state.s[prng_state.i]; t = db->prng.s[db->prng.i];
prng_state.s[prng_state.i] = prng_state.s[prng_state.j]; db->prng.s[db->prng.i] = db->prng.s[db->prng.j];
prng_state.s[prng_state.j] = t; db->prng.s[db->prng.j] = t;
t = prng_state.s[prng_state.i] + prng_state.s[prng_state.j]; t = db->prng.s[db->prng.i] + db->prng.s[db->prng.j];
return prng_state.s[t & 0xff]; return db->prng.s[t & 0xff];
} }
/* /*
** Return a random 32-bit integer. The integer is generated by making ** Return a random 32-bit integer. The integer is generated by making
** 4 calls to sqliteRandomByte(). ** 4 calls to sqliteRandomByte().
*/ */
int sqliteRandomInteger(void){ int sqliteRandomInteger(sqlite *db){
int r; int r;
int i; int i;
r = sqliteRandomByte(); r = sqliteRandomByte(db);
for(i=1; i<4; i++){ for(i=1; i<4; i++){
r = (r<<8) + sqliteRandomByte(); r = (r<<8) + sqliteRandomByte(db);
} }
return r; return r;
} }
/*
** Return a random 16-bit unsigned integer. The integer is generated by
** making 2 calls to sqliteRandomByte().
*/
int sqliteRandomShort(void){
int r;
r = sqliteRandomByte();
r = (r<<8) + sqliteRandomByte();
return r;
}
/*
** Generate a random filename with the given prefix. The new filename
** is written into zBuf[]. The calling function must insure that
** zBuf[] is big enough to hold the prefix plus 20 or so extra
** characters.
**
** Very random names are chosen so that the chance of a
** collision with an existing filename is very very small.
*/
void sqliteRandomName(char *zBuf, char *zPrefix){
int i, j;
static const char zRandomChars[] = "abcdefghijklmnopqrstuvwxyz0123456789";
strcpy(zBuf, zPrefix);
j = strlen(zBuf);
for(i=0; i<15; i++){
int c = sqliteRandomByte() % (sizeof(zRandomChars) - 1);
zBuf[j++] = zRandomChars[c];
}
zBuf[j] = 0;
}

View File

@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** Internal interface definitions for SQLite. ** Internal interface definitions for SQLite.
** **
** @(#) $Id: sqliteInt.h,v 1.53 2001/09/22 18:12:10 drh Exp $ ** @(#) $Id: sqliteInt.h,v 1.54 2001/09/23 19:46:52 drh Exp $
*/ */
#include "sqlite.h" #include "sqlite.h"
#include "hash.h" #include "hash.h"
@ -148,6 +148,12 @@ struct sqlite {
int (*xBusyCallback)(void *,const char*,int); /* The busy callback */ int (*xBusyCallback)(void *,const char*,int); /* The busy callback */
Hash tblHash; /* All tables indexed by name */ Hash tblHash; /* All tables indexed by name */
Hash idxHash; /* All (named) indices indexed by name */ Hash idxHash; /* All (named) indices indexed by name */
struct { /* State of the RC4 random number generator */
int isInit; /* True if initialized */
int i, j; /* State variables */
int s[256]; /* State variables */
} prng;
int nextRowid; /* Next generated rowID */
}; };
/* /*
@ -451,9 +457,8 @@ void sqliteExprResolveInSelect(Parse*, Expr*);
int sqliteExprAnalyzeAggregates(Parse*, Expr*); int sqliteExprAnalyzeAggregates(Parse*, Expr*);
void sqliteParseInfoReset(Parse*); void sqliteParseInfoReset(Parse*);
Vdbe *sqliteGetVdbe(Parse*); Vdbe *sqliteGetVdbe(Parse*);
int sqliteRandomByte(void); int sqliteRandomByte(sqlite*);
int sqliteRandomInteger(void); int sqliteRandomInteger(sqlite*);
void sqliteRandomName(char*,char*);
void sqliteBeginTransaction(Parse*); void sqliteBeginTransaction(Parse*);
void sqliteCommitTransaction(Parse*); void sqliteCommitTransaction(Parse*);
void sqliteRollbackTransaction(Parse*); void sqliteRollbackTransaction(Parse*);

View File

@ -30,7 +30,7 @@
** But other routines are also provided to help in building up ** But other routines are also provided to help in building up
** a program instruction by instruction. ** a program instruction by instruction.
** **
** $Id: vdbe.c,v 1.74 2001/09/23 02:35:53 drh Exp $ ** $Id: vdbe.c,v 1.75 2001/09/23 19:46:52 drh Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@ -1886,7 +1886,26 @@ case OP_MakeIdxKey: {
** database. ** database.
*/ */
case OP_Transaction: { case OP_Transaction: {
rc = sqliteBtreeBeginTrans(pBt); int busy = 0;
do{
rc = sqliteBtreeBeginTrans(pBt);
switch( rc ){
case SQLITE_BUSY: {
if( xBusy==0 || (*xBusy)(pBusyArg, "", ++busy)==0 ){
sqliteSetString(pzErrMsg, sqliteErrStr(rc), 0);
busy = 0;
}
break;
}
case SQLITE_OK: {
busy = 0;
break;
}
default: {
goto abort_due_to_error;
}
}
}while( busy );
break; break;
} }
@ -2262,17 +2281,18 @@ case OP_NewRecno: {
** to double the speed of the COPY operation. ** to double the speed of the COPY operation.
*/ */
int res, rx, cnt; int res, rx, cnt;
static int x = 0; int x;
union { union {
char zBuf[sizeof(int)]; char zBuf[sizeof(int)];
int i; int i;
} ux; } ux;
cnt = 0; cnt = 0;
x = db->nextRowid;
do{ do{
if( cnt>5 ){ if( cnt>5 ){
x = sqliteRandomInteger(); x = sqliteRandomInteger(db);
}else{ }else{
x += sqliteRandomByte() + 1; x += sqliteRandomByte(db) + 1;
} }
if( x==0 ) continue; if( x==0 ) continue;
ux.zBuf[3] = x&0xff; ux.zBuf[3] = x&0xff;
@ -2283,6 +2303,7 @@ case OP_NewRecno: {
rx = sqliteBtreeMoveto(p->aCsr[i].pCursor, &v, sizeof(v), &res); rx = sqliteBtreeMoveto(p->aCsr[i].pCursor, &v, sizeof(v), &res);
cnt++; cnt++;
}while( cnt<1000 && rx==SQLITE_OK && res==0 ); }while( cnt<1000 && rx==SQLITE_OK && res==0 );
db->nextRowid = x;
if( rx==SQLITE_OK && res==0 ){ if( rx==SQLITE_OK && res==0 ){
rc = SQLITE_FULL; rc = SQLITE_FULL;
goto abort_due_to_error; goto abort_due_to_error;

View File

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The # This file implements regression tests for SQLite library. The
# focus of this script is database locks. # focus of this script is database locks.
# #
# $Id: lock.test,v 1.11 2001/09/23 02:35:53 drh Exp $ # $Id: lock.test,v 1.12 2001/09/23 19:46:52 drh Exp $
set testdir [file dirname $argv0] set testdir [file dirname $argv0]
@ -101,7 +101,7 @@ do_test lock-1.17 {
set x set x
} {8 9} } {8 9}
# You cannot UPDATE a table from within the callback of a SELECT # You cannot UPDATE a table from within the callback of a SELECT
# on that same table because the SELECT has the table locked. # on that same table because the SELECT has the table locked.
# #
do_test lock-1.18 { do_test lock-1.18 {
@ -152,6 +152,101 @@ if {$::tcl_platform(platform)=="unix"} {
} {0 2} } {0 2}
} }
# If one thread has a transaction another thread cannot start
# a transaction.
#
do_test lock-2.1 {
execsql {BEGIN TRANSACTION}
set r [catch {execsql {BEGIN TRANSACTION} db2} msg]
lappend r $msg
} {1 {database is locked}}
# Nor can the other thread do a query.
#
do_test lock-2.2 {
set r [catch {execsql {SELECT * FROM t2} db2} msg]
lappend r $msg
} {1 {database is locked}}
# If the other thread (the one that does not hold the transaction)
# tries to start a transaction, we get a busy callback.
#
do_test lock-2.3 {
proc callback {args} {
set ::callback_value $args
break
}
set ::callback_value {}
db2 busy callback
set r [catch {execsql {BEGIN TRANSACTION} db2} msg]
lappend r $msg
lappend r $::callback_value
} {1 {database is locked} {{} 1}}
do_test lock-2.4 {
proc callback {file count} {
lappend ::callback_value $count
if {$count>4} break
}
set ::callback_value {}
db2 busy callback
set r [catch {execsql {BEGIN TRANSACTION} db2} msg]
lappend r $msg
lappend r $::callback_value
} {1 {database is locked} {1 2 3 4 5}}
do_test lock-2.5 {
proc callback {file count} {
lappend ::callback_value $count
if {$count>4} break
}
set ::callback_value {}
db2 busy callback
set r [catch {execsql {SELECT * FROM t1} db2} msg]
lappend r $msg
lappend r $::callback_value
} {1 {database is locked} {1 2 3 4 5}}
# In this test, the 3rd invocation of the busy callback causes
# the first thread to release its transaction. That allows the
# second thread to continue.
#
do_test lock-2.6 {
proc callback {file count} {
lappend ::callback_value $count
if {$count>2} {
execsql {ROLLBACK}
}
}
set ::callback_value {}
db2 busy callback
set r [catch {execsql {SELECT * FROM t2} db2} msg]
lappend r $msg
lappend r $::callback_value
} {0 {9 8} {1 2 3}}
do_test lock-2.7 {
execsql {BEGIN TRANSACTION}
proc callback {file count} {
lappend ::callback_value $count
if {$count>2} {
execsql {ROLLBACK}
}
}
set ::callback_value {}
db2 busy callback
set r [catch {execsql {BEGIN TRANSACTION} db2} msg]
execsql {ROLLBACK} db2
lappend r $msg
lappend r $::callback_value
} {0 {} {1 2 3}}
# Try to start two transactions in a row
#
do_test lock-3.1 {
execsql {BEGIN TRANSACTION}
set r [catch {execsql {BEGIN TRANSACTION}} msg]
execsql {ROLLBACK}
lappend r $msg
} {0 {}}
do_test lock-999.1 { do_test lock-999.1 {
rename db2 {} rename db2 {}

View File

@ -17,6 +17,10 @@ proc chng {date desc} {
puts "<DD><P><UL>$desc</UL></P></DD>" puts "<DD><P><UL>$desc</UL></P></DD>"
} }
chng {2001 Sep 22 (2.0-beta-1)} {
<li>Fixes to the rollback and locking behavior</li>
}
chng {2001 Sep 20 (2.0-alpha-2)} { chng {2001 Sep 20 (2.0-alpha-2)} {
<li>Initial release of version 2.0. The idea of renaming the library <li>Initial release of version 2.0. The idea of renaming the library
to "SQLus" was abandoned in favor of keeping the "SQLite" name and to "SQLus" was abandoned in favor of keeping the "SQLite" name and