From: dan Date: Mon, 8 May 2017 18:29:36 +0000 (+0000) Subject: Do not invoke codec macros when reading or writing an in-memory sub-journal. X-Git-Tag: version-3.19.0~19^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2617c9bdd8e74801961eda4f96294b35403cb2ee;p=thirdparty%2Fsqlite.git Do not invoke codec macros when reading or writing an in-memory sub-journal. FossilOrigin-Name: 2c145ee6c9e7916f022331453384cbe61ee3654c08a1b88467f85235b5bc18c4 --- diff --git a/manifest b/manifest index 564f7eec6f..23d43394be 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\san\sobscure\sassertion\sfault\sthat\scan\sfollow\san\sOOM.\s\s\sThe\sproblem\nwas\sintroduced\sby\scheck-in\s[a1cf44763277b6c7]. -D 2017-05-06T18:09:36.744 +C Do\snot\sinvoke\scodec\smacros\swhen\sreading\sor\swriting\san\sin-memory\ssub-journal. +D 2017-05-08T18:29:36.543 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 6a8c838220f7c00820e1fc0ac1bccaaa8e5676067e1dbfa1bafa7a4ffecf8ae6 @@ -389,7 +389,7 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586 F src/os_unix.c 30e2c43e4955db990e5b5a81e901f8aa74cc8820 F src/os_win.c 2a6c73eef01c51a048cc4ddccd57f981afbec18a F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a -F src/pager.c ff1232b3088a39806035ecfac4fffeb22717d80b +F src/pager.c e00e5844b1d61c0f1a44b09b26ab0be941ac9056c44b5973d8343ce80a3973d8 F src/pager.h f2a99646c5533ffe11afa43e9e0bea74054e4efa F src/parse.y 0513387ce02fea97897d8caef82d45f347818593f24f1bdc48e0c530a8af122d F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870 @@ -1168,6 +1168,7 @@ F test/sqllog.test 6af6cb0b09f4e44e1917e06ce85be7670302517a F test/stat.test f8f1279ffffabe6df825723af18cc6e0ae70a893 F test/statfault.test f525a7bf633e50afd027700e9a486090684b1ac1 F test/stmt.test 64844332db69cf1a735fcb3e11548557fc95392f +F test/subjournal.test 2121a93ef3d3e83d52bf236c8a02aef4009fbf52884754104b2b6cad9a041095 F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f F test/subquery2.test 438f8a7da1457277b22e4176510f7659b286995f F test/subselect.test 0966aa8e720224dbd6a5e769a3ec2a723e332303 @@ -1578,7 +1579,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 198ff4c01d86d193a54745764d69376cab8e94747a4daa444690f7e1ec87800b -R 32100f2588ee0aaab5e52c8f56365f52 -U drh -Z 5b7285d0420627775594602075610fb9 +P 04e7e5650efffdce759b46999beb67c250af6cf394a7779ab861f210a84c134d +R 5b566eb883c6b6910bc0ff6faa539b38 +T *branch * codecless-inmemory-subjournal +T *sym-codecless-inmemory-subjournal * +T -sym-trunk * +U dan +Z f779b45aa1c983a004325ff10b211ada diff --git a/manifest.uuid b/manifest.uuid index e3ee6fe2dc..570c1ee5f4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -04e7e5650efffdce759b46999beb67c250af6cf394a7779ab861f210a84c134d \ No newline at end of file +2c145ee6c9e7916f022331453384cbe61ee3654c08a1b88467f85235b5bc18c4 \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 40c4dd9d88..dc8b31fcff 100644 --- a/src/pager.c +++ b/src/pager.c @@ -2258,6 +2258,7 @@ static int pager_playback_one_page( char *aData; /* Temporary storage for the page */ sqlite3_file *jfd; /* The file descriptor for the journal file */ int isSynced; /* True if journal page is synced */ + const int jrnlEnc = (isMainJrnl || pPager->subjInMemory==0); assert( (isMainJrnl&~1)==0 ); /* isMainJrnl is 0 or 1 */ assert( (isSavepnt&~1)==0 ); /* isSavepnt is 0 or 1 */ @@ -2381,14 +2382,24 @@ static int pager_playback_one_page( i64 ofst = (pgno-1)*(i64)pPager->pageSize; testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 ); assert( !pagerUseWal(pPager) ); + + /* Write the data read from the journal back into the database file. + ** This is usually safe even for an encrypted database - as the data + ** was encrypted before it was written to the journal file. The exception + ** is if the data was just read from an in-memory sub-journal. In that + ** case it must be encrypted here before it is copied into the database + ** file. */ + if( !jrnlEnc ){CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT, aData);} rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst); + if( !jrnlEnc ){CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT);} + if( pgno>pPager->dbFileSize ){ pPager->dbFileSize = pgno; } if( pPager->pBackup ){ - CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT); + if( jrnlEnc ){CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT);} sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData); - CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT, aData); + if( jrnlEnc ){CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT,aData);} } }else if( !isMainJrnl && pPg==0 ){ /* If this is a rollback of a savepoint and data was not written to @@ -2440,7 +2451,7 @@ static int pager_playback_one_page( } /* Decode the page just read from disk */ - CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM_BKPT); + if( jrnlEnc ) CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM_BKPT); sqlite3PcacheRelease(pPg); } return rc; @@ -4453,7 +4464,11 @@ static int subjournalPage(PgHdr *pPg){ i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize); char *pData2; - CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2); + if( pPager->subjInMemory ){ + pData2 = pData; + }else{ + CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2); + } PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno)); rc = write32bits(pPager->sjfd, offset, pPg->pgno); if( rc==SQLITE_OK ){ diff --git a/test/subjournal.test b/test/subjournal.test new file mode 100644 index 0000000000..d4ea643c6e --- /dev/null +++ b/test/subjournal.test @@ -0,0 +1,70 @@ +# 2017 May 9 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix subjournal + +do_execsql_test 1.0 { + PRAGMA temp_store = memory; + CREATE TABLE t1(a,b,c); + INSERT INTO t1 VALUES(1, 2, 3); +} {} +do_execsql_test 1.1 { + BEGIN; + INSERT INTO t1 VALUES(4, 5, 6); + SAVEPOINT one; + INSERT INTO t1 VALUES(7, 8, 9); + ROLLBACK TO one; + SELECT * FROM t1; +} {1 2 3 4 5 6} +do_execsql_test 1.2 { + COMMIT; +} + +do_execsql_test 2.0 { + PRAGMA cache_size = 5; + CREATE TABLE t2(a BLOB); + CREATE INDEX i2 ON t2(a); + WITH s(i) AS ( + SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100 + ) INSERT INTO t2 SELECT randomblob(500) FROM s; +} + +do_test 2.1 { + forcedelete test.db2 + sqlite3 db2 test2.db + sqlite3_backup B db2 main db main + set nPage [db one {PRAGMA page_count}] + B step [expr $nPage-10] +} {SQLITE_OK} + +do_execsql_test 2.2 { + BEGIN; + UPDATE t2 SET a=randomblob(499); + SAVEPOINT two; + UPDATE t2 SET a=randomblob(498); + ROLLBACK TO two; + COMMIT; + PRAGMA integrity_check; +} {ok} + +do_test 2.3 { + B step 1000 +} {SQLITE_DONE} +do_test 2.4 { + B finish + execsql { PRAGMA integrity_check } db2 +} {ok} + +finish_test +