-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
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
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
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
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
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
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
-07b56965f3227c9f78680728b955395295c4aa49
\ No newline at end of file
+b6c700370be29db2b974f9abd719c3e56abf8058
\ No newline at end of file
*************************************************************************
** 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"
"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;
** 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"
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 */
};
/*
** 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;
}
/*
sqlite3PagerRollback(pPager);
}
pager_unlock(pPager);
- assert( pPager->errCode || (pPager->journalOpen==0 && pPager->stmtOpen==0) );
}
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
*/
static int pager_unwritelock(Pager *pPager){
PgHdr *pPg;
- int rc;
+ int rc = SQLITE_OK;
assert( !MEMDB );
if( pPager->state<PAGER_RESERVED ){
return SQLITE_OK;
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
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;
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;
}
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.
pPager->pDirty = 0;
return rc;
}
+#endif
/*
** Truncate the main file of the given pager to the number of pages
disable_simulated_io_errors();
pPager->errCode = 0;
+ pPager->exclusiveMode = 0;
pager_reset(pPager);
pagerUnlockAndRollback(pPager);
enable_simulated_io_errors();
pPager->nRef--;
if( iChangeCount!=pPager->iChangeCount ){
pager_reset(pPager);
- }else{
- pagerSoftReset(pPager);
}
pPager->iChangeCount = iChangeCount;
}
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;
/* Release the page reference. */
sqlite3PagerUnref(pPgHdr);
+ pPager->changeCountDone = 1;
return SQLITE_OK;
}
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.
** 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_
#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
void *sqlite3PagerGetData(DbPage *);
void *sqlite3PagerGetExtra(DbPage *);
+int sqlite3PagerLockingMode(Pager *, int);
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
int sqlite3PagerLockstate(Pager*);
*************************************************************************
** 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"
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
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 */
/*
*************************************************************************
** 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_
#ifdef SQLITE_SSE
sqlite3_stmt *pFetch; /* Used by SSE to fetch stored statements */
#endif
+ u8 dfltLockMode; /* Default locking-mode for attached dbs */
};
/*
--- /dev/null
+# 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
+
# 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]
}
db close
sqlite3 db test.db
+ # execsql { PRAGMA locking_mode = exclusive; }
execsql {
BEGIN;
CREATE TABLE t3(x TEXT);