]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Ensure that when the source of a backup is a database that is zero bytes in size...
authordan <dan@noemail.net>
Sat, 13 Oct 2012 19:58:11 +0000 (19:58 +0000)
committerdan <dan@noemail.net>
Sat, 13 Oct 2012 19:58:11 +0000 (19:58 +0000)
FossilOrigin-Name: af5c9ee4a453f71c03f24ad08824ced6c1b97afb

manifest
manifest.uuid
src/backup.c
src/btree.c
src/btree.h
test/backup4.test [new file with mode: 0644]
test/pager1.test

index ca0c8d1cc8c79e9fd5059d45d43aa89a0b60dfbf..fa99540d0a1c09052398a5c0a6af77a1023a3dec 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Allow\sthe\sshowdb\stool\sto\sbe\scompiled\swith\sMSVC.
-D 2012-10-13T09:31:20.156
+C Ensure\sthat\swhen\sthe\ssource\sof\sa\sbackup\sis\sa\sdatabase\sthat\sis\szero\sbytes\sin\ssize,\sthe\sfinal\sdestination\sdatabase\sconsists\sof\sat\sleast\sone\spage.\sTruncating\sit\sto\szero\sbytes\sis\sequivalent\sto\szeroing\sthe\sschema\scookie\sand\schange\scounter,\swhich\scan\scause\sproblems\sfor\sexisting\sclients.
+D 2012-10-13T19:58:11.924
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 5f4f26109f9d80829122e0e09f9cda008fa065fb
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -118,11 +118,11 @@ F src/alter.c f8db986c03eb0bfb221523fc9bbb9d0b70de3168
 F src/analyze.c 7553068d21e32a57fc33ab6b2393fc8c1ba41410
 F src/attach.c 34c15ecd686e58f08e5bb1389e28a0b65c2c83db
 F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
-F src/backup.c afc067b9a9050ff48b9d46285c53d096c556a73d
+F src/backup.c cab40f2c1fe79d6eb93d3b4086c78c41ad2fa5d0
 F src/bitvec.c 26675fe8e431dc555e6f2d0e11e651d172234aa1
 F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
-F src/btree.c 14de53ebb334633ee632ab3c5b9262cfe7cbe455
-F src/btree.h 078f76b28c338ab6eb6dd7324d63ee54463aeb6c
+F src/btree.c 299377f0793038ad3ea322907fbda7fbea615094
+F src/btree.h 3ad7964d6c5b1c7bff569aab6adfa075f8bf06cd
 F src/btreeInt.h 4e5c2bd0f9b36b2a815a6d84f771a61a65830621
 F src/build.c f35dac52924a6e8e6346a90f0c195a84e28b6f21
 F src/callback.c d7e46f40c3cf53c43550b7da7a1d0479910b62cc
@@ -289,6 +289,7 @@ F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
 F test/backcompat.test ecd841f3a3bfb81518721879cc56a760670e3198
 F test/backup.test c9cdd23a495864b9edf75a9fa66f5cb7e10fcf62
 F test/backup2.test 34986ef926ea522911a51dfdb2f8e99b7b75ebcf
+F test/backup4.test cd78366929236357d3b36cbec768a67258817830
 F test/backup_ioerr.test 40d208bc9224b666ee3ed423f49bc9062a36a9d0
 F test/backup_malloc.test 7162d604ec2b4683c4b3799a48657fb8b5e2d450
 F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
@@ -637,7 +638,7 @@ F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
 F test/orderby1.test ef4f7c40df81b9a4303a718433d34052f07db47d
 F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
 F test/oserror.test 50417780d0e0d7cd23cf12a8277bb44024765df3
-F test/pager1.test 2163c6ef119f497a71a84137c957c63763e640ab
+F test/pager1.test 07116f72a61960b882952e7472cc2846d161d6e2
 F test/pager2.test 745b911dde3d1f24ae0870bd433dfa83d7c658c1
 F test/pager3.test 3856d9c80839be0668efee1b74811b1b7f7fc95f
 F test/pagerfault.test 452f2cc23e3bfcfa935f4442aec1da4fe1dc0442
@@ -1019,7 +1020,10 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
 F tool/win/sqlite.vsix 67d8a99aceb56384a81b3f30d6c71743146d2cc9
