1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-29 08:01:23 +03:00

Changes to the backup API: (1) if a negative number is passed as the second argument to backup_step(), this is interpreted as "copy all remaining pages" and (2) if backup_finish() is called after backup_step() fails with a BUSY or LOCKED error, then this error is also returned by backup_finish() (same handling as for other errors encountered by backup_step()). (CVS 6266)

FossilOrigin-Name: 9b8c8b18cf6b7d44d5fd64760537bc030097756b
This commit is contained in:
danielk1977
2009-02-06 05:59:44 +00:00
parent f4883888ca
commit 03ab035796
5 changed files with 72 additions and 21 deletions

View File

@ -1,5 +1,5 @@
C Fix\sa\stest\scase\sthat\swas\sstill\susing\sthe\sold\spending_byte\smechanism.\s(CVS\s6265) 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-05T17:00:54 D 2009-02-06T05:59:44
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in c7a5a30fb6852bd7839b1024e1661da8549878ee F Makefile.in c7a5a30fb6852bd7839b1024e1661da8549878ee
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@ -101,7 +101,7 @@ F src/alter.c 0ec29744c36c6e976596ce38c16289ebc5dc94db
F src/analyze.c c86fd6a1425b22b3a46ce72ad403e4280026364f F src/analyze.c c86fd6a1425b22b3a46ce72ad403e4280026364f
F src/attach.c 81d37d1948f409146a7b22b96998fd90649d1fd3 F src/attach.c 81d37d1948f409146a7b22b96998fd90649d1fd3
F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
F src/backup.c 12cd9a55b9188c21ae2dd466436e1f2b78b71fa2 F src/backup.c 9563f47385f491579135fd7924d70c76c2eba740
F src/bitvec.c 44f7059ac1f874d364b34af31b9617e52223ba75 F src/bitvec.c 44f7059ac1f874d364b34af31b9617e52223ba75
F src/btmutex.c 63c5cc4ad5715690767ffcb741e185d7bc35ec1a F src/btmutex.c 63c5cc4ad5715690767ffcb741e185d7bc35ec1a
F src/btree.c 71f30e74389aa7ae51421592dfaf69511152677c F src/btree.c 71f30e74389aa7ae51421592dfaf69511152677c
@ -157,7 +157,7 @@ F src/resolve.c 18dc9f0df1d60048e012ce6632251063e0dd356a
F src/rowset.c ba9375f37053d422dd76965a9c370a13b6e1aac4 F src/rowset.c ba9375f37053d422dd76965a9c370a13b6e1aac4
F src/select.c ae72b604e47092521c4d9ae54e1b1cbeb872a747 F src/select.c ae72b604e47092521c4d9ae54e1b1cbeb872a747
F src/shell.c f109ebbb50132926ebbc173a6c2d8838d5d78527 F src/shell.c f109ebbb50132926ebbc173a6c2d8838d5d78527
F src/sqlite.h.in bc6654bb2c8e07281c66e860a018b1f4cb6e5dfa F src/sqlite.h.in f44c38b1e16d60de73ad3f49bffab05c00e8370c
F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17 F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
F src/sqliteInt.h 55cc7e45a7fcc166be62b984168dd69159d877eb F src/sqliteInt.h 55cc7e45a7fcc166be62b984168dd69159d877eb
F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d
@ -233,7 +233,7 @@ F test/autoinc.test ab549b48b389cabd92967b86c379ec8b31fa6c16
F test/autovacuum.test 61260e25744189ff766f61ca3df23c1eeec0060e F test/autovacuum.test 61260e25744189ff766f61ca3df23c1eeec0060e
F test/autovacuum_ioerr2.test 598b0663074d3673a9c1bc9a16e80971313bafe6 F test/autovacuum_ioerr2.test 598b0663074d3673a9c1bc9a16e80971313bafe6
F test/avtrans.test 1e901d8102706b63534dbd2bdd4d8f16c4082650 F test/avtrans.test 1e901d8102706b63534dbd2bdd4d8f16c4082650
F test/backup.test f3592c6759de90fa7a7dcd4bce380aed97115c88 F test/backup.test 12d7ad0545f47175e27445267d0810a277679ef2
F test/backup2.test 392318e059b83e87e5e4175f08be181a6ddce468 F test/backup2.test 392318e059b83e87e5e4175f08be181a6ddce468
F test/backup_ioerr.test a9b8084e488154341719833783ac9db321e14284 F test/backup_ioerr.test a9b8084e488154341719833783ac9db321e14284
F test/backup_malloc.test 1e063c6d75143d0d6e0ae77971dd690070369387 F test/backup_malloc.test 1e063c6d75143d0d6e0ae77971dd690070369387
@ -701,7 +701,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
P 193c871f3d16ce982040334c543610d330117bd5 P 08ec4f2c394ec834c20bfce0d98bbe6b4ce2be65
R d5652a2a1df1206bcb9247c6e46b26d9 R d04d3b804c3f1e9769c67b029dd2532c
U drh U danielk1977
Z 566a5233b34049b2c94643d8e525a629 Z 0d132187e7d66d9f6523f0e0833bc7a9

