]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Make sure the database file is correctly truncated after a ROLLBACK that
authordrh <drh@noemail.net>
Wed, 18 Aug 2004 19:09:43 +0000 (19:09 +0000)
committerdrh <drh@noemail.net>
Wed, 18 Aug 2004 19:09:43 +0000 (19:09 +0000)
occurs after a statement abort. (CVS 1893)

FossilOrigin-Name: 6afe467d146828d67ad17af21604c2e691aa5dff

manifest
manifest.uuid
src/pager.c
test/pager3.test [new file with mode: 0644]

index ce16a02589edc8610ee614c21e1d3a2c7d75b2a8..4ff1c3735423ba35c8e597fa8d371614e7514605 100644 (file)
--- 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
index 2cc621a71a327d57ff6470b11310ef21d8298971..722674a0b01b345a318b0f740b9745c73be54a1f 100644 (file)
@@ -1 +1 @@
-1cc0323f2597584b3f3239e8948ac3ff3db8da03
\ No newline at end of file
+6afe467d146828d67ad17af21604c2e691aa5dff
\ No newline at end of file
index 435673e43e51cac033e8976d24495936ea6a2625..e37407028c84f2556a9a31a5d8dc0ca493c05fb3 100644 (file)
@@ -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 (file)
index 0000000..cfee6b6
--- /dev/null
@@ -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