-C Additional\sgrammar\scleanup\sresulting\sfrom\sthe\s%fallback\sdirective.\s(CVS\s606)
-D 2002-06-06T19:04:16
+C Fix\sfor\sticket\s#62:\sDo\snot\sreport\san\sSQLITE_READONLY\serror\suntil\sthe\sapplication\nactually\stries\sto\swrite\sdata\sinto\sa\sreadonly\sfile.\s\sIt\sis\sOK\sto\sstart\sa\ntransaction\son\sa\sread-only\sfile,\sand\sdoing\sso\swill\sget\syou\sa\sread\slock.\s\sThis\nchange\sallows\sTEMP\stables\sto\sbe\sread/write\seven\sthough\sthe\smain\sdatabase\sis\nreadonly.\s(CVS\s607)
+D 2002-06-06T23:16:05
F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c
F Makefile.template 4e11752e0b5c7a043ca50af4296ec562857ba495
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
F spec.template 238f7db425a78dc1bb7682e56e3834c7270a3f5e
F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea
F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6
-F src/btree.c c01b404b9373ae1c0daf7d1f9211c72ead67638e
+F src/btree.c 8b86be8f234c1c5dab3186f69cee2544ec9d7257
F src/btree.h 8abeabfe6e0b1a990b64fa457592a6482f6674f3
F src/build.c 36e42718a7a94f554ea39508993378482f5335c7
F src/delete.c a2b098cbbf518e6b641847e26de85827793bc523
F src/trigger.c d02f8e3510c7c2ad948a0e8c3bb0cca8adaf80c5
F src/update.c f68375173bf5338cae3e97012708e10f206aedd9
F src/util.c 7cf46b5612f5d12601c697374b9c6b38b2332ce8
-F src/vdbe.c ee08fbae7f7bfc150b5840ce69967c469c440752
+F src/vdbe.c 27b71e3c6cc77c071421b24462872f32047e2c20
F src/vdbe.h b8706429131c14b307a07aab7e47f95a9da53610
F src/where.c b054f2f23127bd57eb5f973bcd38764b875d73fe
F test/all.test e4d3821eeba751829b419cd47814bd20af4286d1
F test/table.test 42511f98a3e9bbee62913e3ae1774777faa23d35
F test/tableapi.test 3c80421a889e1d106df16e5800fa787f0d2914a6
F test/tclsqlite.test 79deeffd7cd637ca0f06c5dbbf2f44d272079533
-F test/temptable.test daa83489eea2e9aaeeece09675c28be84c72cb67
+F test/temptable.test ae58694c0fdd2d0b781508b64adc5aee3416aeed
F test/tester.tcl dc1b56bd628b487e4d75bfd1e7480b5ed8810ac6
F test/trans.test ae0b9a82d5d34122c3a3108781eb8d078091ccee
F test/trigger1.test bb63749fa8a395a60541100607d86381604b7194
F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P 7ac5bd293cbb2bf252f31f1571f7efac7e77280a
-R d4345db261ae090ac6a58373d7650fb9
+P c0cb3a012e02df1a7965413a92f9b5a77331edb4
+R bbf73b9f76e1af31b5358613f061b43c
U drh
-Z a44424a54b4cc26f96d80deba8206afd
+Z 202177a08e619734270177dc9e884211
-c0cb3a012e02df1a7965413a92f9b5a77331edb4
\ No newline at end of file
+9ef795d1d756a404d2123ebc19df1985b19c9888
\ No newline at end of file
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.61 2002/05/15 11:44:14 drh Exp $
+** $Id: btree.c,v 1.62 2002/06/06 23:16:05 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
PageOne *page1; /* First page of the database */
u8 inTrans; /* True if a transaction is in progress */
u8 inCkpt; /* True if there is a checkpoint on the transaction */
+ u8 readOnly; /* True if the underlying file is readonly */
Hash locks; /* Key: root page number. Data: lock count */
};
typedef Btree Bt;
sqlitepager_set_destructor(pBt->pPager, pageDestructor);
pBt->pCursor = 0;
pBt->page1 = 0;
+ pBt->readOnly = sqlitepager_isreadonly(pBt->pPager);
sqliteHashInit(&pBt->locks, SQLITE_HASH_INT, 0);
*ppBtree = pBt;
return SQLITE_OK;
return rc;
}
}
- if( sqlitepager_isreadonly(pBt->pPager) ){
- return SQLITE_READONLY;
- }
- rc = sqlitepager_begin(pBt->page1);
- if( rc==SQLITE_OK ){
- rc = newDatabase(pBt);
+ if( pBt->readOnly ){
+ rc = SQLITE_OK;
+ }else{
+ rc = sqlitepager_begin(pBt->page1);
+ if( rc==SQLITE_OK ){
+ rc = newDatabase(pBt);
+ }
}
if( rc==SQLITE_OK ){
pBt->inTrans = 1;
int sqliteBtreeCommit(Btree *pBt){
int rc;
if( pBt->inTrans==0 ) return SQLITE_ERROR;
- rc = sqlitepager_commit(pBt->pPager);
+ rc = pBt->readOnly ? SQLITE_OK : sqlitepager_commit(pBt->pPager);
pBt->inTrans = 0;
pBt->inCkpt = 0;
unlockBtreeIfUnused(pBt);
pCur->pPage = 0;
}
}
- rc = sqlitepager_rollback(pBt->pPager);
+ rc = pBt->readOnly ? SQLITE_OK : sqlitepager_rollback(pBt->pPager);
unlockBtreeIfUnused(pBt);
return rc;
}
if( !pBt->inTrans || pBt->inCkpt ){
return SQLITE_ERROR;
}
- rc = sqlitepager_ckpt_begin(pBt->pPager);
+ rc = pBt->readOnly ? SQLITE_OK : sqlitepager_ckpt_begin(pBt->pPager);
pBt->inCkpt = 1;
return rc;
}
*/
int sqliteBtreeCommitCkpt(Btree *pBt){
int rc;
- if( pBt->inCkpt ){
+ if( pBt->inCkpt && !pBt->readOnly ){
rc = sqlitepager_ckpt_commit(pBt->pPager);
}else{
rc = SQLITE_OK;
int sqliteBtreeRollbackCkpt(Btree *pBt){
int rc;
BtCursor *pCur;
- if( pBt->inCkpt==0 ) return SQLITE_OK;
+ if( pBt->inCkpt==0 || pBt->readOnly ) return SQLITE_OK;
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
if( pCur->pPage ){
sqlitepager_unref(pCur->pPage);
return rc;
}
}
+ if( wrFlag && pBt->readOnly ){
+ *ppCur = 0;
+ return SQLITE_READONLY;
+ }
pCur = sqliteMalloc( sizeof(*pCur) );
if( pCur==0 ){
rc = SQLITE_NOMEM;
if( !pBt->inTrans ){
return SQLITE_ERROR; /* Must start a transaction first */
}
+ if( pBt->readOnly ){
+ return SQLITE_READONLY;
+ }
rc = allocatePage(pBt, &pRoot, &pgnoRoot);
if( rc ) return rc;
assert( sqlitepager_iswriteable(pRoot) );
** BTree indices are restricted to having an arbitrary key and no data.
*/
int sqliteBtreeCreateIndex(Btree *pBt, int *piIndex){
- MemPage *pRoot;
- Pgno pgnoRoot;
- int rc;
- if( !pBt->inTrans ){
- return SQLITE_ERROR; /* Must start a transaction first */
- }
- rc = allocatePage(pBt, &pRoot, &pgnoRoot);
- if( rc ) return rc;
- assert( sqlitepager_iswriteable(pRoot) );
- zeroPage(pRoot);
- sqlitepager_unref(pRoot);
- *piIndex = (int)pgnoRoot;
- return SQLITE_OK;
+ return sqliteBtreeCreateTable(pBt, piIndex);
}
/*
if( !pBt->inTrans ){
return SQLITE_ERROR; /* Must start a transaction first */
}
+ if( pBt->readOnly ){
+ return SQLITE_READONLY;
+ }
nLock = (ptr)sqliteHashFind(&pBt->locks, 0, iTable);
if( nLock ){
return SQLITE_LOCKED;
if( !pBt->inTrans ){
return SQLITE_ERROR; /* Must start a transaction first */
}
+ if( pBt->readOnly ){
+ return SQLITE_READONLY;
+ }
rc = sqlitepager_get(pBt->pPager, (Pgno)iTable, (void**)&pPage);
if( rc ) return rc;
rc = sqliteBtreeClearTable(pBt, iTable);
if( !pBt->inTrans ){
return SQLITE_ERROR; /* Must start a transaction first */
}
+ if( pBt->readOnly ){
+ return SQLITE_READONLY;
+ }
pP1 = pBt->page1;
rc = sqlitepager_write(pP1);
if( rc ) return rc;
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
-** $Id: vdbe.c,v 1.152 2002/06/01 21:41:10 drh Exp $
+** $Id: vdbe.c,v 1.153 2002/06/06 23:16:06 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
case OE_Rollback: {
sqliteBtreeRollback(pBt);
if( db->pBeTemp ) sqliteBtreeRollback(db->pBeTemp);
- sqliteRollbackInternalChanges(db);
db->flags &= ~SQLITE_InTrans;
db->onError = OE_Default;
break;
if( undoTransOnError ){
sqliteBtreeCommit(pBt);
if( db->pBeTemp ) sqliteBtreeCommit(db->pBeTemp);
- sqliteCommitInternalChanges(db);
db->flags &= ~SQLITE_InTrans;
db->onError = OE_Default;
}
break;
}
}
+ sqliteRollbackInternalChanges(db);
}
sqliteBtreeCommitCkpt(pBt);
if( db->pBeTemp ) sqliteBtreeCommitCkpt(db->pBeTemp);
#
# This file implements tests for temporary tables and indices.
#
-# $Id: temptable.test,v 1.5 2002/05/10 13:14:08 drh Exp $
+# $Id: temptable.test,v 1.6 2002/06/06 23:16:06 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
db2 close
+# Test for correct operation of read-only databases
+#
+do_test temptable-6.1 {
+ execsql {
+ CREATE TABLE t8(x);
+ INSERT INTO t8 VALUES('xyzzy');
+ SELECT * FROM t8;
+ }
+} {xyzzy}
+do_test temptable-6.2 {
+ db close
+ catch {file attributes test.db -permissions 0444}
+ catch {file attributes test.db -readonly 1}
+ sqlite db test.db
+ execsql {
+ SELECT * FROM t8;
+ }
+} {xyzzy}
+do_test temptable-6.3 {
+ catchsql {
+ CREATE TABLE t9(x,y);
+ }
+} {1 {attempt to write a readonly database}}
+do_test temptable-6.4 {
+ catchsql {
+ CREATE TEMP TABLE t9(x,y);
+ }
+} {0 {}}
+do_test temptable-6.5 {
+ catchsql {
+ INSERT INTO t9 VALUES(1,2);
+ SELECT * FROM t9;
+ }
+} {0 {1 2}}
+do_test temptable-6.6 {
+ catchsql {
+ INSERT INTO t8 VALUES('hello');
+ SELECT * FROM t8;
+ }
+} {1 {attempt to write a readonly database}}
+do_test temptable-6.7 {
+ catchsql {
+ SELECT * FROM t8,t9;
+ }
+} {0 {xyzzy 1 2}}
+do_test temptable-6.8 {
+ db close
+ sqlite db test.db
+ catchsql {
+ SELECT * FROM t8,t9;
+ }
+} {1 {no such table: t9}}
+
finish_test