Index: src/btree.c ================================================================== --- src/btree.c +++ src/btree.c @@ -8524,5 +8524,12 @@ */ void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){ assert( mask==BTREE_BULKLOAD || mask==0 ); pCsr->hints = mask; } + +/* +** Return true if the given Btree is read-only. +*/ +int sqlite3BtreeIsReadonly(Btree *p){ + return (p->pBt->btsFlags & BTS_READ_ONLY)!=0; +} Index: src/btree.h ================================================================== --- src/btree.h +++ src/btree.h @@ -192,10 +192,11 @@ int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); void sqlite3BtreeIncrblobCursor(BtCursor *); void sqlite3BtreeClearCursor(BtCursor *); int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask); +int sqlite3BtreeIsReadonly(Btree *pBt); #ifndef NDEBUG int sqlite3BtreeCursorIsValid(BtCursor*); #endif Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -3443,7 +3443,7 @@ ** Return 1 if database is read-only or 0 if read/write. Return -1 if ** no such database exists. */ int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){ Btree *pBt = sqlite3DbNameToBtree(db, zDbName); - return pBt ? sqlite3PagerIsreadonly(sqlite3BtreePager(pBt)) : -1; + return pBt ? sqlite3BtreeIsReadonly(pBt) : -1; } Index: test/rdonly.test ================================================================== --- test/rdonly.test +++ test/rdonly.test @@ -30,10 +30,13 @@ CREATE TABLE t1(x); INSERT INTO t1 VALUES(1); SELECT * FROM t1; } } {1} +do_test rdonly-1.1.1 { + sqlite3_db_readonly db main +} {0} # Changes the write version from 1 to 3. Verify that the database # can be read but not written. # do_test rdonly-1.2 { @@ -45,10 +48,13 @@ sqlite3 db test.db execsql { SELECT * FROM t1; } } {1} +do_test rdonly-1.3.1 { + sqlite3_db_readonly db main +} {1} do_test rdonly-1.4 { catchsql { INSERT INTO t1 VALUES(2) } } {1 {attempt to write a readonly database}}