-P de784399ed1f0e27fc875e32719643d19819c8fb
-R eae4686c36e29e07358a0f64b1678cc7
-U mistachkin
-Z 3d1371a2f131ddfec977348963d5fb7d
+P dce391fc6302301e9ac53a5e4fc69f3bd7ba13a7
+R d0a8a8a7a76a5a8279230581af3ba8e0
+T *branch * zero-byte-backup-fix
+T *sym-zero-byte-backup-fix *
+T -sym-trunk *
+U dan
+Z 43bd238d77d2ace9bdb6f46c1f518da4
index 3bf3a778759a2d753dd1861ebb1f3bb60ffebc36..b142990ca53146c2e12a54ba0f17c4676fa7193e 100644 (file)
@@ -1 +1 @@
-dce391fc6302301e9ac53a5e4fc69f3bd7ba13a7
\ No newline at end of file
+af5c9ee4a453f71c03f24ad08824ced6c1b97afb
\ No newline at end of file
index 6abc11c20c27ddc9e2e48eae993e6b82661a7490..b234716d61d53a9cf742853dd9e3c313009666cd 100644 (file)
@@ -413,7 +413,13 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
     ** same schema version.
     */
     if( rc==SQLITE_DONE ){
-      rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
+      if( nSrcPage==0 ){
+        rc = sqlite3BtreeNewDb(p->pDest);
+        nSrcPage = 1;
+      }
+      if( rc==SQLITE_OK || rc==SQLITE_DONE ){
+        rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
+      }
       if( rc==SQLITE_OK ){
         if( p->pDestDb ){
           sqlite3ResetAllSchemasOfConnection(p->pDestDb);
@@ -447,6 +453,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
         }else{
           nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
         }
+        assert( nDestTruncate>0 );
         sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
 
         if( pgszSrc<pgszDest ){
@@ -465,7 +472,8 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
           i64 iEnd;
 
           assert( pFile );
-          assert( (i64)nDestTruncate*(i64)pgszDest >= iSize || (
+          assert( nDestTruncate==0 
+              || (i64)nDestTruncate*(i64)pgszDest >= iSize || (
                 nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
              && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
           ));
index 4ee0c860a7d54393db20fe4bd9d0e0d652e84183..c0cda1281b7f0ad0e38767d160de9ebca78f9cfa 100644 (file)
@@ -2531,6 +2531,20 @@ static int newDatabase(BtShared *pBt){
   return SQLITE_OK;
 }
 
+/*
+** Initialize the first page of the database file (creating a database
+** consisting of a single page and no schema objects). Return SQLITE_OK
+** if successful, or an SQLite error code otherwise.
+*/
+int sqlite3BtreeNewDb(Btree *p){
+  int rc;
+  sqlite3BtreeEnter(p);
+  p->pBt->nPage = 0;
+  rc = newDatabase(p->pBt);
+  sqlite3BtreeLeave(p);
+  return rc;
+}
+
 /*
 ** Attempt to start a new transaction. A write-transaction
 ** is started if the second argument is nonzero, otherwise a read-
index 0efa0cdcdca521f2c78d54725eddda34301039f0..d4c9fe37d783773f5d55711da2defece5880f0ff 100644 (file)
@@ -117,6 +117,8 @@ void sqlite3BtreeTripAllCursors(Btree*, int);
 void sqlite3BtreeGetMeta(Btree *pBtree, int idx, u32 *pValue);
 int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
 
+int sqlite3BtreeNewDb(Btree *p);
+
 /*
 ** The second parameter to sqlite3BtreeGetMeta or sqlite3BtreeUpdateMeta
 ** should be one of the following values. The integer values are assigned 
diff --git a/test/backup4.test b/test/backup4.test
new file mode 100644 (file)
index 0000000..1d24e16
--- /dev/null
@@ -0,0 +1,106 @@
+# 2012 October 13
+#
+# 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.
+#
+#***********************************************************************
+#
+# The tests in this file verify that if an empty database (zero bytes in 
+# size) is used as the source of a backup operation, the final destination
+# database is one page in size.
+#
+# The destination must consist of at least one page as truncating a 
+# database file to zero bytes is equivalent to resetting the database
+# schema cookie and change counter. Doing that could cause other clients
+# to become confused and continue using out-of-date cache data.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix backup
+
+#-------------------------------------------------------------------------
+# At one point this test was failing because [db] was using an out of
+# date schema in test case 1.2.
+#
+do_execsql_test 1.0 {
+  CREATE TABLE t1(x, y, UNIQUE(x, y));
+  INSERT INTO t1 VALUES('one', 'two');
+  SELECT * FROM t1 WHERE x='one';
+  PRAGMA integrity_check;
+} {one two ok}
+
+do_test 1.1 {
+  sqlite3 db1 :memory:
+  db1 backup test.db
+  sqlite3 db1 test.db
+  db1 eval {
+    CREATE TABLE t1(x, y);
+    INSERT INTO t1 VALUES('one', 'two');
+  }
+  db1 close
+} {}
+
+do_execsql_test 1.2 {
+  SELECT * FROM t1 WHERE x='one';
+  PRAGMA integrity_check;
+} {one two ok}
+
+db close
+forcedelete test.db
+forcedelete test.db2
+sqlite3 db test.db
+
+#-------------------------------------------------------------------------
+# Test that if the source is zero bytes, the destination database 
+# consists of a single page only.
+#
+do_execsql_test 2.1 {
+  CREATE TABLE t1(a, b);
+  CREATE INDEX i1 ON t1(a, b);
+}
+
+do_test 2.2 { file size test.db } 3072
+
+do_test 2.3 {
+  sqlite3 db1 test.db2
+  db1 backup test.db
+  db1 close
+  file size test.db
+} {1024}
+
+do_test 2.4 { file size test.db2 } 0
+
+db close
+forcedelete test.db
+forcedelete test.db2
+sqlite3 db test.db
+
+#-------------------------------------------------------------------------
+# Test that if the destination has a page-size larger than the implicit
+# page-size of the source, the final destination database still consists
+# of a single page.
+#
+do_execsql_test 3.1 {
+  PRAGMA page_size = 4096;
+  CREATE TABLE t1(a, b);
+  CREATE INDEX i1 ON t1(a, b);
+}
+
+do_test 3.2 { file size test.db } 12288
+
+do_test 3.3 {
+  sqlite3 db1 test.db2
+  db1 backup test.db
+  db1 close
+  file size test.db
+} {1024}
+
+do_test 3.4 { file size test.db2 } 0
+
+finish_test
+
index 61a0c0ccdbd9d76a26845a1bd93526c8e21e4706..fac434037eb623d3a60d76404545ed60c891308f 100644 (file)
@@ -1365,7 +1365,7 @@ do_test pager1-9.4.1 {
 } {SQLITE_DONE SQLITE_OK}
 do_test pager1-9.4.2 {
   list [file size test.db2] [file size test.db]
-} {0 0}
+} {1024 0}
 db2 close
 
 #-------------------------------------------------------------------------