Index: src/attach.c ================================================================== --- src/attach.c +++ src/attach.c @@ -141,12 +141,10 @@ "attached databases must use the same text encoding as main database"); rc = SQLITE_ERROR; } pPager = sqlite3BtreePager(aNew->pBt); sqlite3PagerLockingMode(pPager, db->dfltLockMode); - /* journal_mode set by the OP_JournalMode opcode that will following - ** the OP_Function opcode that invoked this function. */ sqlite3BtreeSecureDelete(aNew->pBt, sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) ); } aNew->safety_level = 3; aNew->zName = sqlite3DbStrDup(db, zName); @@ -338,21 +336,10 @@ sqlite3VdbeAddOp3(v, OP_Function, 0, regArgs+3-pFunc->nArg, regArgs+3); assert( pFunc->nArg==-1 || (pFunc->nArg&0xff)==pFunc->nArg ); sqlite3VdbeChangeP5(v, (u8)(pFunc->nArg)); sqlite3VdbeChangeP4(v, -1, (char *)pFunc, P4_FUNCDEF); - if( type==SQLITE_ATTACH ){ - /* On an attach, also set the journal mode. Note that - ** sqlite3VdbeUsesBtree() is not call here since the iDb index - ** will be out of range prior to the new database being attached. - ** The OP_JournalMode opcode will all sqlite3VdbeUsesBtree() for us. - */ - sqlite3VdbeAddOp3(v, OP_JournalMode, db->nDb, regArgs+3, - db->dfltJournalMode); - sqlite3VdbeChangeP5(v, 1); - } - /* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this ** statement only). For DETACH, set it to false (expire all existing ** statements). */ sqlite3VdbeAddOp1(v, OP_Expire, (type==SQLITE_ATTACH)); Index: src/build.c ================================================================== --- src/build.c +++ src/build.c @@ -3421,11 +3421,10 @@ assert( db->aDb[1].pSchema ); if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){ db->mallocFailed = 1; return 1; } - sqlite3PagerSetJournalMode(sqlite3BtreePager(pBt), db->dfltJournalMode); } return 0; } /* Index: src/pragma.c ================================================================== --- src/pragma.c +++ src/pragma.c @@ -533,62 +533,49 @@ ** PRAGMA [database.]journal_mode ** PRAGMA [database.]journal_mode = ** (delete|persist|off|truncate|memory|wal|off) */ if( sqlite3StrICmp(zLeft,"journal_mode")==0 ){ - int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */ + int eMode; /* One of the PAGER_JOURNALMODE_XXX symbols */ + int ii; /* Loop counter */ + /* Force the schema to be loaded on all databases. This cases all + ** database files to be opened and the journal_modes set. */ if( sqlite3ReadSchema(pParse) ){ goto pragma_out; } sqlite3VdbeSetNumCols(v, 1); sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "journal_mode", SQLITE_STATIC); if( zRight==0 ){ + /* If there is no "=MODE" part of the pragma, do a query for the + ** current mode */ eMode = PAGER_JOURNALMODE_QUERY; }else{ const char *zMode; int n = sqlite3Strlen30(zRight); for(eMode=0; (zMode = sqlite3JournalModename(eMode))!=0; eMode++){ if( sqlite3StrNICmp(zRight, zMode, n)==0 ) break; } if( !zMode ){ + /* If the "=MODE" part does not match any known journal mode, + ** then do a query */ eMode = PAGER_JOURNALMODE_QUERY; } } - if( pId2->n==0 && eMode==PAGER_JOURNALMODE_QUERY ){ - /* Simple "PRAGMA journal_mode;" statement. This is a query for - ** the current default journal mode (which may be different to - ** the journal-mode of the main database). - */ - eMode = db->dfltJournalMode; - sqlite3VdbeAddOp2(v, OP_String8, 0, 1); - sqlite3VdbeChangeP4(v, -1, sqlite3JournalModename(eMode), P4_STATIC); - }else{ - int ii; - - if( pId2->n==0 ){ - /* When there is no database name before the "journal_mode" keyword - ** in the PRAGMA, then the journal-mode will be set on - ** all attached databases, as well as the main db file. - ** - ** Also, the sqlite3.dfltJournalMode variable is set so that - ** any subsequently attached databases also use the specified - ** journal mode. - */ - db->dfltJournalMode = (u8)eMode; - } - - for(ii=db->nDb-1; ii>=0; ii--){ - if( db->aDb[ii].pBt && (ii==iDb || pId2->n==0) ){ - sqlite3VdbeUsesBtree(v, ii); - sqlite3VdbeAddOp3(v, OP_JournalMode, ii, 1, eMode); - } - } - } - + if( eMode==PAGER_JOURNALMODE_QUERY && pId2->n==0 ){ + /* Convert "PRAGMA journal_mode" into "PRAGMA main.journal_mode" */ + iDb = 0; + pId2->n = 1; + } + for(ii=db->nDb-1; ii>=0; ii--){ + if( db->aDb[ii].pBt && (ii==iDb || pId2->n==0) ){ + sqlite3VdbeUsesBtree(v, ii); + sqlite3VdbeAddOp3(v, OP_JournalMode, ii, 1, eMode); + } + } sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 1); }else /* ** PRAGMA [database.]journal_size_limit Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -795,11 +795,10 @@ int errMask; /* & result codes with this before returning */ u8 autoCommit; /* The auto-commit flag. */ u8 temp_store; /* 1: file 2: memory 0: default */ u8 mallocFailed; /* True if we have seen a malloc failure */ u8 dfltLockMode; /* Default locking-mode for attached dbs */ - u8 dfltJournalMode; /* Default journal mode for attached dbs */ signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ u8 suppressErr; /* Do not issue error messages if true */ int nextPagesize; /* Pagesize after VACUUM if >0 */ int nTable; /* Number of tables in the database */ CollSeq *pDfltColl; /* The default collating sequence (BINARY) */ Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -5163,15 +5163,10 @@ ** operation. No IO is required. ** ** If changing into or out of WAL mode the procedure is more complicated. ** ** Write a string containing the final journal-mode to register P2. -** -** If an attempt to change in to or out of WAL mode fails because another -** connection also has the same database open, then an SQLITE_BUSY error -** is raised if P5==0, or of P5!=0 the journal mode changed is skipped -** without signaling the error. */ case OP_JournalMode: { /* out2-prerelease */ Btree *pBt; /* Btree to change journal mode of */ Pager *pPager; /* Pager associated with pBt */ int eNew; /* New journal mode */ @@ -5265,11 +5260,10 @@ } } #endif /* ifndef SQLITE_OMIT_WAL */ if( rc ){ - if( rc==SQLITE_BUSY && pOp->p5!=0 ) rc = SQLITE_OK; eNew = eOld; } eNew = sqlite3PagerSetJournalMode(pPager, eNew); pOut = &aMem[pOp->p2]; Index: test/crash8.test ================================================================== --- test/crash8.test +++ test/crash8.test @@ -256,10 +256,11 @@ INSERT INTO ab VALUES(4, NULL); INSERT INTO ab VALUES(5, NULL); INSERT INTO ab VALUES(6, NULL); UPDATE ab SET b = randstr(1000,1000); ATTACH 'test2.db' AS aux; + PRAGMA aux.journal_mode = persist; CREATE TABLE aux.ab(a, b); INSERT INTO aux.ab SELECT * FROM main.ab; UPDATE aux.ab SET b = randstr(1000,1000) WHERE a>=1; UPDATE ab SET b = randstr(1000,1000) WHERE a>=1; Index: test/jrnlmode.test ================================================================== --- test/jrnlmode.test +++ test/jrnlmode.test @@ -130,11 +130,11 @@ } [list off [temp_journal_mode persist] memory] do_test jrnlmode-1.11 { execsql { PRAGMA journal_mode; } - } {persist} + } {off} do_test jrnlmode-1.12 { execsql { ATTACH ':memory:' as aux2; } execsql { @@ -315,13 +315,14 @@ execsql { PRAGMA journal_size_limit } } {-1} do_test jrnlmode-5.3 { execsql { ATTACH 'test2.db' AS aux; + PRAGMA aux.journal_mode=persist; PRAGMA aux.journal_size_limit; } - } {-1} + } {persist -1} do_test jrnlmode-5.4.1 { execsql { PRAGMA aux.journal_size_limit = 999999999999 } } {999999999999} do_test jrnlmode-5.4.2 { execsql { PRAGMA aux.journal_size_limit = 10240 } @@ -335,12 +336,15 @@ do_test jrnlmode-5.7 { execsql { PRAGMA aux.journal_size_limit } } {10240} do_test jrnlmode-5.8 { - execsql { ATTACH 'test3.db' AS aux2 } - } {} + execsql { + ATTACH 'test3.db' AS aux2; + PRAGMA aux2.journal_mode=persist; + } + } {persist} do_test jrnlmode-5.9 { execsql { CREATE TABLE main.t1(a, b, c); CREATE TABLE aux.t2(a, b, c); Index: test/walmode.test ================================================================== --- test/walmode.test +++ test/walmode.test @@ -301,26 +301,26 @@ PRAGMA journal_mode = WAL; CREATE TABLE t1(a, b); } } {wal} foreach {tn sql result} { - 1 "PRAGMA journal_mode" delete + 1 "PRAGMA journal_mode" wal 2 "PRAGMA main.journal_mode" wal 3 "PRAGMA journal_mode = delete" delete 4 "PRAGMA journal_mode" delete 5 "PRAGMA main.journal_mode" delete 6 "PRAGMA journal_mode = wal" wal - 7 "PRAGMA journal_mode" delete + 7 "PRAGMA journal_mode" wal 8 "PRAGMA main.journal_mode" wal - 9 "PRAGMA journal_mode" delete + 9 "PRAGMA journal_mode" wal 10 "PRAGMA main.journal_mode" wal 11 "PRAGMA main.journal_mode = delete" delete 12 "PRAGMA journal_mode" delete 13 "PRAGMA main.journal_mode" delete 14 "PRAGMA main.journal_mode = wal" wal - 15 "PRAGMA journal_mode" delete + 15 "PRAGMA journal_mode" wal 16 "PRAGMA main.journal_mode" wal } { do_test walmode-7.$tn { db close sqlite3 db test.db @@ -339,11 +339,11 @@ PRAGMA journal_mode = WAL; ATTACH 'test.db2' AS two; CREATE TABLE two.t2(a, b); } {wal} do_execsql_test walmode-8.2 { PRAGMA main.journal_mode } {wal} -do_execsql_test walmode-8.3 { PRAGMA two.journal_mode } {wal} +do_execsql_test walmode-8.3 { PRAGMA two.journal_mode } {delete} do_execsql_test walmode-8.4 { PRAGMA two.journal_mode = DELETE } {delete} db close sqlite3 db test.db do_execsql_test walmode-8.5 { ATTACH 'test.db2' AS two } {} @@ -351,11 +351,20 @@ do_execsql_test walmode-8.7 { PRAGMA two.journal_mode } {delete} do_execsql_test walmode-8.8 { INSERT INTO two.t2 DEFAULT VALUES } {} do_execsql_test walmode-8.9 { PRAGMA two.journal_mode } {delete} do_execsql_test walmode-8.10 { INSERT INTO t1 DEFAULT VALUES } {} do_execsql_test walmode-8.11 { PRAGMA main.journal_mode } {wal} -do_execsql_test walmode-8.12 { PRAGMA journal_mode } {delete} +do_execsql_test walmode-8.12 { PRAGMA journal_mode } {wal} + +# Change to WAL mode on test2.db and make sure (in the tests that follow) +# that this mode change persists. +do_test walmode-8.x1 { + execsql { + PRAGMA two.journal_mode=WAL; + PRAGMA two.journal_mode; + } +} {wal wal} db close sqlite3 db test.db do_execsql_test walmode-8.13 { PRAGMA journal_mode = WAL } {wal} do_execsql_test walmode-8.14 { ATTACH 'test.db2' AS two } {} @@ -367,6 +376,5 @@ sqlite3 db2 test.db2 do_test walmode-8.19 { execsql { PRAGMA main.journal_mode } db2 } {wal} db2 close finish_test -