diff --git a/manifest b/manifest index 66a595de84..1dbc61d129 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\stest\scase\sthat\swas\sstill\susing\sthe\sold\spending_byte\smechanism.\s(CVS\s6265) -D 2009-02-05T17:00:54 +C Changes\sto\sthe\sbackup\sAPI:\s(1)\sif\sa\snegative\snumber\sis\spassed\sas\sthe\ssecond\sargument\sto\sbackup_step(),\sthis\sis\sinterpreted\sas\s"copy\sall\sremaining\spages"\sand\s(2)\sif\sbackup_finish()\sis\scalled\safter\sbackup_step()\sfails\swith\sa\sBUSY\sor\sLOCKED\serror,\sthen\sthis\serror\sis\salso\sreturned\sby\sbackup_finish()\s(same\shandling\sas\sfor\sother\serrors\sencountered\sby\sbackup_step()).\s(CVS\s6266) +D 2009-02-06T05:59:44 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in c7a5a30fb6852bd7839b1024e1661da8549878ee F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -101,7 +101,7 @@ F src/alter.c 0ec29744c36c6e976596ce38c16289ebc5dc94db F src/analyze.c c86fd6a1425b22b3a46ce72ad403e4280026364f F src/attach.c 81d37d1948f409146a7b22b96998fd90649d1fd3 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627 -F src/backup.c 12cd9a55b9188c21ae2dd466436e1f2b78b71fa2 +F src/backup.c 9563f47385f491579135fd7924d70c76c2eba740 F src/bitvec.c 44f7059ac1f874d364b34af31b9617e52223ba75 F src/btmutex.c 63c5cc4ad5715690767ffcb741e185d7bc35ec1a F src/btree.c 71f30e74389aa7ae51421592dfaf69511152677c @@ -157,7 +157,7 @@ F src/resolve.c 18dc9f0df1d60048e012ce6632251063e0dd356a F src/rowset.c ba9375f37053d422dd76965a9c370a13b6e1aac4 F src/select.c ae72b604e47092521c4d9ae54e1b1cbeb872a747 F src/shell.c f109ebbb50132926ebbc173a6c2d8838d5d78527 -F src/sqlite.h.in bc6654bb2c8e07281c66e860a018b1f4cb6e5dfa +F src/sqlite.h.in f44c38b1e16d60de73ad3f49bffab05c00e8370c F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17 F src/sqliteInt.h 55cc7e45a7fcc166be62b984168dd69159d877eb F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d @@ -233,7 +233,7 @@ F test/autoinc.test ab549b48b389cabd92967b86c379ec8b31fa6c16 F test/autovacuum.test 61260e25744189ff766f61ca3df23c1eeec0060e F test/autovacuum_ioerr2.test 598b0663074d3673a9c1bc9a16e80971313bafe6 F test/avtrans.test 1e901d8102706b63534dbd2bdd4d8f16c4082650 -F test/backup.test f3592c6759de90fa7a7dcd4bce380aed97115c88 +F test/backup.test 12d7ad0545f47175e27445267d0810a277679ef2 F test/backup2.test 392318e059b83e87e5e4175f08be181a6ddce468 F test/backup_ioerr.test a9b8084e488154341719833783ac9db321e14284 F test/backup_malloc.test 1e063c6d75143d0d6e0ae77971dd690070369387 @@ -701,7 +701,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P 193c871f3d16ce982040334c543610d330117bd5 -R d5652a2a1df1206bcb9247c6e46b26d9 -U drh -Z 566a5233b34049b2c94643d8e525a629 +P 08ec4f2c394ec834c20bfce0d98bbe6b4ce2be65 +R d04d3b804c3f1e9769c67b029dd2532c +U danielk1977 +Z 0d132187e7d66d9f6523f0e0833bc7a9 diff --git a/manifest.uuid b/manifest.uuid index eecc92424f..08c80756fe 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -08ec4f2c394ec834c20bfce0d98bbe6b4ce2be65 \ No newline at end of file +9b8c8b18cf6b7d44d5fd64760537bc030097756b \ No newline at end of file diff --git a/src/backup.c b/src/backup.c index 26299b9e0d..31d14a0aec 100644 --- a/src/backup.c +++ b/src/backup.c @@ -12,7 +12,7 @@ ** This file contains the implementation of the sqlite3_backup_XXX() ** API functions and the related features. ** -** $Id: backup.c,v 1.7 2009/02/04 17:40:58 drh Exp $ +** $Id: backup.c,v 1.8 2009/02/06 05:59:44 danielk1977 Exp $ */ #include "sqliteInt.h" #include "btreeInt.h" @@ -187,6 +187,15 @@ sqlite3_backup *sqlite3_backup_init( return p; } +/* +** Argument rc is an SQLite error code. Return true if this error is +** considered fatal if encountered during a backup operation. All errors +** are considered fatal except for SQLITE_BUSY and SQLITE_LOCKED. +*/ +static int isFatalError(int rc){ + return (rc!=SQLITE_OK && rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED); +} + /* ** Parameter zSrcData points to a buffer containing the data for ** page iSrcPg from the source database. Copy this data into the @@ -203,7 +212,7 @@ static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){ i64 iOff; assert( p->bDestLocked ); - assert( p->rc==SQLITE_OK ); + assert( !isFatalError(p->rc) ); assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ); assert( zSrcData ); @@ -258,7 +267,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){ } rc = p->rc; - if( rc==SQLITE_OK ){ + if( !isFatalError(rc) ){ Pager * const pSrcPager = sqlite3BtreePager(p->pSrc); /* Source pager */ Pager * const pDestPager = sqlite3BtreePager(p->pDest); /* Dest pager */ int ii; /* Iterator variable */ @@ -270,6 +279,8 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){ */ if( p->pDestDb && p->pSrc->pBt->inTransaction==TRANS_WRITE ){ rc = SQLITE_LOCKED; + }else{ + rc = SQLITE_OK; } /* Lock the destination database, if it is not locked already. */ @@ -295,7 +306,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){ if( rc==SQLITE_OK ){ rc = sqlite3PagerPagecount(pSrcPager, &nSrcPage); } - for(ii=0; iiiNext<=(Pgno)nSrcPage && rc==SQLITE_OK; ii++){ + for(ii=0; (nPage<0 || iiiNext<=(Pgno)nSrcPage && !rc; ii++){ const Pgno iSrcPg = p->iNext; /* Source page number */ if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){ DbPage *pSrcPg; /* Source page object */ @@ -410,9 +421,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){ assert( rc2==SQLITE_OK ); } - if( rc!=SQLITE_LOCKED && rc!=SQLITE_BUSY ){ - p->rc = rc; - } + p->rc = rc; } if( p->pDestDb ){ sqlite3_mutex_leave(p->pDestDb->mutex); @@ -499,12 +508,13 @@ void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){ sqlite3_backup *p; /* Iterator variable */ for(p=pBackup; p; p=p->pNext){ assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) ); - if( p->rc==SQLITE_OK && iPageiNext ){ + if( !isFatalError(p->rc) && iPageiNext ){ /* The backup process p has already copied page iPage. But now it ** has been modified by a transaction on the source pager. Copy ** the new data into the backup. */ int rc = backupOnePage(p, iPage, aData); + assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED ); if( rc!=SQLITE_OK ){ p->rc = rc; } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 69b4c037f6..e7fdfe3f69 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -30,7 +30,7 @@ ** the version number) and changes its name to "sqlite3.h" as ** part of the build process. ** -** @(#) $Id: sqlite.h.in,v 1.427 2009/02/05 16:31:46 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.428 2009/02/06 05:59:44 danielk1977 Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -6787,7 +6787,8 @@ typedef struct sqlite3_backup sqlite3_backup; ** ** Function [sqlite3_backup_step()] is used to copy up to nPage pages between ** the source and destination databases, where nPage is the value of the -** second parameter passed to sqlite3_backup_step(). If nPage pages are +** second parameter passed to sqlite3_backup_step(). If nPage is a negative +** value, all remaining source pages are copied. If the required pages are ** succesfully copied, but there are still more pages to copy before the ** backup is complete, it returns [SQLITE_OK]. If no error occured and there ** are no more pages to copy, then [SQLITE_DONE] is returned. If an error diff --git a/test/backup.test b/test/backup.test index f6e1d5c25b..3db2a499d5 100644 --- a/test/backup.test +++ b/test/backup.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this file is testing the sqlite3_backup_XXX API. # -# $Id: backup.test,v 1.3 2009/02/04 22:46:47 drh Exp $ +# $Id: backup.test,v 1.4 2009/02/06 05:59:45 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -36,6 +36,9 @@ source $testdir/tester.tcl # # backup-8.*: Test multiple simultaneous backup operations. # +# backup-9.*: Test that passing a negative argument to backup_step() is +# interpreted as "copy the whole file". +# proc data_checksum {db file} { $db one "SELECT md5sum(a, b) FROM ${file}.t1" } proc test_contents {name db1 file1 db2 file2} { @@ -763,5 +766,42 @@ do_test backup-8.10 { catch { db2 close } catch { db3 close } +#----------------------------------------------------------------------- +# The following tests, backup-9.*, test that: +# +# * Passing 0 as an argument to sqlite3_backup_step() means no pages +# are backed up (backup-9.1.*), and +# * Passing a negative value as an argument to sqlite3_backup_step() means +# all pages are backed up (backup-9.2.*). +# +# These tests reuse the database "test.db" left over from backup-7.*. +# +do_test backup-9.1.1 { + sqlite3 db2 test2.db + sqlite3_backup B db2 main db main + B step 1 +} {SQLITE_OK} +do_test backup-9.1.2 { + set nRemaining [B remaining] + expr {$nRemaining>100} +} {1} +do_test backup-9.1.3 { + B step 0 +} {SQLITE_OK} +do_test backup-9.1.4 { + B remaining +} $nRemaining + +do_test backup-9.2.1 { + B step -1 +} {SQLITE_DONE} +do_test backup-9.2.2 { + B remaining +} {0} +do_test backup-9.2.3 { + B finish +} {SQLITE_OK} +catch {db2 close} finish_test +