View File

@ -1 +1 @@
08ec4f2c394ec834c20bfce0d98bbe6b4ce2be65 9b8c8b18cf6b7d44d5fd64760537bc030097756b

View File

@ -12,7 +12,7 @@
** This file contains the implementation of the sqlite3_backup_XXX() ** This file contains the implementation of the sqlite3_backup_XXX()
** API functions and the related features. ** 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 "sqliteInt.h"
#include "btreeInt.h" #include "btreeInt.h"
@ -187,6 +187,15 @@ sqlite3_backup *sqlite3_backup_init(
return p; 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 ** Parameter zSrcData points to a buffer containing the data for
** page iSrcPg from the source database. Copy this data into the ** 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; i64 iOff;
assert( p->bDestLocked ); assert( p->bDestLocked );
assert( p->rc==SQLITE_OK ); assert( !isFatalError(p->rc) );
assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ); assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) );
assert( zSrcData ); assert( zSrcData );
@ -258,7 +267,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
} }
rc = p->rc; rc = p->rc;
if( rc==SQLITE_OK ){ if( !isFatalError(rc) ){
Pager * const pSrcPager = sqlite3BtreePager(p->pSrc); /* Source pager */ Pager * const pSrcPager = sqlite3BtreePager(p->pSrc); /* Source pager */
Pager * const pDestPager = sqlite3BtreePager(p->pDest); /* Dest pager */ Pager * const pDestPager = sqlite3BtreePager(p->pDest); /* Dest pager */
int ii; /* Iterator variable */ 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 ){ if( p->pDestDb && p->pSrc->pBt->inTransaction==TRANS_WRITE ){
rc = SQLITE_LOCKED; rc = SQLITE_LOCKED;
}else{
rc = SQLITE_OK;
} }
/* Lock the destination database, if it is not locked already. */ /* 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 ){ if( rc==SQLITE_OK ){
rc = sqlite3PagerPagecount(pSrcPager, &nSrcPage); rc = sqlite3PagerPagecount(pSrcPager, &nSrcPage);
} }
for(ii=0; ii<nPage && p->iNext<=(Pgno)nSrcPage && rc==SQLITE_OK; ii++){ for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){
const Pgno iSrcPg = p->iNext; /* Source page number */ const Pgno iSrcPg = p->iNext; /* Source page number */
if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){ if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
DbPage *pSrcPg; /* Source page object */ DbPage *pSrcPg; /* Source page object */
@ -410,9 +421,7 @@ int sqlite3_backup_step(sqlite3_backup *p, int nPage){
assert( rc2==SQLITE_OK ); assert( rc2==SQLITE_OK );
} }
if( rc!=SQLITE_LOCKED && rc!=SQLITE_BUSY ){ p->rc = rc;
p->rc = rc;
}
} }
if( p->pDestDb ){ if( p->pDestDb ){
sqlite3_mutex_leave(p->pDestDb->mutex); 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 */ sqlite3_backup *p; /* Iterator variable */
for(p=pBackup; p; p=p->pNext){ for(p=pBackup; p; p=p->pNext){
assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) ); assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) );
if( p->rc==SQLITE_OK && iPage<p->iNext ){ if( !isFatalError(p->rc) && iPage<p->iNext ){
/* The backup process p has already copied page iPage. But now it /* The backup process p has already copied page iPage. But now it
** has been modified by a transaction on the source pager. Copy ** has been modified by a transaction on the source pager. Copy
** the new data into the backup. ** the new data into the backup.
*/ */
int rc = backupOnePage(p, iPage, aData); int rc = backupOnePage(p, iPage, aData);
assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED );
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
p->rc = rc; p->rc = rc;
} }

View File

@ -30,7 +30,7 @@
** the version number) and changes its name to "sqlite3.h" as ** the version number) and changes its name to "sqlite3.h" as
** part of the build process. ** 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_ #ifndef _SQLITE3_H_
#define _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 ** 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 ** 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 ** 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 ** 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 ** are no more pages to copy, then [SQLITE_DONE] is returned. If an error

View File

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The # This file implements regression tests for SQLite library. The
# focus of this file is testing the sqlite3_backup_XXX API. # 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] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
@ -36,6 +36,9 @@ source $testdir/tester.tcl
# #
# backup-8.*: Test multiple simultaneous backup operations. # 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 data_checksum {db file} { $db one "SELECT md5sum(a, b) FROM ${file}.t1" }
proc test_contents {name db1 file1 db2 file2} { proc test_contents {name db1 file1 db2 file2} {
@ -763,5 +766,42 @@ do_test backup-8.10 {
catch { db2 close } catch { db2 close }
catch { db3 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 finish_test