diff --git a/manifest b/manifest index a5fef54ace..8c4ccf6e9e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -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 @@ -18,7 +18,7 @@ F publish.sh d115bd49631e3bb0d799e7dc1da51f9866d67647 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 @@ -52,7 +52,7 @@ F src/tokenize.c 35c63867d03fcaf81fe520f8d8206981d0c7270e 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 @@ -98,7 +98,7 @@ F test/subselect.test f3bc1dcbddddcea08d818fcff75228ad3464fc83 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 @@ -136,7 +136,7 @@ F www/speed.tcl da8afcc1d3ccc5696cfb388a68982bc3d9f7f00f 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 diff --git a/manifest.uuid b/manifest.uuid index 3971952eed..4ca4d416d2 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c0cb3a012e02df1a7965413a92f9b5a77331edb4 \ No newline at end of file +9ef795d1d756a404d2123ebc19df1985b19c9888 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index f096e5f625..6eb5b96cc2 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** 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 @@ -317,6 +317,7 @@ struct Btree { 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; @@ -630,6 +631,7 @@ int sqliteBtreeOpen( 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; @@ -771,12 +773,13 @@ int sqliteBtreeBeginTrans(Btree *pBt){ 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; @@ -796,7 +799,7 @@ int sqliteBtreeBeginTrans(Btree *pBt){ 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); @@ -824,7 +827,7 @@ int sqliteBtreeRollback(Btree *pBt){ pCur->pPage = 0; } } - rc = sqlitepager_rollback(pBt->pPager); + rc = pBt->readOnly ? SQLITE_OK : sqlitepager_rollback(pBt->pPager); unlockBtreeIfUnused(pBt); return rc; } @@ -844,7 +847,7 @@ int sqliteBtreeBeginCkpt(Btree *pBt){ 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; } @@ -856,7 +859,7 @@ int sqliteBtreeBeginCkpt(Btree *pBt){ */ int sqliteBtreeCommitCkpt(Btree *pBt){ int rc; - if( pBt->inCkpt ){ + if( pBt->inCkpt && !pBt->readOnly ){ rc = sqlitepager_ckpt_commit(pBt->pPager); }else{ rc = SQLITE_OK; @@ -876,7 +879,7 @@ int sqliteBtreeCommitCkpt(Btree *pBt){ 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); @@ -916,6 +919,10 @@ int sqliteBtreeCursor(Btree *pBt, int iTable, int wrFlag, BtCursor **ppCur){ return rc; } } + if( wrFlag && pBt->readOnly ){ + *ppCur = 0; + return SQLITE_READONLY; + } pCur = sqliteMalloc( sizeof(*pCur) ); if( pCur==0 ){ rc = SQLITE_NOMEM; @@ -2422,6 +2429,9 @@ int sqliteBtreeCreateTable(Btree *pBt, int *piTable){ 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) ); @@ -2441,19 +2451,7 @@ int sqliteBtreeCreateTable(Btree *pBt, int *piTable){ ** 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); } /* @@ -2503,6 +2501,9 @@ int sqliteBtreeClearTable(Btree *pBt, int iTable){ 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; @@ -2525,6 +2526,9 @@ int sqliteBtreeDropTable(Btree *pBt, int iTable){ 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); @@ -2562,6 +2566,9 @@ int sqliteBtreeUpdateMeta(Btree *pBt, int *aMeta){ 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; diff --git a/src/vdbe.c b/src/vdbe.c index d3cce40b05..032b39a769 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -30,7 +30,7 @@ ** 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 @@ -4864,7 +4864,6 @@ cleanup: case OE_Rollback: { sqliteBtreeRollback(pBt); if( db->pBeTemp ) sqliteBtreeRollback(db->pBeTemp); - sqliteRollbackInternalChanges(db); db->flags &= ~SQLITE_InTrans; db->onError = OE_Default; break; @@ -4873,13 +4872,13 @@ cleanup: 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); diff --git a/test/temptable.test b/test/temptable.test index 01d66dc812..7e7d9b59e3 100644 --- a/test/temptable.test +++ b/test/temptable.test @@ -12,7 +12,7 @@ # # 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 @@ -299,4 +299,57 @@ do_test temptable-5.9 { 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