From cb4c40ba0ecd7fe5e3542f421ba119855052443e Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 18 Aug 2004 19:09:43 +0000 Subject: [PATCH] Make sure the database file is correctly truncated after a ROLLBACK that occurs after a statement abort. (CVS 1893) FossilOrigin-Name: 6afe467d146828d67ad17af21604c2e691aa5dff --- manifest | 13 ++++----- manifest.uuid | 2 +- src/pager.c | 22 +++++++++++----- test/pager3.test | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 13 deletions(-) create mode 100644 test/pager3.test diff --git a/manifest b/manifest index ce16a02589..4ff1c37354 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Better\sdebug\slogging\sof\sthe\spager.\s(CVS\s1892) -D 2004-08-18T16:05:19 +C Make\ssure\sthe\sdatabase\sfile\sis\scorrectly\struncated\safter\sa\sROLLBACK\sthat\noccurs\safter\sa\sstatement\sabort.\s(CVS\s1893) +D 2004-08-18T19:09:44 F Makefile.in 4a5e570a9e2d35b09c31b3cf01b78cea764ade4b F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -51,7 +51,7 @@ F src/os_unix.c 3239a45dbd2f50195bfc97f1ed35cb8fe5a3f60c F src/os_unix.h f3097815e041e82e24d92505e1ff61ba24172d13 F src/os_win.c 54181eb73cb4783c4241feca9eaa490768b39008 F src/os_win.h babd4e912967c6b09088cfe38a45e8005a07ba44 -F src/pager.c 6f36dae72437a16bd8a40ac2541b6966b5bc9b98 +F src/pager.c f42404ba6858cb3744deca6bb764af6f4ed0275e F src/pager.h 67739fe649f33be55dba522ca8a9cc4e42d14f71 F src/parse.y 589b1a39b23092888adfa9ec1f3ded8a35e8e006 F src/pragma.c 5cf335adfdac453a2d03ab0c82f93847c43bea81 @@ -147,6 +147,7 @@ F test/notnull.test 7a08117a71e74b0321aaa937dbeb41a09d6eb1d0 F test/null.test c14d0f4739f21e929b8115b72bf0c765b6bb1721 F test/pager.test 059cc5c58d3b5a851343dff8c56cf7286425d03a F test/pager2.test 55469c7c1c1a54d6b32d7b3cc99001e90101a1ce +F test/pager3.test 16f546293bb751b8151dc17df613fca938bbec8b F test/pragma.test 66a66b7f3b273b93325c9a5794acb418f52fdcbf F test/printf.test 5a30fb0d736148fca64cb1b7ed0390be7414e024 F test/progress.test 76c722f090b1ccb575e7e4e203a71608c5763beb x @@ -242,7 +243,7 @@ F www/tclsqlite.tcl 06a86cba4d7fc88e2bcd633b57702d3d16abebb5 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P 6b2b6b2dbd821070a2781685c4b63a50bc8f5cae -R 7a82009cfca716de658bd46e436375ca +P 1cc0323f2597584b3f3239e8948ac3ff3db8da03 +R 2c16cf3adea0061c2a5685694da75e5b U drh -Z 7be61bbeb15fa842d9f627b0bce20f13 +Z 53449f732f05d53766a7cbf7eda7107f diff --git a/manifest.uuid b/manifest.uuid index 2cc621a71a..722674a0b0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1cc0323f2597584b3f3239e8948ac3ff3db8da03 \ No newline at end of file +6afe467d146828d67ad17af21604c2e691aa5dff \ No newline at end of file diff --git a/src/pager.c b/src/pager.c index 435673e43e..e37407028c 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.157 2004/08/18 16:05:19 drh Exp $ +** @(#) $Id: pager.c,v 1.158 2004/08/18 19:09:44 drh Exp $ */ #include "os.h" /* Must be first to enable large file support */ #include "sqliteInt.h" @@ -1017,6 +1017,14 @@ static int pager_reload_cache(Pager *pPager){ return rc; } +/* +** Truncate the main file of the given pager to the number of pages +** indicated. +*/ +static int pager_truncate(Pager *pPager, int nPage){ + return sqlite3OsTruncate(&pPager->fd, pPager->pageSize*(off_t)nPage); +} + /* ** Playback the journal and thus restore the database file to ** the state it was in before we started making changes. @@ -1135,7 +1143,7 @@ static int pager_playback(Pager *pPager){ */ if( pPager->journalOff==JOURNAL_HDR_SZ(pPager) ){ assert( pPager->origDbSize==0 || pPager->origDbSize==mxPg ); - rc = sqlite3OsTruncate(&pPager->fd, pPager->pageSize*(off_t)mxPg); + rc = pager_truncate(pPager, mxPg); if( rc!=SQLITE_OK ){ goto end_playback; } @@ -1235,7 +1243,7 @@ static int pager_stmt_playback(Pager *pPager){ /* Truncate the database back to its original size. */ - rc = sqlite3OsTruncate(&pPager->fd, pPager->pageSize*(off_t)pPager->stmtSize); + rc = pager_truncate(pPager, pPager->stmtSize); pPager->dbSize = pPager->stmtSize; /* Figure out how many records are in the statement journal. @@ -1673,7 +1681,7 @@ int sqlite3pager_truncate(Pager *pPager, Pgno nPage){ if( rc!=SQLITE_OK ){ return rc; } - rc = sqlite3OsTruncate(&pPager->fd, pPager->pageSize*(off_t)nPage); + rc = pager_truncate(pPager, nPage); if( rc==SQLITE_OK ){ pPager->dbSize = nPage; } @@ -2860,11 +2868,13 @@ int sqlite3pager_rollback(Pager *pPager){ return pager_errcode(pPager); } if( pPager->state==PAGER_RESERVED ){ - int rc2; + int rc2, rc3; rc = pager_reload_cache(pPager); - rc2 = pager_unwritelock(pPager); + rc2 = pager_truncate(pPager, pPager->origDbSize); + rc3 = pager_unwritelock(pPager); if( rc==SQLITE_OK ){ rc = rc2; + if( rc3 ) rc = rc3; } }else{ rc = pager_playback(pPager); diff --git a/test/pager3.test b/test/pager3.test new file mode 100644 index 0000000000..cfee6b6f49 --- /dev/null +++ b/test/pager3.test @@ -0,0 +1,68 @@ +# 2001 September 15 +# +# 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. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. The +# focus of this script is page cache subsystem. +# +# $Id: pager3.test,v 1.1 2004/08/18 19:09:44 drh Exp $ + + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +# This test makes sure the database file is truncated back to the correct +# length on a rollback. +# +# After some preliminary setup, a transaction is start at NOTE (1). +# The create table on the following line allocates an additional page +# at the end of the database file. But that page is not written because +# the database still has a RESERVED lock, not an EXCLUSIVE lock. The +# new page is held in memory and the size of the file is unchanged. +# The insert at NOTE (2) begins adding additional pages. Then it hits +# a constraint error and aborts. The abort causes sqlite3OsTruncate() +# to be called to restore the file to the same length as it was after +# the create table. But the create table results had not yet been +# written so the file is actually lengthened by this truncate. Finally, +# the rollback at NOTE (3) is called to undo all the changes since the +# begin. This rollback should truncate the database again. +# +# This test was added because the second truncate at NOTE (3) was not +# occurring on early versions of SQLite 3.0. +# +do_test pager3-1.1 { + execsql { + create table t1(a unique, b); + insert into t1 values(1, 'abcdefghijklmnopqrstuvwxyz'); + insert into t1 values(2, 'abcdefghijklmnopqrstuvwxyz'); + update t1 set b=b||a||b; + update t1 set b=b||a||b; + update t1 set b=b||a||b; + update t1 set b=b||a||b; + update t1 set b=b||a||b; + update t1 set b=b||a||b; + create temp table t2 as select * from t1; + begin; ------- NOTE (1) + create table t3(x); + } + catchsql { + insert into t1 select 4-a, b from t2; ----- NOTE (2) + } + execsql { + rollback; ------- NOTE (3) + } + db close + sqlite3 db test.db + execsql { + pragma integrity_check; + } +} ok + + +finish_test