mirror of https://github.com/sqlite/sqlite
Changes for exclusive access mode. There are still some bugs. (CVS 3712)
FossilOrigin-Name: b6c700370be29db2b974f9abd719c3e56abf8058
This commit is contained in:
parent
e277be0545
commit
414834686c
23
manifest
23
manifest
|
@ -1,5 +1,5 @@
|
|||
C Discard\sthe\scontents\sof\sthe\spager-cache\sonly\swhen\sthe\schange-counter\sindicates\sthat\sit\sis\sstale.\s(CVS\s3711)
|
||||
D 2007-03-23T18:12:07
|
||||
C Changes\sfor\sexclusive\saccess\smode.\sThere\sare\sstill\ssome\sbugs.\s(CVS\s3712)
|
||||
D 2007-03-24T16:45:05
|
||||
F Makefile.in 1fe3d0b46e40fd684e1e61f8e8056cefed16de9f
|
||||
F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
|
||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||
|
@ -56,7 +56,7 @@ F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4
|
|||
F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a
|
||||
F src/alter.c 2c79ec40f65e33deaf90ca493422c74586e481a3
|
||||
F src/analyze.c 7d2b7ab9a9c2fd6e55700f69064dfdd3e36d7a8a
|
||||
F src/attach.c fd286a9140a2df84b1482f052b67ff5fad9569a1
|
||||
F src/attach.c 9b5a9c50fb92883e3404353b225674142da826cd
|
||||
F src/auth.c 902f4722661c796b97f007d9606bd7529c02597f
|
||||
F src/btree.c 4d94251b59fa33c888efc43881729f7d297899a4
|
||||
F src/btree.h 066444ee25bd6e6accb997bfd2cf5ace14dbcd00
|
||||
|
@ -86,10 +86,10 @@ F src/os_unix.c 4642f23ed0c1ae0f1440db1d2b4231348af69360
|
|||
F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e
|
||||
F src/os_win.c 1d1d0989b0f235751504292c2f28e81044be0d70
|
||||
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
|
||||
F src/pager.c da3c5e90b2c99bdba6129f568102c24cbd438452
|
||||
F src/pager.h 9f6b5ef42c761deec8a9b1966b32e9a9dc89a631
|
||||
F src/pager.c 9023042d50d961cfcaad4e9211eea711abb2b7f4
|
||||
F src/pager.h 3c16500c25051536e43fb19e246e58fc7cb51d9f
|
||||
F src/parse.y bcfe366c1fd61cfc40e5344eb69a31997a821af0
|
||||
F src/pragma.c a3fe1dacdbf320ad99d4125a60a5bce8f1808bc8
|
||||
F src/pragma.c 9cb8b94e7d38ba35a86037bd517d07ba9870b4b2
|
||||
F src/prepare.c 4e075fe28591b7d4ffbf818fb88a7e19bbe98065
|
||||
F src/printf.c aade23a789d7cc88b397ec0d33a0a01a33a7a9c1
|
||||
F src/random.c 6119474a6f6917f708c1dee25b9a8e519a620e88
|
||||
|
@ -98,7 +98,7 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
|||
F src/shell.c 3ae4654560e91220a95738a73d135d91d937cda1
|
||||
F src/sqlite.h.in 6b7383baf76070214f6381f603328ca9b22a7fae
|
||||
F src/sqlite3ext.h 011c75fd6459a61454514af07c7a4f1f5c767f27
|
||||
F src/sqliteInt.h 6e3ac7a1a8f51e24ce4784236aa957e9bd11217f
|
||||
F src/sqliteInt.h 5451308c885e8620e0d4764ae162da2566520073
|
||||
F src/table.c 6d0da66dde26ee75614ed8f584a1996467088d06
|
||||
F src/tclsqlite.c cd2b3b86ab07c0e0779f6c6e71e72c6c7dc1e704
|
||||
F src/test1.c b4ff8f82f84d2ccdf07a2db5acae7b47c12f60d7
|
||||
|
@ -199,6 +199,7 @@ F test/distinctagg.test 2b89d1c5220d966a30ba4b40430338669301188b
|
|||
F test/enc.test 7a03417a1051fe8bc6c7641cf4c8c3f7e0066d52
|
||||
F test/enc2.test 45710bacfa9df29720bc84c067dfdf8c8ddfb797
|
||||
F test/enc3.test 890508efff6677345e93bf2a8adb0489b30df030
|
||||
F test/exclusive.test 67a1bedd37b92785a0ba3b596401910713653b5e
|
||||
F test/expr.test c78843f730ccbe973d0c2ad1c99978f936893131
|
||||
F test/fkey1.test 153004438d51e6769fb1ce165f6313972d6263ce
|
||||
F test/format4.test bf3bed3b13c63abfb3cfec232597a319a31d0bcc
|
||||
|
@ -330,7 +331,7 @@ F test/tkt2192.test 480d0e017ddb01a46ee20809427370f343bb3c03
|
|||
F test/tkt2213.test 8cf7c446e1fcd0627fffe7fc19046eb24ac7333b
|
||||
F test/tkt2251.test 3f0549213386ed911715665a908ff2bb7a871002
|
||||
F test/trace.test 75ffc1b992c780d054748a656e3e7fd674f18567
|
||||
F test/trans.test 06bff0246886858793fca3748721936e2f65e3df
|
||||
F test/trans.test f4577bbefe1fb49e6c13f32923a8891250a9d628
|
||||
F test/trigger1.test 2c79e2bf76350811e362814e98779c120b6a9421
|
||||
F test/trigger2.test 33bf8ae9b788013be194efe5f66c04a202facbb4
|
||||
F test/trigger3.test 9102fd3933db294dc654b5aee9edfe9e94f2b9e2
|
||||
|
@ -437,7 +438,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
|
|||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
|
||||
P 0fd9983a98d8d61654f252f1708a4d7232a96b53
|
||||
R ec284a76fe569250a4f6f20542fb07fe
|
||||
P 07b56965f3227c9f78680728b955395295c4aa49
|
||||
R 5306d65289bf66945a0a4cf7185afe17
|
||||
U danielk1977
|
||||
Z c13a7ab87a49cb94c1a31349a8579dca
|
||||
Z 4da3e2ad8e93e75be905d9a01fa04929
|
||||
|
|
|
@ -1 +1 @@
|
|||
07b56965f3227c9f78680728b955395295c4aa49
|
||||
b6c700370be29db2b974f9abd719c3e56abf8058
|
|
@ -11,7 +11,7 @@
|
|||
*************************************************************************
|
||||
** This file contains code used to implement the ATTACH and DETACH commands.
|
||||
**
|
||||
** $Id: attach.c,v 1.54 2007/03/15 15:35:29 danielk1977 Exp $
|
||||
** $Id: attach.c,v 1.55 2007/03/24 16:45:05 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
|
@ -133,6 +133,7 @@ static void attachFunc(
|
|||
"attached databases must use the same text encoding as main database");
|
||||
goto attach_error;
|
||||
}
|
||||
sqlite3PagerLockingMode(sqlite3BtreePager(aNew->pBt), db->dfltLockMode);
|
||||
}
|
||||
aNew->zName = sqliteStrDup(zName);
|
||||
aNew->safety_level = 3;
|
||||
|
|
102
src/pager.c
102
src/pager.c
|
@ -18,7 +18,7 @@
|
|||
** file simultaneously, or one process from reading the database while
|
||||
** another is writing.
|
||||
**
|
||||
** @(#) $Id: pager.c,v 1.293 2007/03/23 18:12:07 danielk1977 Exp $
|
||||
** @(#) $Id: pager.c,v 1.294 2007/03/24 16:45:05 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_DISKIO
|
||||
#include "sqliteInt.h"
|
||||
|
@ -285,8 +285,10 @@ struct Pager {
|
|||
Pager *pNext; /* Linked list of pagers in this thread */
|
||||
#endif
|
||||
char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */
|
||||
int doNotSync; /* While true, do not spill the cache */
|
||||
u32 iChangeCount; /* Db change-counter for which cache is valid */
|
||||
u8 doNotSync; /* Boolean. While true, do not spill the cache */
|
||||
u8 exclusiveMode; /* Boolean. True if locking_mode==EXCLUSIVE */
|
||||
u8 changeCountDone; /* Set after incrementing the change-counter */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -854,12 +856,15 @@ static PgHdr *pager_lookup(Pager *pPager, Pgno pgno){
|
|||
** Unlock the database file.
|
||||
*/
|
||||
static void pager_unlock(Pager *pPager){
|
||||
if( !MEMDB ){
|
||||
sqlite3OsUnlock(pPager->fd, NO_LOCK);
|
||||
pPager->dbSize = -1;
|
||||
IOTRACE(("UNLOCK %p\n", pPager))
|
||||
if( !pPager->exclusiveMode ){
|
||||
if( !MEMDB ){
|
||||
sqlite3OsUnlock(pPager->fd, NO_LOCK);
|
||||
pPager->dbSize = -1;
|
||||
IOTRACE(("UNLOCK %p\n", pPager))
|
||||
}
|
||||
pPager->state = PAGER_UNLOCK;
|
||||
pPager->changeCountDone = 0;
|
||||
}
|
||||
pPager->state = PAGER_UNLOCK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -873,7 +878,6 @@ static void pagerUnlockAndRollback(Pager *pPager){
|
|||
sqlite3PagerRollback(pPager);
|
||||
}
|
||||
pager_unlock(pPager);
|
||||
assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -902,28 +906,6 @@ static void pager_reset(Pager *pPager){
|
|||
pPager->nRef = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function resets the various pager flags to their initial
|
||||
** state but does not discard the cached content.
|
||||
*/
|
||||
static void pagerSoftReset(Pager *pPager){
|
||||
PgHdr *pPg;
|
||||
|
||||
assert(pPager->pStmt==0);
|
||||
assert(pPager->nRef==0);
|
||||
assert(pPager->pFirstSynced==pPager->pFirst);
|
||||
assert(pPager->aInJournal==0);
|
||||
|
||||
for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
|
||||
assert( pPg->nRef==0 );
|
||||
pPg->inJournal = 0;
|
||||
pPg->inStmt = 0;
|
||||
pPg->dirty = 0;
|
||||
pPg->needSync = 0;
|
||||
pPg->alwaysRollback = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** When this routine is called, the pager has the journal file open and
|
||||
** a RESERVED or EXCLUSIVE lock on the database. This routine releases
|
||||
|
@ -936,7 +918,7 @@ static void pagerSoftReset(Pager *pPager){
|
|||
*/
|
||||
static int pager_unwritelock(Pager *pPager){
|
||||
PgHdr *pPg;
|
||||
int rc;
|
||||
int rc = SQLITE_OK;
|
||||
assert( !MEMDB );
|
||||
if( pPager->state<PAGER_RESERVED ){
|
||||
return SQLITE_OK;
|
||||
|
@ -947,15 +929,22 @@ static int pager_unwritelock(Pager *pPager){
|
|||
pPager->stmtOpen = 0;
|
||||
}
|
||||
if( pPager->journalOpen ){
|
||||
sqlite3OsClose(&pPager->jfd);
|
||||
pPager->journalOpen = 0;
|
||||
sqlite3OsDelete(pPager->zJournal);
|
||||
if( pPager->exclusiveMode ){
|
||||
sqlite3OsTruncate(pPager->jfd, 0);
|
||||
sqlite3OsSeek(pPager->jfd, 0);
|
||||
pPager->journalOff = 0;
|
||||
}else{
|
||||
sqlite3OsClose(&pPager->jfd);
|
||||
pPager->journalOpen = 0;
|
||||
sqlite3OsDelete(pPager->zJournal);
|
||||
}
|
||||
sqliteFree( pPager->aInJournal );
|
||||
pPager->aInJournal = 0;
|
||||
for(pPg=pPager->pAll; pPg; pPg=pPg->pNextAll){
|
||||
pPg->inJournal = 0;
|
||||
pPg->dirty = 0;
|
||||
pPg->needSync = 0;
|
||||
pPg->alwaysRollback = 0;
|
||||
#ifdef SQLITE_CHECK_PAGES
|
||||
pPg->pageHash = pager_pagehash(pPg);
|
||||
#endif
|
||||
|
@ -967,9 +956,18 @@ static int pager_unwritelock(Pager *pPager){
|
|||
assert( pPager->aInJournal==0 );
|
||||
assert( pPager->dirtyCache==0 || pPager->useJournal==0 );
|
||||
}
|
||||
rc = sqlite3OsUnlock(pPager->fd, SHARED_LOCK);
|
||||
pPager->state = PAGER_SHARED;
|
||||
pPager->origDbSize = 0;
|
||||
if( !pPager->exclusiveMode ){
|
||||
rc = sqlite3OsUnlock(pPager->fd, SHARED_LOCK);
|
||||
pPager->state = PAGER_SHARED;
|
||||
pPager->origDbSize = 0;
|
||||
}else{
|
||||
sqlite3PagerPagecount(pPager);
|
||||
pPager->origDbSize = pPager->dbSize;
|
||||
pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 );
|
||||
if( !pPager->aInJournal ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
pPager->setMaster = 0;
|
||||
pPager->needSync = 0;
|
||||
pPager->pFirstSynced = pPager->pFirst;
|
||||
|
@ -1109,6 +1107,11 @@ static int pager_playback_one_page(Pager *pPager, OsFile *jfd, int useCksum){
|
|||
pPg->pageHash = pager_pagehash(pPg);
|
||||
#endif
|
||||
CODEC1(pPager, pData, pPg->pgno, 3);
|
||||
|
||||
/* If this was page 1, then restore the value of Pager.iChangeCount */
|
||||
if( pgno==1 ){
|
||||
pPager->iChangeCount = retrieve32bits(pPg, 24);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
@ -1199,6 +1202,7 @@ delmaster_out:
|
|||
return rc;
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
** Make every page in the cache agree with what is on disk. In other words,
|
||||
** reread the disk to reset the state of the cache.
|
||||
|
@ -1242,6 +1246,7 @@ static int pager_reload_cache(Pager *pPager){
|
|||
pPager->pDirty = 0;
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Truncate the main file of the given pager to the number of pages
|
||||
|
@ -2126,6 +2131,7 @@ int sqlite3PagerClose(Pager *pPager){
|
|||
|
||||
disable_simulated_io_errors();
|
||||
pPager->errCode = 0;
|
||||
pPager->exclusiveMode = 0;
|
||||
pager_reset(pPager);
|
||||
pagerUnlockAndRollback(pPager);
|
||||
enable_simulated_io_errors();
|
||||
|
@ -2734,8 +2740,6 @@ static int pagerSharedLock(Pager *pPager){
|
|||
pPager->nRef--;
|
||||
if( iChangeCount!=pPager->iChangeCount ){
|
||||
pager_reset(pPager);
|
||||
}else{
|
||||
pagerSoftReset(pPager);
|
||||
}
|
||||
pPager->iChangeCount = iChangeCount;
|
||||
}
|
||||
|
@ -3610,6 +3614,8 @@ int sqlite3PagerRollback(Pager *pPager){
|
|||
PgHistory *pHist;
|
||||
assert( !p->alwaysRollback );
|
||||
if( !p->dirty ){
|
||||
assert( p->inJournal==0 );
|
||||
assert( p->inStmt==0 );
|
||||
assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pOrig );
|
||||
assert( !((PgHistory *)PGHDR_TO_HIST(p, pPager))->pStmt );
|
||||
continue;
|
||||
|
@ -3890,6 +3896,7 @@ static int pager_incr_changecounter(Pager *pPager){
|
|||
|
||||
/* Release the page reference. */
|
||||
sqlite3PagerUnref(pPgHdr);
|
||||
pPager->changeCountDone = 1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
@ -4098,6 +4105,23 @@ void *sqlite3PagerGetExtra(DbPage *pPg){
|
|||
return (pPager?PGHDR_TO_EXTRA(pPg, pPager):0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Get/set the locking-mode for this pager. Parameter eMode must be one
|
||||
** of PAGER_LOCKINGMODE_QUERY, PAGER_LOCKINGMODE_NORMAL or
|
||||
** PAGER_LOCKINGMODE_EXCLUSIVE. If the parameter is not _QUERY, then
|
||||
** the locking-mode is set to the value specified.
|
||||
**
|
||||
** The returned value is either PAGER_LOCKINGMODE_NORMAL or
|
||||
** PAGER_LOCKINGMODE_EXCLUSIVE, indicating the current (possibly updated)
|
||||
** locking-mode.
|
||||
*/
|
||||
int sqlite3PagerLockingMode(Pager *pPager, int eMode){
|
||||
if( eMode>=0 ){
|
||||
pPager->exclusiveMode = eMode;
|
||||
}
|
||||
return (int)pPager->exclusiveMode;
|
||||
}
|
||||
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
/*
|
||||
** Return the current state of the file lock for the given pager.
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
** subsystem. The page cache subsystem reads and writes a file a page
|
||||
** at a time and provides a journal for rollback.
|
||||
**
|
||||
** @(#) $Id: pager.h,v 1.54 2007/03/19 17:44:27 danielk1977 Exp $
|
||||
** @(#) $Id: pager.h,v 1.55 2007/03/24 16:45:05 danielk1977 Exp $
|
||||
*/
|
||||
|
||||
#ifndef _PAGER_H_
|
||||
|
@ -69,6 +69,12 @@ typedef struct PgHdr DbPage;
|
|||
#define PAGER_OMIT_JOURNAL 0x0001 /* Do not use a rollback journal */
|
||||
#define PAGER_NO_READLOCK 0x0002 /* Omit readlocks on readonly files */
|
||||
|
||||
/*
|
||||
** Valid values for the second argument to sqlite3PagerLockingMode().
|
||||
*/
|
||||
#define PAGER_LOCKINGMODE_QUERY -1
|
||||
#define PAGER_LOCKINGMODE_NORMAL 0
|
||||
#define PAGER_LOCKINGMODE_EXCLUSIVE 1
|
||||
|
||||
/*
|
||||
** See source code comments for a detailed description of the following
|
||||
|
@ -119,6 +125,7 @@ int sqlite3PagerReleaseMemory(int);
|
|||
|
||||
void *sqlite3PagerGetData(DbPage *);
|
||||
void *sqlite3PagerGetExtra(DbPage *);
|
||||
int sqlite3PagerLockingMode(Pager *, int);
|
||||
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
||||
int sqlite3PagerLockstate(Pager*);
|
||||
|
|
60
src/pragma.c
60
src/pragma.c
|
@ -11,7 +11,7 @@
|
|||
*************************************************************************
|
||||
** This file contains code used to implement the PRAGMA command.
|
||||
**
|
||||
** $Id: pragma.c,v 1.129 2007/03/19 17:44:28 danielk1977 Exp $
|
||||
** $Id: pragma.c,v 1.130 2007/03/24 16:45:05 danielk1977 Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
|
@ -62,6 +62,17 @@ static int getBoolean(const char *z){
|
|||
return getSafetyLevel(z)&1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Interpret the given string as a locking mode value.
|
||||
*/
|
||||
static int getLockingMode(const char *z){
|
||||
if( z ){
|
||||
if( 0==sqlite3StrICmp(z, "exclusive") ) return PAGER_LOCKINGMODE_EXCLUSIVE;
|
||||
if( 0==sqlite3StrICmp(z, "normal") ) return PAGER_LOCKINGMODE_NORMAL;
|
||||
}
|
||||
return PAGER_LOCKINGMODE_QUERY;
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
|
||||
/*
|
||||
** Interpret the given string as a temp db location. Return 1 for file
|
||||
|
@ -315,6 +326,53 @@ void sqlite3Pragma(
|
|||
sqlite3BtreeSetPageSize(pBt, atoi(zRight), -1);
|
||||
}
|
||||
}else
|
||||
|
||||
/*
|
||||
** PRAGMA [database.]locking_mode
|
||||
** PRAGMA [database.]locking_mode = (normal|exclusive)
|
||||
*/
|
||||
if( sqlite3StrICmp(zLeft,"locking_mode")==0 ){
|
||||
const char *zRet = "normal";
|
||||
int eMode = getLockingMode(zRight);
|
||||
|
||||
if( pId2->n==0 && eMode==PAGER_LOCKINGMODE_QUERY ){
|
||||
/* Simple "PRAGMA locking_mode;" statement. This is a query for
|
||||
** the current default locking mode (which may be different to
|
||||
** the locking-mode of the main database).
|
||||
*/
|
||||
eMode = db->dfltLockMode;
|
||||
}else{
|
||||
Pager *pPager;
|
||||
if( pId2->n==0 ){
|
||||
/* This indicates that no database name was specified as part
|
||||
** of the PRAGMA command. In this case the locking-mode must be
|
||||
** set on all attached databases, as well as the main db file.
|
||||
**
|
||||
** Also, the sqlite3.dfltLockMode variable is set so that
|
||||
** any subsequently attached databases also use the specified
|
||||
** locking mode.
|
||||
*/
|
||||
int ii;
|
||||
assert(pDb==&db->aDb[0]);
|
||||
for(ii=2; ii<db->nDb; ii++){
|
||||
pPager = sqlite3BtreePager(db->aDb[ii].pBt);
|
||||
sqlite3PagerLockingMode(pPager, eMode);
|
||||
}
|
||||
db->dfltLockMode = eMode;
|
||||
}
|
||||
pPager = sqlite3BtreePager(pDb->pBt);
|
||||
eMode = sqlite3PagerLockingMode(pPager, eMode);
|
||||
}
|
||||
|
||||
assert(eMode==PAGER_LOCKINGMODE_NORMAL||eMode==PAGER_LOCKINGMODE_EXCLUSIVE);
|
||||
if( eMode==PAGER_LOCKINGMODE_EXCLUSIVE ){
|
||||
zRet = "exclusive";
|
||||
}
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "locking_mode", P3_STATIC);
|
||||
sqlite3VdbeOp3(v, OP_String8, 0, 0, zRet, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
|
||||
}else
|
||||
#endif /* SQLITE_OMIT_PAGER_PRAGMAS */
|
||||
|
||||
/*
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.542 2007/03/14 15:37:04 danielk1977 Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.543 2007/03/24 16:45:05 danielk1977 Exp $
|
||||
*/
|
||||
#ifndef _SQLITEINT_H_
|
||||
#define _SQLITEINT_H_
|
||||
|
@ -510,6 +510,7 @@ struct sqlite3 {
|
|||
#ifdef SQLITE_SSE
|
||||
sqlite3_stmt *pFetch; /* Used by SSE to fetch stored statements */
|
||||
#endif
|
||||
u8 dfltLockMode; /* Default locking-mode for attached dbs */
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -0,0 +1,340 @@
|
|||
# 2007 March 24
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library.
|
||||
#
|
||||
# $Id: exclusive.test,v 1.1 2007/03/24 16:45:05 danielk1977 Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
|
||||
ifcapable {!pager_pragmas} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
file delete -force test2.db-journal
|
||||
file delete -force test2.db
|
||||
file delete -force test3.db-journal
|
||||
file delete -force test3.db
|
||||
file delete -force test4.db-journal
|
||||
file delete -force test4.db
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Test cases exclusive-1.X test the PRAGMA logic.
|
||||
#
|
||||
do_test exclusive-1.0 {
|
||||
execsql {
|
||||
pragma locking_mode;
|
||||
pragma main.locking_mode;
|
||||
}
|
||||
} {normal normal}
|
||||
do_test exclusive-1.1 {
|
||||
execsql {
|
||||
pragma locking_mode = exclusive;
|
||||
}
|
||||
} {exclusive}
|
||||
do_test exclusive-1.2 {
|
||||
execsql {
|
||||
pragma locking_mode;
|
||||
pragma main.locking_mode;
|
||||
}
|
||||
} {exclusive exclusive}
|
||||
do_test exclusive-1.3 {
|
||||
execsql {
|
||||
pragma locking_mode = normal;
|
||||
}
|
||||
} {normal}
|
||||
do_test exclusive-1.4 {
|
||||
execsql {
|
||||
pragma locking_mode;
|
||||
pragma main.locking_mode;
|
||||
}
|
||||
} {normal normal}
|
||||
do_test exclusive-1.5 {
|
||||
execsql {
|
||||
pragma locking_mode = invalid;
|
||||
}
|
||||
} {normal}
|
||||
do_test exclusive-1.6 {
|
||||
execsql {
|
||||
pragma locking_mode;
|
||||
pragma main.locking_mode;
|
||||
}
|
||||
} {normal normal}
|
||||
do_test exclusive-1.7 {
|
||||
execsql {
|
||||
pragma locking_mode = exclusive;
|
||||
ATTACH 'test2.db' as aux;
|
||||
}
|
||||
execsql {
|
||||
pragma main.locking_mode;
|
||||
pragma aux.locking_mode;
|
||||
}
|
||||
} {exclusive exclusive}
|
||||
do_test exclusive-1.8 {
|
||||
execsql {
|
||||
pragma main.locking_mode = normal;
|
||||
}
|
||||
execsql {
|
||||
pragma main.locking_mode;
|
||||
pragma aux.locking_mode;
|
||||
}
|
||||
} {normal exclusive}
|
||||
do_test exclusive-1.9 {
|
||||
execsql {
|
||||
pragma locking_mode;
|
||||
}
|
||||
} {exclusive}
|
||||
do_test exclusive-1.10 {
|
||||
execsql {
|
||||
ATTACH 'test3.db' as aux2;
|
||||
}
|
||||
execsql {
|
||||
pragma main.locking_mode;
|
||||
pragma aux.locking_mode;
|
||||
pragma aux2.locking_mode;
|
||||
}
|
||||
} {normal exclusive exclusive}
|
||||
do_test exclusive-1.11 {
|
||||
execsql {
|
||||
pragma aux.locking_mode = normal;
|
||||
}
|
||||
execsql {
|
||||
pragma main.locking_mode;
|
||||
pragma aux.locking_mode;
|
||||
pragma aux2.locking_mode;
|
||||
}
|
||||
} {normal normal exclusive}
|
||||
do_test exclusive-1.12 {
|
||||
execsql {
|
||||
pragma locking_mode = normal;
|
||||
}
|
||||
execsql {
|
||||
pragma main.locking_mode;
|
||||
pragma aux.locking_mode;
|
||||
pragma aux2.locking_mode;
|
||||
}
|
||||
} {normal normal normal}
|
||||
do_test exclusive-1.13 {
|
||||
execsql {
|
||||
ATTACH 'test4.db' as aux3;
|
||||
}
|
||||
execsql {
|
||||
pragma main.locking_mode;
|
||||
pragma aux.locking_mode;
|
||||
pragma aux2.locking_mode;
|
||||
pragma aux3.locking_mode;
|
||||
}
|
||||
} {normal normal normal normal}
|
||||
|
||||
do_test exclusive-1.99 {
|
||||
execsql {
|
||||
DETACH aux;
|
||||
DETACH aux2;
|
||||
DETACH aux3;
|
||||
}
|
||||
} {}
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Test cases exclusive-2.X verify that connections in exclusive
|
||||
# locking_mode do not relinquish locks.
|
||||
#
|
||||
do_test exclusive-2.0 {
|
||||
execsql {
|
||||
CREATE TABLE abc(a, b, c);
|
||||
INSERT INTO abc VALUES(1, 2, 3);
|
||||
PRAGMA locking_mode = exclusive;
|
||||
}
|
||||
} {exclusive}
|
||||
do_test exclusive-2.1 {
|
||||
sqlite3 db2 test.db
|
||||
execsql {
|
||||
INSERT INTO abc VALUES(4, 5, 6);
|
||||
SELECT * FROM abc;
|
||||
} db2
|
||||
} {1 2 3 4 5 6}
|
||||
do_test exclusive-2.2 {
|
||||
# This causes connection 'db' (in exclusive mode) to establish
|
||||
# a shared-lock on the db. The other connection should now be
|
||||
# locked out as a writer.
|
||||
execsql {
|
||||
SELECT * FROM abc;
|
||||
} db
|
||||
} {1 2 3 4 5 6}
|
||||
do_test exclusive-2.4 {
|
||||
execsql {
|
||||
SELECT * FROM abc;
|
||||
} db2
|
||||
} {1 2 3 4 5 6}
|
||||
do_test exclusive-2.5 {
|
||||
catchsql {
|
||||
INSERT INTO abc VALUES(7, 8, 9);
|
||||
} db2
|
||||
} {1 {database is locked}}
|
||||
do_test exclusive-2.6 {
|
||||
# Because connection 'db' only has a shared-lock, the other connection
|
||||
# will be able to get a RESERVED, but will fail to upgrade to EXCLUSIVE.
|
||||
execsql {
|
||||
BEGIN;
|
||||
INSERT INTO abc VALUES(7, 8, 9);
|
||||
} db2
|
||||
catchsql {
|
||||
COMMIT
|
||||
} db2
|
||||
} {1 {database is locked}}
|
||||
do_test exclusive-2.7 {
|
||||
catchsql {
|
||||
COMMIT
|
||||
} db2
|
||||
} {1 {database is locked}}
|
||||
do_test exclusive-2.8 {
|
||||
execsql {
|
||||
ROLLBACK;
|
||||
} db2
|
||||
} {}
|
||||
|
||||
do_test exclusive-2.9 {
|
||||
# Write the database to establish the exclusive lock with connection 'db.
|
||||
execsql {
|
||||
INSERT INTO abc VALUES(7, 8, 9);
|
||||
} db
|
||||
catchsql {
|
||||
SELECT * FROM abc;
|
||||
} db2
|
||||
} {1 {database is locked}}
|
||||
do_test exclusive-2.10 {
|
||||
# Changing the locking-mode does not release any locks.
|
||||
execsql {
|
||||
PRAGMA locking_mode = normal;
|
||||
} db
|
||||
catchsql {
|
||||
SELECT * FROM abc;
|
||||
} db2
|
||||
} {1 {database is locked}}
|
||||
do_test exclusive-2.11 {
|
||||
# After changing the locking mode, accessing the db releases locks.
|
||||
execsql {
|
||||
SELECT * FROM abc;
|
||||
} db
|
||||
execsql {
|
||||
SELECT * FROM abc;
|
||||
} db2
|
||||
} {1 2 3 4 5 6 7 8 9}
|
||||
db2 close
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Tests exclusive-3.X - test that a connection in exclusive mode
|
||||
# truncates instead of deletes the journal file when committing
|
||||
# a transaction.
|
||||
#
|
||||
proc filestate {fname} {
|
||||
set exists 0
|
||||
set content 0
|
||||
if {[file exists $fname]} {
|
||||
set exists 1
|
||||
set content [expr {[file size $fname] > 0}]
|
||||
}
|
||||
list $exists $content
|
||||
}
|
||||
do_test exclusive-3.0 {
|
||||
filestate test.db-journal
|
||||
} {0 0}
|
||||
do_test exclusive-3.1 {
|
||||
execsql {
|
||||
PRAGMA locking_mode = exclusive;
|
||||
BEGIN;
|
||||
DELETE FROM abc;
|
||||
}
|
||||
filestate test.db-journal
|
||||
} {1 1}
|
||||
do_test exclusive-3.2 {
|
||||
execsql {
|
||||
COMMIT;
|
||||
}
|
||||
filestate test.db-journal
|
||||
} {1 0}
|
||||
do_test exclusive-3.3 {
|
||||
execsql {
|
||||
INSERT INTO abc VALUES('A', 'B', 'C');
|
||||
SELECT * FROM abc;
|
||||
}
|
||||
} {A B C}
|
||||
do_test exclusive-3.4 {
|
||||
execsql {
|
||||
BEGIN;
|
||||
UPDATE abc SET a = 1, b = 2, c = 3;
|
||||
ROLLBACK;
|
||||
SELECT * FROM abc;
|
||||
}
|
||||
} {1 2 3}
|
||||
do_test exclusive-3.5 {
|
||||
filestate test.db-journal
|
||||
} {1 0}
|
||||
do_test exclusive-3.6 {
|
||||
execsql {
|
||||
PRAGMA locking_mode = normal;
|
||||
SELECT * FROM abc;
|
||||
}
|
||||
filestate test.db-journal
|
||||
} {0 0}
|
||||
|
||||
# The following procedure computes a "signature" for table "t3". If
|
||||
# T3 changes in any way, the signature should change.
|
||||
#
|
||||
# This is used to test ROLLBACK. We gather a signature for t3, then
|
||||
# make lots of changes to t3, then rollback and take another signature.
|
||||
# The two signatures should be the same.
|
||||
#
|
||||
proc signature {} {
|
||||
return [db eval {SELECT count(*), md5sum(x) FROM t3}]
|
||||
}
|
||||
|
||||
if 0 {
|
||||
|
||||
do_test exclusive-4.0 {
|
||||
execsql { PRAGMA default_cache_size=10; }
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
execsql { PRAGMA locking_mode = exclusive; }
|
||||
execsql {
|
||||
BEGIN;
|
||||
CREATE TABLE t3(x TEXT);
|
||||
INSERT INTO t3 VALUES(randstr(10,400));
|
||||
INSERT INTO t3 VALUES(randstr(10,400));
|
||||
INSERT INTO t3 SELECT randstr(10,400) FROM t3;
|
||||
INSERT INTO t3 SELECT randstr(10,400) FROM t3;
|
||||
INSERT INTO t3 SELECT randstr(10,400) FROM t3;
|
||||
INSERT INTO t3 SELECT randstr(10,400) FROM t3;
|
||||
INSERT INTO t3 SELECT randstr(10,400) FROM t3;
|
||||
INSERT INTO t3 SELECT randstr(10,400) FROM t3;
|
||||
INSERT INTO t3 SELECT randstr(10,400) FROM t3;
|
||||
INSERT INTO t3 SELECT randstr(10,400) FROM t3;
|
||||
INSERT INTO t3 SELECT randstr(10,400) FROM t3;
|
||||
COMMIT;
|
||||
SELECT count(*) FROM t3;
|
||||
}
|
||||
} {1024}
|
||||
set sig [signature]
|
||||
do_test exclusive-4.1 {
|
||||
execsql {
|
||||
BEGIN;
|
||||
DELETE FROM t3 WHERE random()%10!=0;
|
||||
INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
|
||||
INSERT INTO t3 SELECT randstr(10,10)||x FROM t3;
|
||||
ROLLBACK;
|
||||
}
|
||||
signature
|
||||
} $sig
|
||||
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this script is database locks.
|
||||
#
|
||||
# $Id: trans.test,v 1.32 2006/06/20 11:01:09 danielk1977 Exp $
|
||||
# $Id: trans.test,v 1.33 2007/03/24 16:45:05 danielk1977 Exp $
|
||||
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
|
@ -815,6 +815,7 @@ do_test trans-9.1 {
|
|||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
# execsql { PRAGMA locking_mode = exclusive; }
|
||||
execsql {
|
||||
BEGIN;
|
||||
CREATE TABLE t3(x TEXT);
|
||||
|
|
Loading…
Reference in New Issue