-C Website\schanges\sfor\sversion\s2.8.14.\s(CVS\s1553)
-D 2004-06-09T23:15:22
+C Check\sfor\sschema\supdates\sif\sthe\sparser\sfails\sto\sfind\sa\stable.\s\sMore\slocking\ntest\supdates.\s(CVS\s1555)
+D 2004-06-10T00:29:09
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
F src/auth.c 5c2f0bea4729c98c2be3b69d6b466fc51448fe79
F src/btree.c 281af87aa117de024f5b6c2728a2339cba9ef584
F src/btree.h 589427ac13bb544d298cd99726e2572a6fe4bdaa
-F src/build.c 4ea78aba171f02b96254dd7a312e4266d3693bfe
+F src/build.c 9ee417777c8d1be293773482c28adbf5cd59981b
F src/date.c 8e6fa3173386fb29fdef012ee08a853c1e9908b2
F src/delete.c b30f08250c9ed53a25a13c7c04599c1e8753992d
F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37
F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb
F src/insert.c 4268d9e3959cc845ea243fb4ec7507269404dad9
F src/legacy.c ad23746f15f67e34577621b1875f639c94839e1f
-F src/main.c 3df17ac486ff1772af8b537cf0bbd0aabba6e863
+F src/main.c 185b7bbac8bbc341b7b6028625c569a651a7fdd6
F src/md5.c 4302e84ae516c616bb079c4e6d038c0addb33481
F src/os.h 23c69c5084e71b5fe199ff1c4e35a4aded0f1380
F src/os_common.h 6393ac67a3a7b4aea19ff17529980ecf77eb2348
F src/select.c 1f8355e702f109f6771f82a9bfe7aac4c82cbaf2
F src/shell.c ca519519dcbbc582f6d88f7d0e7583b857fd3469
F src/sqlite.h.in 6ad05abc7fd72da74691e1eb45f0eff4117eba4e
-F src/sqliteInt.h f384e81fa635b6323aa6297011d9dc2d976868fb
+F src/sqliteInt.h 52b73ec6ebd5fe342cc15007771c63ccaf767cbe
F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2
F src/tclsqlite.c f5c5116720baefb7de5d6acf18baedf1e42756cc
F src/test1.c f78d6ac0675bc5db48dac9c5379c965bdadb9113
F test/lastinsert.test 31382f88b9b0270333ac9e4a17f2c2f4732da718
F test/laststmtchanges.test cabd11bdfbaf73a4486c50b58297d9c2038ccc18
F test/limit.test 60d7f856ee7846f7130dee67f10f0e726cd70b5d
-F test/lock.test bf3beb32eb792dd328c499c57b81a7fc15024d53
+F test/lock.test 65b98e8812489e157a2bd51fb44c520f6bc76e32
F test/main.test 6a851b5992c4881a725a3d9647e629199df8de9d
F test/malloc.test 4e19b96d9cd7d61f4826e6fce03849ad5ad526dd
F test/memdb.test befe8f26d430d07ba65692243a893a0e82a0b866
F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P 39b4ba95c4a16b28b5e8c7a3331e09cb5796e258
-R 44b229b6f9f8c0c03939e9b1fc2349f9
+P 73afa14a04e8aa22de71aac7d08abc0ec68dc327
+R 4a457b2bb951374d999015f4602a5043
U drh
-Z 46184513a3c8accdddcddf8998ee3516
+Z 0642bdc31cc4198c64ee7082ebf04a73
-73afa14a04e8aa22de71aac7d08abc0ec68dc327
\ No newline at end of file
+a22283512afe2df09d5783d189fbd7389ed313ad
\ No newline at end of file
** ROLLBACK
** PRAGMA
**
-** $Id: build.c,v 1.212 2004/06/09 12:30:05 danielk1977 Exp $
+** $Id: build.c,v 1.213 2004/06/10 00:29:09 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
}else{
sqlite3ErrorMsg(pParse, "no such table: %s", zName);
}
+ pParse->checkSchema = 1;
}
return p;
}
sqliteFree(zName);
if( pTab==0 ){
sqlite3ErrorMsg(pParse, "no such table: %T", pTok);
+ pParse->checkSchema = 1;
}
return pTab;
}
pIndex = sqlite3FindIndex(db, pName->a[0].zName, pName->a[0].zDatabase);
if( pIndex==0 ){
sqlite3ErrorMsg(pParse, "no such index: %S", pName, 0);
+ pParse->checkSchema = 1;
goto exit_drop_index;
}
if( pIndex->autoIndex ){
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: main.c,v 1.210 2004/06/09 20:03:09 drh Exp $
+** $Id: main.c,v 1.211 2004/06/10 00:29:09 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
return db->errCode;
}
+/*
+** Check schema cookies in all databases except TEMP. If any cookie is out
+** of date, return 0. If all schema cookies are current, return 1.
+*/
+static int schemaIsValid(sqlite *db){
+ int iDb;
+ int rc;
+ BtCursor *curTemp;
+ int cookie;
+ int allOk = 1;
+
+ for(iDb=0; allOk && iDb<db->nDb; iDb++){
+ Btree *pBt;
+ if( iDb==1 ) continue;
+ pBt = db->aDb[iDb].pBt;
+ if( pBt==0 ) continue;
+ rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, 0, &curTemp);
+ if( rc==SQLITE_OK ){
+ rc = sqlite3BtreeGetMeta(pBt, 1, &cookie);
+ if( rc==SQLITE_OK && cookie!=db->aDb[iDb].schema_cookie ){
+ allOk = 0;
+ }
+ sqlite3BtreeCloseCursor(curTemp);
+ }
+ }
+ return allOk;
+}
+
/*
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
*/
goto prepare_out;
}
if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
+ if( sParse.checkSchema && !schemaIsValid(db) ){
+ sParse.rc = SQLITE_SCHEMA;
+ }
if( sParse.rc==SQLITE_SCHEMA ){
sqlite3ResetInternalSchema(db, 0);
}
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.276 2004/06/09 20:03:09 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.277 2004/06/10 00:29:10 drh Exp $
*/
#include "config.h"
#include "sqlite3.h"
u8 nameClash; /* A permanent table name clashes with temp table name */
u8 useAgg; /* If true, extract field values from the aggregator
** while generating expressions. Normally false */
+ u8 checkSchema; /* Causes schema cookie check after an error */
int nErr; /* Number of errors seen */
int nTab; /* Number of previously allocated VDBE cursors */
int nMem; /* Number of memory cells used so far */
# This file implements regression tests for SQLite library. The
# focus of this script is database locks.
#
-# $Id: lock.test,v 1.22 2004/06/09 23:15:22 drh Exp $
+# $Id: lock.test,v 1.23 2004/06/10 00:29:12 drh Exp $
set testdir [file dirname $argv0]
catchsql {SELECT * FROM t1} db2
} {1 {no such table: t1}}
do_test lock-1.7.2 {
- execsql {SELECT * FROM sqlite_master LIMIT 1} db2
catchsql {SELECT * FROM t1} db2
} {0 {1 2}}
do_test lock-1.8 {
} {2 1}
do_test lock-1.11 {
catchsql {SELECT * FROM t1} db2
-} {1 {database is locked}}
+} {0 {2 1}}
do_test lock-1.12 {
execsql {ROLLBACK}
catchsql {SELECT * FROM t1}
integrity_check lock-1.23
# If one thread has a transaction another thread cannot start
-# a transaction.
+# a transaction. -> Not true in version 3.0. But if one thread
+# as a RESERVED lock another thread cannot acquire one.
#
do_test lock-2.1 {
execsql {BEGIN TRANSACTION}
lappend r $msg
} {1 {database is locked}}
-# Nor can the other thread do a query.
+# A thread can read when another has a RESERVED lock.
#
do_test lock-2.2 {
- set r [catch {execsql {SELECT * FROM t2} db2} msg]
- lappend r $msg
-} {1 {database is locked}}
+ catchsql {SELECT * FROM t2} db2
+} {0 {9 8}}
-# If the other thread (the one that does not hold the transaction)
-# tries to start a transaction, we get a busy callback.
+# If the other thread (the one that does not hold the transaction with
+# a RESERVED lock) tries to get a RESERVED lock, we get a busy callback.
#
do_test lock-2.3 {
proc callback {args} {
}
set ::callback_value {}
db2 busy callback
- set r [catch {execsql {BEGIN TRANSACTION} db2} msg]
+ set r [catch {execsql {UPDATE t1 SET a=b, b=a} db2} msg]
lappend r $msg
lappend r $::callback_value
} {1 {database is locked} {{} 1}}
}
set ::callback_value {}
db2 busy callback
- set r [catch {execsql {BEGIN TRANSACTION} db2} msg]
+ set r [catch {execsql {UPDATE t1 SET a=b, b=a} db2} msg]
lappend r $msg
lappend r $::callback_value
} {1 {database is locked} {1 2 3 4 5}}
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}}
+} {0 {2 1} {}}
# In this test, the 3rd invocation of the busy callback causes
# the first thread to release its transaction. That allows the
set r [catch {execsql {SELECT * FROM t2} db2} msg]
lappend r $msg
lappend r $::callback_value
-} {0 {9 8} {1 2 3}}
+} {0 {9 8} {}}
do_test lock-2.7 {
- execsql {BEGIN TRANSACTION}
- execsql {UPDATE t1 SET a = 0 WHERE 0}
proc callback {file count} {
lappend ::callback_value $count
if {$count>2} {
db eval BEGIN
db eval {UPDATE t1 SET a=0 WHERE 0}
sqlite db2 ./test.db
- set rc [catch {db2 eval {SELECT * FROM t1}} msg]
- lappend rc $msg
+ catchsql {UPDATE t1 SET a=0} db2
} {1 {database is locked}}
do_test lock-4.2 {
set ::callback_value {}
- set rc [catch {db2 eval {SELECT * FROM t1}} msg]
+ set rc [catch {db2 eval {UPDATE t1 SET a=0}} msg]
lappend rc $msg $::callback_value
} {1 {database is locked} {}}
do_test lock-4.3 {
if {$count>4} break
}
db2 busy callback
- set rc [catch {db2 eval {SELECT * FROM t1}} msg]
+ set rc [catch {db2 eval {UPDATE t1 SET a=0}} msg]
lappend rc $msg $::callback_value
} {1 {database is locked} {1 2 3 4 5}}
execsql {ROLLBACK}
# When one thread is writing, other threads cannot read. Except if the
# writing thread is writing to its temporary tables, the other threads
-# can still read.
+# can still read. -> Not so in 3.0. One thread can read while another
+# holds a RESERVED lock.
#
proc tx_exec {sql} {
db2 eval $sql
catchsql {
INSERT INTO t1(a,b) SELECT 3, tx_exec('SELECT y FROM t2 LIMIT 1');
}
-} {1 {database is locked}}
+} {0 {}}
do_test lock-5.3 {
execsql {
CREATE TEMP TABLE t3(x);
catchsql {
UPDATE t1 SET a=tx_exec('SELECT x FROM t2');
}
-} {1 {database is locked}}
+} {0 {}}
do_test lock-5.7 {
execsql {
SELECT * FROM t1;
}
-} {2 1}
+} {9 1 9 8}
do_test lock-5.8 {
catchsql {
UPDATE t3 SET x=tx_exec('SELECT x FROM t2');