10410302eSdanielk1977 /*
20410302eSdanielk1977 ** 2009 January 28
30410302eSdanielk1977 **
40410302eSdanielk1977 ** The author disclaims copyright to this source code. In place of
50410302eSdanielk1977 ** a legal notice, here is a blessing:
60410302eSdanielk1977 **
70410302eSdanielk1977 ** May you do good and not evil.
80410302eSdanielk1977 ** May you find forgiveness for yourself and forgive others.
90410302eSdanielk1977 ** May you share freely, never taking more than you give.
100410302eSdanielk1977 **
110410302eSdanielk1977 *************************************************************************
120410302eSdanielk1977 ** This file contains the implementation of the sqlite3_backup_XXX()
130410302eSdanielk1977 ** API functions and the related features.
140410302eSdanielk1977 */
150410302eSdanielk1977 #include "sqliteInt.h"
160410302eSdanielk1977 #include "btreeInt.h"
170410302eSdanielk1977
180410302eSdanielk1977 /*
190410302eSdanielk1977 ** Structure allocated for each backup operation.
200410302eSdanielk1977 */
210410302eSdanielk1977 struct sqlite3_backup {
220410302eSdanielk1977 sqlite3* pDestDb; /* Destination database handle */
230410302eSdanielk1977 Btree *pDest; /* Destination b-tree file */
240410302eSdanielk1977 u32 iDestSchema; /* Original schema cookie in destination */
250410302eSdanielk1977 int bDestLocked; /* True once a write-transaction is open on pDest */
260410302eSdanielk1977
270410302eSdanielk1977 Pgno iNext; /* Page number of the next source page to copy */
280410302eSdanielk1977 sqlite3* pSrcDb; /* Source database handle */
290410302eSdanielk1977 Btree *pSrc; /* Source b-tree file */
300410302eSdanielk1977
310410302eSdanielk1977 int rc; /* Backup process error code */
320410302eSdanielk1977
330410302eSdanielk1977 /* These two variables are set by every call to backup_step(). They are
340410302eSdanielk1977 ** read by calls to backup_remaining() and backup_pagecount().
350410302eSdanielk1977 */
360410302eSdanielk1977 Pgno nRemaining; /* Number of pages left to copy */
370410302eSdanielk1977 Pgno nPagecount; /* Total number of pages to copy */
380410302eSdanielk1977
39e70f4f64Sdanielk1977 int isAttached; /* True once backup has been registered with pager */
400410302eSdanielk1977 sqlite3_backup *pNext; /* Next backup associated with source pager */
410410302eSdanielk1977 };
420410302eSdanielk1977
430410302eSdanielk1977 /*
440410302eSdanielk1977 ** THREAD SAFETY NOTES:
450410302eSdanielk1977 **
460410302eSdanielk1977 ** Once it has been created using backup_init(), a single sqlite3_backup
470410302eSdanielk1977 ** structure may be accessed via two groups of thread-safe entry points:
480410302eSdanielk1977 **
490410302eSdanielk1977 ** * Via the sqlite3_backup_XXX() API function backup_step() and
500410302eSdanielk1977 ** backup_finish(). Both these functions obtain the source database
510410302eSdanielk1977 ** handle mutex and the mutex associated with the source BtShared
520410302eSdanielk1977 ** structure, in that order.
530410302eSdanielk1977 **
540410302eSdanielk1977 ** * Via the BackupUpdate() and BackupRestart() functions, which are
550410302eSdanielk1977 ** invoked by the pager layer to report various state changes in
560410302eSdanielk1977 ** the page cache associated with the source database. The mutex
570410302eSdanielk1977 ** associated with the source database BtShared structure will always
580410302eSdanielk1977 ** be held when either of these functions are invoked.
590410302eSdanielk1977 **
600410302eSdanielk1977 ** The other sqlite3_backup_XXX() API functions, backup_remaining() and
610410302eSdanielk1977 ** backup_pagecount() are not thread-safe functions. If they are called
620410302eSdanielk1977 ** while some other thread is calling backup_step() or backup_finish(),
630410302eSdanielk1977 ** the values returned may be invalid. There is no way for a call to
640410302eSdanielk1977 ** BackupUpdate() or BackupRestart() to interfere with backup_remaining()
650410302eSdanielk1977 ** or backup_pagecount().
660410302eSdanielk1977 **
670410302eSdanielk1977 ** Depending on the SQLite configuration, the database handles and/or
680410302eSdanielk1977 ** the Btree objects may have their own mutexes that require locking.
690410302eSdanielk1977 ** Non-sharable Btrees (in-memory databases for example), do not have
700410302eSdanielk1977 ** associated mutexes.
710410302eSdanielk1977 */
720410302eSdanielk1977
730410302eSdanielk1977 /*
740410302eSdanielk1977 ** Return a pointer corresponding to database zDb (i.e. "main", "temp")
750410302eSdanielk1977 ** in connection handle pDb. If such a database cannot be found, return
760410302eSdanielk1977 ** a NULL pointer and write an error message to pErrorDb.
770410302eSdanielk1977 **
780410302eSdanielk1977 ** If the "temp" database is requested, it may need to be opened by this
790410302eSdanielk1977 ** function. If an error occurs while doing so, return 0 and write an
800410302eSdanielk1977 ** error message to pErrorDb.
810410302eSdanielk1977 */
findBtree(sqlite3 * pErrorDb,sqlite3 * pDb,const char * zDb)820410302eSdanielk1977 static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
830410302eSdanielk1977 int i = sqlite3FindDbName(pDb, zDb);
840410302eSdanielk1977
850410302eSdanielk1977 if( i==1 ){
86cb43a937Sdrh Parse sParse;
87e98c9049Sdrh int rc = 0;
88*92ecf306Sdrh sqlite3ParseObjectInit(&sParse,pDb);
89cb43a937Sdrh if( sqlite3OpenTempDatabase(&sParse) ){
90cb43a937Sdrh sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg);
91e98c9049Sdrh rc = SQLITE_ERROR;
92e98c9049Sdrh }
93cb43a937Sdrh sqlite3DbFree(pErrorDb, sParse.zErrMsg);
94c692df27Sdrh sqlite3ParseObjectReset(&sParse);
95e98c9049Sdrh if( rc ){
960410302eSdanielk1977 return 0;
970410302eSdanielk1977 }
980410302eSdanielk1977 }
990410302eSdanielk1977
1000410302eSdanielk1977 if( i<0 ){
10113f40da3Sdrh sqlite3ErrorWithMsg(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb);
1020410302eSdanielk1977 return 0;
1030410302eSdanielk1977 }
1040410302eSdanielk1977
1050410302eSdanielk1977 return pDb->aDb[i].pBt;
1060410302eSdanielk1977 }
1070410302eSdanielk1977
1080410302eSdanielk1977 /*
109ca94d8bfSdrh ** Attempt to set the page size of the destination to match the page size
110ca94d8bfSdrh ** of the source.
111ca94d8bfSdrh */
setDestPgsz(sqlite3_backup * p)112ca94d8bfSdrh static int setDestPgsz(sqlite3_backup *p){
113ca94d8bfSdrh int rc;
114e937df81Sdrh rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),0,0);
115ca94d8bfSdrh return rc;
116ca94d8bfSdrh }
117ca94d8bfSdrh
118ca94d8bfSdrh /*
119fad01993Sdan ** Check that there is no open read-transaction on the b-tree passed as the
120fad01993Sdan ** second argument. If there is not, return SQLITE_OK. Otherwise, if there
121fad01993Sdan ** is an open read-transaction, return SQLITE_ERROR and leave an error
122fad01993Sdan ** message in database handle db.
123fad01993Sdan */
checkReadTransaction(sqlite3 * db,Btree * p)124fad01993Sdan static int checkReadTransaction(sqlite3 *db, Btree *p){
12599744fa4Sdrh if( sqlite3BtreeTxnState(p)!=SQLITE_TXN_NONE ){
126fad01993Sdan sqlite3ErrorWithMsg(db, SQLITE_ERROR, "destination database is in use");
127fad01993Sdan return SQLITE_ERROR;
128fad01993Sdan }
129fad01993Sdan return SQLITE_OK;
130fad01993Sdan }
131fad01993Sdan
132fad01993Sdan /*
1330410302eSdanielk1977 ** Create an sqlite3_backup process to copy the contents of zSrcDb from
1340410302eSdanielk1977 ** connection handle pSrcDb to zDestDb in pDestDb. If successful, return
1350410302eSdanielk1977 ** a pointer to the new sqlite3_backup object.
1360410302eSdanielk1977 **
1370410302eSdanielk1977 ** If an error occurs, NULL is returned and an error code and error message
1380410302eSdanielk1977 ** stored in database handle pDestDb.
1390410302eSdanielk1977 */
sqlite3_backup_init(sqlite3 * pDestDb,const char * zDestDb,sqlite3 * pSrcDb,const char * zSrcDb)1400410302eSdanielk1977 sqlite3_backup *sqlite3_backup_init(
1410410302eSdanielk1977 sqlite3* pDestDb, /* Database to write to */
1420410302eSdanielk1977 const char *zDestDb, /* Name of database within pDestDb */
1430410302eSdanielk1977 sqlite3* pSrcDb, /* Database connection to read from */
1440410302eSdanielk1977 const char *zSrcDb /* Name of database within pSrcDb */
1450410302eSdanielk1977 ){
1460410302eSdanielk1977 sqlite3_backup *p; /* Value to return */
1470410302eSdanielk1977
1489ca95730Sdrh #ifdef SQLITE_ENABLE_API_ARMOR
1499ca95730Sdrh if( !sqlite3SafetyCheckOk(pSrcDb)||!sqlite3SafetyCheckOk(pDestDb) ){
1509ca95730Sdrh (void)SQLITE_MISUSE_BKPT;
1519ca95730Sdrh return 0;
1529ca95730Sdrh }
1539ca95730Sdrh #endif
1549ca95730Sdrh
1550410302eSdanielk1977 /* Lock the source database handle. The destination database
156662c58c9Sdrh ** handle is not locked in this routine, but it is locked in
157662c58c9Sdrh ** sqlite3_backup_step(). The user is required to ensure that no
1580410302eSdanielk1977 ** other thread accesses the destination handle for the duration
159662c58c9Sdrh ** of the backup operation. Any attempt to use the destination
160662c58c9Sdrh ** database connection while a backup is in progress may cause
161662c58c9Sdrh ** a malfunction or a deadlock.
1620410302eSdanielk1977 */
1630410302eSdanielk1977 sqlite3_mutex_enter(pSrcDb->mutex);
164eef1eb0fSdrh sqlite3_mutex_enter(pDestDb->mutex);
1650410302eSdanielk1977
1660410302eSdanielk1977 if( pSrcDb==pDestDb ){
16713f40da3Sdrh sqlite3ErrorWithMsg(
168b309becdSdrh pDestDb, SQLITE_ERROR, "source and destination must be distinct"
1690410302eSdanielk1977 );
1700410302eSdanielk1977 p = 0;
1710410302eSdanielk1977 }else {
1729f129f46Sdrh /* Allocate space for a new sqlite3_backup object...
1739f129f46Sdrh ** EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a
1749f129f46Sdrh ** call to sqlite3_backup_init() and is destroyed by a call to
1759f129f46Sdrh ** sqlite3_backup_finish(). */
1766809c96dSdan p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup));
1770410302eSdanielk1977 if( !p ){
178fad3039cSmistachkin sqlite3Error(pDestDb, SQLITE_NOMEM_BKPT);
1790410302eSdanielk1977 }
1800410302eSdanielk1977 }
1810410302eSdanielk1977
1820410302eSdanielk1977 /* If the allocation succeeded, populate the new object. */
1830410302eSdanielk1977 if( p ){
1840410302eSdanielk1977 p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb);
1850410302eSdanielk1977 p->pDest = findBtree(pDestDb, pDestDb, zDestDb);
1860410302eSdanielk1977 p->pDestDb = pDestDb;
1870410302eSdanielk1977 p->pSrcDb = pSrcDb;
1880410302eSdanielk1977 p->iNext = 1;
189e70f4f64Sdanielk1977 p->isAttached = 0;
1900410302eSdanielk1977
191fad01993Sdan if( 0==p->pSrc || 0==p->pDest
192fad01993Sdan || checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK
193fad01993Sdan ){
194ca94d8bfSdrh /* One (or both) of the named databases did not exist or an OOM
195fad01993Sdan ** error was hit. Or there is a transaction open on the destination
196fad01993Sdan ** database. The error has already been written into the pDestDb
197fad01993Sdan ** handle. All that is left to do here is free the sqlite3_backup
198fad01993Sdan ** structure. */
1990410302eSdanielk1977 sqlite3_free(p);
2000410302eSdanielk1977 p = 0;
2010410302eSdanielk1977 }
2020410302eSdanielk1977 }
2030410302eSdanielk1977 if( p ){
2040410302eSdanielk1977 p->pSrc->nBackup++;
2050410302eSdanielk1977 }
2060410302eSdanielk1977
207eef1eb0fSdrh sqlite3_mutex_leave(pDestDb->mutex);
2080410302eSdanielk1977 sqlite3_mutex_leave(pSrcDb->mutex);
2090410302eSdanielk1977 return p;
2100410302eSdanielk1977 }
2110410302eSdanielk1977
2120410302eSdanielk1977 /*
21303ab0357Sdanielk1977 ** Argument rc is an SQLite error code. Return true if this error is
21403ab0357Sdanielk1977 ** considered fatal if encountered during a backup operation. All errors
21503ab0357Sdanielk1977 ** are considered fatal except for SQLITE_BUSY and SQLITE_LOCKED.
21603ab0357Sdanielk1977 */
isFatalError(int rc)21703ab0357Sdanielk1977 static int isFatalError(int rc){
218dcd7db5dSdrh return (rc!=SQLITE_OK && rc!=SQLITE_BUSY && ALWAYS(rc!=SQLITE_LOCKED));
21903ab0357Sdanielk1977 }
22003ab0357Sdanielk1977
22103ab0357Sdanielk1977 /*
2220410302eSdanielk1977 ** Parameter zSrcData points to a buffer containing the data for
2230410302eSdanielk1977 ** page iSrcPg from the source database. Copy this data into the
2240410302eSdanielk1977 ** destination database.
2250410302eSdanielk1977 */
backupOnePage(sqlite3_backup * p,Pgno iSrcPg,const u8 * zSrcData,int bUpdate)2265cc3bea4Sdan static int backupOnePage(
2275cc3bea4Sdan sqlite3_backup *p, /* Backup handle */
2285cc3bea4Sdan Pgno iSrcPg, /* Source database page to backup */
2295cc3bea4Sdan const u8 *zSrcData, /* Source database page data */
2305cc3bea4Sdan int bUpdate /* True for an update, false otherwise */
2315cc3bea4Sdan ){
2320410302eSdanielk1977 Pager * const pDestPager = sqlite3BtreePager(p->pDest);
2330410302eSdanielk1977 const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc);
2340410302eSdanielk1977 int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
2350410302eSdanielk1977 const int nCopy = MIN(nSrcPgsz, nDestPgsz);
2360410302eSdanielk1977 const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
2370410302eSdanielk1977 int rc = SQLITE_OK;
2380410302eSdanielk1977 i64 iOff;
2390410302eSdanielk1977
2400094f37eSdan assert( sqlite3BtreeGetReserveNoMutex(p->pSrc)>=0 );
2410410302eSdanielk1977 assert( p->bDestLocked );
24203ab0357Sdanielk1977 assert( !isFatalError(p->rc) );
2430410302eSdanielk1977 assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) );
2440410302eSdanielk1977 assert( zSrcData );
2450410302eSdanielk1977
2460410302eSdanielk1977 /* Catch the case where the destination is an in-memory database and the
2470410302eSdanielk1977 ** page sizes of the source and destination differ.
2480410302eSdanielk1977 */
2493289c5efSdrh if( nSrcPgsz!=nDestPgsz && sqlite3PagerIsMemdb(pDestPager) ){
2500410302eSdanielk1977 rc = SQLITE_READONLY;
2510410302eSdanielk1977 }
2520410302eSdanielk1977
2530410302eSdanielk1977 /* This loop runs once for each destination page spanned by the source
2540410302eSdanielk1977 ** page. For each iteration, variable iOff is set to the byte offset
2550410302eSdanielk1977 ** of the destination page.
2560410302eSdanielk1977 */
2570410302eSdanielk1977 for(iOff=iEnd-(i64)nSrcPgsz; rc==SQLITE_OK && iOff<iEnd; iOff+=nDestPgsz){
2580410302eSdanielk1977 DbPage *pDestPg = 0;
2590410302eSdanielk1977 Pgno iDest = (Pgno)(iOff/nDestPgsz)+1;
2600410302eSdanielk1977 if( iDest==PENDING_BYTE_PAGE(p->pDest->pBt) ) continue;
2619584f58cSdrh if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg, 0))
2620410302eSdanielk1977 && SQLITE_OK==(rc = sqlite3PagerWrite(pDestPg))
2630410302eSdanielk1977 ){
2640410302eSdanielk1977 const u8 *zIn = &zSrcData[iOff%nSrcPgsz];
2650410302eSdanielk1977 u8 *zDestData = sqlite3PagerGetData(pDestPg);
2660410302eSdanielk1977 u8 *zOut = &zDestData[iOff%nDestPgsz];
2670410302eSdanielk1977
2680410302eSdanielk1977 /* Copy the data from the source page into the destination page.
2690410302eSdanielk1977 ** Then clear the Btree layer MemPage.isInit flag. Both this module
2700410302eSdanielk1977 ** and the pager code use this trick (clearing the first byte
2710410302eSdanielk1977 ** of the page 'extra' space to invalidate the Btree layers
2720410302eSdanielk1977 ** cached parse of the page). MemPage.isInit is marked
2730410302eSdanielk1977 ** "MUST BE FIRST" for this purpose.
2740410302eSdanielk1977 */
2750410302eSdanielk1977 memcpy(zOut, zIn, nCopy);
2760410302eSdanielk1977 ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0;
2775cc3bea4Sdan if( iOff==0 && bUpdate==0 ){
2785cc3bea4Sdan sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc));
2795cc3bea4Sdan }
2800410302eSdanielk1977 }
2810410302eSdanielk1977 sqlite3PagerUnref(pDestPg);
2820410302eSdanielk1977 }
2830410302eSdanielk1977
2840410302eSdanielk1977 return rc;
2850410302eSdanielk1977 }
2860410302eSdanielk1977
2870410302eSdanielk1977 /*
2883d0cbc33Sdanielk1977 ** If pFile is currently larger than iSize bytes, then truncate it to
2893d0cbc33Sdanielk1977 ** exactly iSize bytes. If pFile is not larger than iSize bytes, then
2903d0cbc33Sdanielk1977 ** this function is a no-op.
2913d0cbc33Sdanielk1977 **
2923d0cbc33Sdanielk1977 ** Return SQLITE_OK if everything is successful, or an SQLite error
2933d0cbc33Sdanielk1977 ** code if an error occurs.
2943d0cbc33Sdanielk1977 */
backupTruncateFile(sqlite3_file * pFile,i64 iSize)2953d0cbc33Sdanielk1977 static int backupTruncateFile(sqlite3_file *pFile, i64 iSize){
2963d0cbc33Sdanielk1977 i64 iCurrent;
2973d0cbc33Sdanielk1977 int rc = sqlite3OsFileSize(pFile, &iCurrent);
2983d0cbc33Sdanielk1977 if( rc==SQLITE_OK && iCurrent>iSize ){
2993d0cbc33Sdanielk1977 rc = sqlite3OsTruncate(pFile, iSize);
3003d0cbc33Sdanielk1977 }
3013d0cbc33Sdanielk1977 return rc;
3023d0cbc33Sdanielk1977 }
3033d0cbc33Sdanielk1977
3043d0cbc33Sdanielk1977 /*
305e70f4f64Sdanielk1977 ** Register this backup object with the associated source pager for
306e70f4f64Sdanielk1977 ** callbacks when pages are changed or the cache invalidated.
307e70f4f64Sdanielk1977 */
attachBackupObject(sqlite3_backup * p)308e70f4f64Sdanielk1977 static void attachBackupObject(sqlite3_backup *p){
309e70f4f64Sdanielk1977 sqlite3_backup **pp;
310e70f4f64Sdanielk1977 assert( sqlite3BtreeHoldsMutex(p->pSrc) );
311e70f4f64Sdanielk1977 pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));
312e70f4f64Sdanielk1977 p->pNext = *pp;
313e70f4f64Sdanielk1977 *pp = p;
314e70f4f64Sdanielk1977 p->isAttached = 1;
315e70f4f64Sdanielk1977 }
316e70f4f64Sdanielk1977
317e70f4f64Sdanielk1977 /*
3180410302eSdanielk1977 ** Copy nPage pages from the source b-tree to the destination.
3190410302eSdanielk1977 */
sqlite3_backup_step(sqlite3_backup * p,int nPage)3200410302eSdanielk1977 int sqlite3_backup_step(sqlite3_backup *p, int nPage){
3210410302eSdanielk1977 int rc;
3223289c5efSdrh int destMode; /* Destination journal mode */
3235c10f77dSdrh int pgszSrc = 0; /* Source page size */
3245c10f77dSdrh int pgszDest = 0; /* Destination page size */
3250410302eSdanielk1977
3269ca95730Sdrh #ifdef SQLITE_ENABLE_API_ARMOR
3279ca95730Sdrh if( p==0 ) return SQLITE_MISUSE_BKPT;
3289ca95730Sdrh #endif
3290410302eSdanielk1977 sqlite3_mutex_enter(p->pSrcDb->mutex);
3300410302eSdanielk1977 sqlite3BtreeEnter(p->pSrc);
331d3a5c50eSdrh if( p->pDestDb ){
332662c58c9Sdrh sqlite3_mutex_enter(p->pDestDb->mutex);
333d3a5c50eSdrh }
3340410302eSdanielk1977
3350410302eSdanielk1977 rc = p->rc;
33603ab0357Sdanielk1977 if( !isFatalError(rc) ){
3370410302eSdanielk1977 Pager * const pSrcPager = sqlite3BtreePager(p->pSrc); /* Source pager */
3380410302eSdanielk1977 Pager * const pDestPager = sqlite3BtreePager(p->pDest); /* Dest pager */
3390410302eSdanielk1977 int ii; /* Iterator variable */
34063207ab2Sshane int nSrcPage = -1; /* Size of source db in pages */
3410410302eSdanielk1977 int bCloseTrans = 0; /* True if src db requires unlocking */
3420410302eSdanielk1977
3430410302eSdanielk1977 /* If the source pager is currently in a write-transaction, return
344404ca075Sdanielk1977 ** SQLITE_BUSY immediately.
3450410302eSdanielk1977 */
3460410302eSdanielk1977 if( p->pDestDb && p->pSrc->pBt->inTransaction==TRANS_WRITE ){
347404ca075Sdanielk1977 rc = SQLITE_BUSY;
34803ab0357Sdanielk1977 }else{
34903ab0357Sdanielk1977 rc = SQLITE_OK;
3500410302eSdanielk1977 }
3510410302eSdanielk1977
3520410302eSdanielk1977 /* If there is no open read-transaction on the source database, open
3530410302eSdanielk1977 ** one now. If a transaction is opened here, then it will be closed
3540410302eSdanielk1977 ** before this function exits.
3550410302eSdanielk1977 */
35699744fa4Sdrh if( rc==SQLITE_OK && SQLITE_TXN_NONE==sqlite3BtreeTxnState(p->pSrc) ){
357bb2d9b1bSdrh rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0);
3580410302eSdanielk1977 bCloseTrans = 1;
3590410302eSdanielk1977 }
3600410302eSdanielk1977
361033564ccSdan /* If the destination database has not yet been locked (i.e. if this
362033564ccSdan ** is the first call to backup_step() for the current backup operation),
363033564ccSdan ** try to set its page size to the same as the source database. This
364033564ccSdan ** is especially important on ZipVFS systems, as in that case it is
365033564ccSdan ** not possible to create a database file that uses one page size by
366033564ccSdan ** writing to it with another. */
36776729ed4Sdrh if( p->bDestLocked==0 && rc==SQLITE_OK && setDestPgsz(p)==SQLITE_NOMEM ){
36876729ed4Sdrh rc = SQLITE_NOMEM;
36976729ed4Sdrh }
370033564ccSdan
371033564ccSdan /* Lock the destination database, if it is not locked already. */
372033564ccSdan if( SQLITE_OK==rc && p->bDestLocked==0
373bb2d9b1bSdrh && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2,
374bb2d9b1bSdrh (int*)&p->iDestSchema))
375033564ccSdan ){
376033564ccSdan p->bDestLocked = 1;
377033564ccSdan }
378033564ccSdan
3795c10f77dSdrh /* Do not allow backup if the destination database is in WAL mode
3805c10f77dSdrh ** and the page sizes are different between source and destination */
3815c10f77dSdrh pgszSrc = sqlite3BtreeGetPageSize(p->pSrc);
3825c10f77dSdrh pgszDest = sqlite3BtreeGetPageSize(p->pDest);
3830b9b4301Sdrh destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest));
3845c10f77dSdrh if( SQLITE_OK==rc && destMode==PAGER_JOURNALMODE_WAL && pgszSrc!=pgszDest ){
3855c10f77dSdrh rc = SQLITE_READONLY;
3865c10f77dSdrh }
3875c10f77dSdrh
3880410302eSdanielk1977 /* Now that there is a read-lock on the source database, query the
3890410302eSdanielk1977 ** source pager for the number of pages in the database.
3900410302eSdanielk1977 */
391b1299158Sdrh nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc);
392b1299158Sdrh assert( nSrcPage>=0 );
39303ab0357Sdanielk1977 for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){
3940410302eSdanielk1977 const Pgno iSrcPg = p->iNext; /* Source page number */
3950410302eSdanielk1977 if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
3960410302eSdanielk1977 DbPage *pSrcPg; /* Source page object */
3979584f58cSdrh rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg,PAGER_GET_READONLY);
3980410302eSdanielk1977 if( rc==SQLITE_OK ){
3995cc3bea4Sdan rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0);
4000410302eSdanielk1977 sqlite3PagerUnref(pSrcPg);
4010410302eSdanielk1977 }
4020410302eSdanielk1977 }
4030410302eSdanielk1977 p->iNext++;
4040410302eSdanielk1977 }
4050410302eSdanielk1977 if( rc==SQLITE_OK ){
4060410302eSdanielk1977 p->nPagecount = nSrcPage;
4070410302eSdanielk1977 p->nRemaining = nSrcPage+1-p->iNext;
40863207ab2Sshane if( p->iNext>(Pgno)nSrcPage ){
4090410302eSdanielk1977 rc = SQLITE_DONE;
410e70f4f64Sdanielk1977 }else if( !p->isAttached ){
411e70f4f64Sdanielk1977 attachBackupObject(p);
4120410302eSdanielk1977 }
4130410302eSdanielk1977 }
4140410302eSdanielk1977
4150410302eSdanielk1977 /* Update the schema version field in the destination database. This
4160410302eSdanielk1977 ** is to make sure that the schema-version really does change in
4170410302eSdanielk1977 ** the case where the source and destination databases have the
4180410302eSdanielk1977 ** same schema version.
4190410302eSdanielk1977 */
420c5dbffe7Sdrh if( rc==SQLITE_DONE ){
421b483eba0Sdan if( nSrcPage==0 ){
422b483eba0Sdan rc = sqlite3BtreeNewDb(p->pDest);
423b483eba0Sdan nSrcPage = 1;
424b483eba0Sdan }
425b483eba0Sdan if( rc==SQLITE_OK || rc==SQLITE_DONE ){
426c5dbffe7Sdrh rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
427b483eba0Sdan }
428c5dbffe7Sdrh if( rc==SQLITE_OK ){
429d3a5c50eSdrh if( p->pDestDb ){
43081028a45Sdrh sqlite3ResetAllSchemasOfConnection(p->pDestDb);
431d3a5c50eSdrh }
43206199d84Sdan if( destMode==PAGER_JOURNALMODE_WAL ){
4334b270402Sdan rc = sqlite3BtreeSetVersion(p->pDest, 2);
43406199d84Sdan }
435c5dbffe7Sdrh }
4364b270402Sdan if( rc==SQLITE_OK ){
4374b270402Sdan int nDestTruncate;
4380410302eSdanielk1977 /* Set nDestTruncate to the final number of pages in the destination
4390410302eSdanielk1977 ** database. The complication here is that the destination page
4400410302eSdanielk1977 ** size may be different to the source page size.
4410410302eSdanielk1977 **
4420410302eSdanielk1977 ** If the source page size is smaller than the destination page size,
4430410302eSdanielk1977 ** round up. In this case the call to sqlite3OsTruncate() below will
4440410302eSdanielk1977 ** fix the size of the file. However it is important to call
4450410302eSdanielk1977 ** sqlite3PagerTruncateImage() here so that any pages in the
4460410302eSdanielk1977 ** destination file that lie beyond the nDestTruncate page mark are
4470410302eSdanielk1977 ** journalled by PagerCommitPhaseOne() before they are destroyed
4480410302eSdanielk1977 ** by the file truncation.
4490410302eSdanielk1977 */
4503289c5efSdrh assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) );
4513289c5efSdrh assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) );
4523289c5efSdrh if( pgszSrc<pgszDest ){
4533289c5efSdrh int ratio = pgszDest/pgszSrc;
4540410302eSdanielk1977 nDestTruncate = (nSrcPage+ratio-1)/ratio;
45538aec8dcSdrh if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
456f2a79f22Sdanielk1977 nDestTruncate--;
457f2a79f22Sdanielk1977 }
4580410302eSdanielk1977 }else{
4593289c5efSdrh nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
4600410302eSdanielk1977 }
461b483eba0Sdan assert( nDestTruncate>0 );
4620410302eSdanielk1977
4633289c5efSdrh if( pgszSrc<pgszDest ){
4640410302eSdanielk1977 /* If the source page-size is smaller than the destination page-size,
4650410302eSdanielk1977 ** two extra things may need to happen:
4660410302eSdanielk1977 **
4670410302eSdanielk1977 ** * The destination may need to be truncated, and
4680410302eSdanielk1977 **
4690410302eSdanielk1977 ** * Data stored on the pages immediately following the
4700410302eSdanielk1977 ** pending-byte page in the source database may need to be
4710410302eSdanielk1977 ** copied into the destination database.
4720410302eSdanielk1977 */
4733289c5efSdrh const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
4743d0cbc33Sdanielk1977 sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
475bc1a3c6cSdan Pgno iPg;
476bc1a3c6cSdan int nDstPage;
477c6aed542Sdrh i64 iOff;
478c6aed542Sdrh i64 iEnd;
4793d0cbc33Sdanielk1977
4800410302eSdanielk1977 assert( pFile );
481b483eba0Sdan assert( nDestTruncate==0
482b483eba0Sdan || (i64)nDestTruncate*(i64)pgszDest >= iSize || (
48365ad7d22Sshane nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
4843289c5efSdrh && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
485f2a79f22Sdanielk1977 ));
4864d26d585Sdan
487bc1a3c6cSdan /* This block ensures that all data required to recreate the original
4884d26d585Sdan ** database has been stored in the journal for pDestPager and the
4894d26d585Sdan ** journal synced to disk. So at this point we may safely modify
4904d26d585Sdan ** the database file in any way, knowing that if a power failure
4914d26d585Sdan ** occurs, the original database will be reconstructed from the
4924d26d585Sdan ** journal file. */
493bc1a3c6cSdan sqlite3PagerPagecount(pDestPager, &nDstPage);
494bc1a3c6cSdan for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){
495bc1a3c6cSdan if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){
496bc1a3c6cSdan DbPage *pPg;
4979584f58cSdrh rc = sqlite3PagerGet(pDestPager, iPg, &pPg, 0);
498bc1a3c6cSdan if( rc==SQLITE_OK ){
499bc1a3c6cSdan rc = sqlite3PagerWrite(pPg);
500bc1a3c6cSdan sqlite3PagerUnref(pPg);
501bc1a3c6cSdan }
502bc1a3c6cSdan }
503bc1a3c6cSdan }
504896f99e9Sdan if( rc==SQLITE_OK ){
5054d26d585Sdan rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);
506896f99e9Sdan }
5074d26d585Sdan
5084b270402Sdan /* Write the extra pages and truncate the database file as required */
509c6aed542Sdrh iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
5100410302eSdanielk1977 for(
5113289c5efSdrh iOff=PENDING_BYTE+pgszSrc;
5120410302eSdanielk1977 rc==SQLITE_OK && iOff<iEnd;
5133289c5efSdrh iOff+=pgszSrc
5140410302eSdanielk1977 ){
5150410302eSdanielk1977 PgHdr *pSrcPg = 0;
5163289c5efSdrh const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1);
5179584f58cSdrh rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg, 0);
5180410302eSdanielk1977 if( rc==SQLITE_OK ){
5190410302eSdanielk1977 u8 *zData = sqlite3PagerGetData(pSrcPg);
520f23da966Sdan rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff);
5210410302eSdanielk1977 }
5220410302eSdanielk1977 sqlite3PagerUnref(pSrcPg);
5230410302eSdanielk1977 }
524c6aed542Sdrh if( rc==SQLITE_OK ){
525c6aed542Sdrh rc = backupTruncateFile(pFile, iSize);
526c6aed542Sdrh }
5274d26d585Sdan
5284d26d585Sdan /* Sync the database file to disk. */
5294d26d585Sdan if( rc==SQLITE_OK ){
530999cd08aSdan rc = sqlite3PagerSync(pDestPager, 0);
5310410302eSdanielk1977 }
5320410302eSdanielk1977 }else{
533bc1a3c6cSdan sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
5340410302eSdanielk1977 rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
5350410302eSdanielk1977 }
5360410302eSdanielk1977
5370410302eSdanielk1977 /* Finish committing the transaction to the destination database. */
5380410302eSdanielk1977 if( SQLITE_OK==rc
53960939d0aSdan && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0))
5400410302eSdanielk1977 ){
5410410302eSdanielk1977 rc = SQLITE_DONE;
5420410302eSdanielk1977 }
5430410302eSdanielk1977 }
5444b270402Sdan }
5450410302eSdanielk1977
5460410302eSdanielk1977 /* If bCloseTrans is true, then this function opened a read transaction
5470410302eSdanielk1977 ** on the source database. Close the read transaction here. There is
5480410302eSdanielk1977 ** no need to check the return values of the btree methods here, as
5490410302eSdanielk1977 ** "committing" a read-only transaction cannot fail.
5500410302eSdanielk1977 */
5510410302eSdanielk1977 if( bCloseTrans ){
5520410302eSdanielk1977 TESTONLY( int rc2 );
5530410302eSdanielk1977 TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(p->pSrc, 0);
55460939d0aSdan TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc, 0);
5550410302eSdanielk1977 assert( rc2==SQLITE_OK );
5560410302eSdanielk1977 }
5570410302eSdanielk1977
558ba3cbf3dSdan if( rc==SQLITE_IOERR_NOMEM ){
559fad3039cSmistachkin rc = SQLITE_NOMEM_BKPT;
560ba3cbf3dSdan }
5610410302eSdanielk1977 p->rc = rc;
5620410302eSdanielk1977 }
563d3a5c50eSdrh if( p->pDestDb ){
564662c58c9Sdrh sqlite3_mutex_leave(p->pDestDb->mutex);
565d3a5c50eSdrh }
5660410302eSdanielk1977 sqlite3BtreeLeave(p->pSrc);
5670410302eSdanielk1977 sqlite3_mutex_leave(p->pSrcDb->mutex);
5680410302eSdanielk1977 return rc;
5690410302eSdanielk1977 }
5700410302eSdanielk1977
5710410302eSdanielk1977 /*
5720410302eSdanielk1977 ** Release all resources associated with an sqlite3_backup* handle.
5730410302eSdanielk1977 */
sqlite3_backup_finish(sqlite3_backup * p)5740410302eSdanielk1977 int sqlite3_backup_finish(sqlite3_backup *p){
5750410302eSdanielk1977 sqlite3_backup **pp; /* Ptr to head of pagers backup list */
576ed68801bSdrh sqlite3 *pSrcDb; /* Source database connection */
5770410302eSdanielk1977 int rc; /* Value to return */
5780410302eSdanielk1977
5790410302eSdanielk1977 /* Enter the mutexes */
580dcd7db5dSdrh if( p==0 ) return SQLITE_OK;
581ed68801bSdrh pSrcDb = p->pSrcDb;
582ed68801bSdrh sqlite3_mutex_enter(pSrcDb->mutex);
5830410302eSdanielk1977 sqlite3BtreeEnter(p->pSrc);
584d3a5c50eSdrh if( p->pDestDb ){
585662c58c9Sdrh sqlite3_mutex_enter(p->pDestDb->mutex);
586d3a5c50eSdrh }
5870410302eSdanielk1977
5880410302eSdanielk1977 /* Detach this backup from the source pager. */
5890410302eSdanielk1977 if( p->pDestDb ){
590e70f4f64Sdanielk1977 p->pSrc->nBackup--;
591e70f4f64Sdanielk1977 }
592e70f4f64Sdanielk1977 if( p->isAttached ){
5930410302eSdanielk1977 pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));
59455f66b34Sdrh assert( pp!=0 );
5950410302eSdanielk1977 while( *pp!=p ){
5960410302eSdanielk1977 pp = &(*pp)->pNext;
59755f66b34Sdrh assert( pp!=0 );
5980410302eSdanielk1977 }
5990410302eSdanielk1977 *pp = p->pNext;
6000410302eSdanielk1977 }
6010410302eSdanielk1977
6020410302eSdanielk1977 /* If a transaction is still open on the Btree, roll it back. */
60347b7fc78Sdrh sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0);
6040410302eSdanielk1977
6050410302eSdanielk1977 /* Set the error code of the destination database handle. */
6060410302eSdanielk1977 rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
607a3cc007dSdrh if( p->pDestDb ){
60813f40da3Sdrh sqlite3Error(p->pDestDb, rc);
6090410302eSdanielk1977
6100410302eSdanielk1977 /* Exit the mutexes and free the backup context structure. */
6114245c405Sdrh sqlite3LeaveMutexAndCloseZombie(p->pDestDb);
612d3a5c50eSdrh }
6130410302eSdanielk1977 sqlite3BtreeLeave(p->pSrc);
6140410302eSdanielk1977 if( p->pDestDb ){
6159f129f46Sdrh /* EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a
6169f129f46Sdrh ** call to sqlite3_backup_init() and is destroyed by a call to
6179f129f46Sdrh ** sqlite3_backup_finish(). */
6180410302eSdanielk1977 sqlite3_free(p);
6190410302eSdanielk1977 }
6204245c405Sdrh sqlite3LeaveMutexAndCloseZombie(pSrcDb);
6210410302eSdanielk1977 return rc;
6220410302eSdanielk1977 }
6230410302eSdanielk1977
6240410302eSdanielk1977 /*
6250410302eSdanielk1977 ** Return the number of pages still to be backed up as of the most recent
6260410302eSdanielk1977 ** call to sqlite3_backup_step().
6270410302eSdanielk1977 */
sqlite3_backup_remaining(sqlite3_backup * p)6280410302eSdanielk1977 int sqlite3_backup_remaining(sqlite3_backup *p){
6299ca95730Sdrh #ifdef SQLITE_ENABLE_API_ARMOR
6309ca95730Sdrh if( p==0 ){
6319ca95730Sdrh (void)SQLITE_MISUSE_BKPT;
6329ca95730Sdrh return 0;
6339ca95730Sdrh }
6349ca95730Sdrh #endif
6350410302eSdanielk1977 return p->nRemaining;
6360410302eSdanielk1977 }
6370410302eSdanielk1977
6380410302eSdanielk1977 /*
6390410302eSdanielk1977 ** Return the total number of pages in the source database as of the most
6400410302eSdanielk1977 ** recent call to sqlite3_backup_step().
6410410302eSdanielk1977 */
sqlite3_backup_pagecount(sqlite3_backup * p)6420410302eSdanielk1977 int sqlite3_backup_pagecount(sqlite3_backup *p){
6439ca95730Sdrh #ifdef SQLITE_ENABLE_API_ARMOR
6449ca95730Sdrh if( p==0 ){
6459ca95730Sdrh (void)SQLITE_MISUSE_BKPT;
6469ca95730Sdrh return 0;
6479ca95730Sdrh }
6489ca95730Sdrh #endif
6490410302eSdanielk1977 return p->nPagecount;
6500410302eSdanielk1977 }
6510410302eSdanielk1977
6520410302eSdanielk1977 /*
6530410302eSdanielk1977 ** This function is called after the contents of page iPage of the
6540410302eSdanielk1977 ** source database have been modified. If page iPage has already been
6550410302eSdanielk1977 ** copied into the destination database, then the data written to the
6560410302eSdanielk1977 ** destination is now invalidated. The destination copy of iPage needs
6570410302eSdanielk1977 ** to be updated with the new data before the backup operation is
6580410302eSdanielk1977 ** complete.
6590410302eSdanielk1977 **
6600410302eSdanielk1977 ** It is assumed that the mutex associated with the BtShared object
6610410302eSdanielk1977 ** corresponding to the source database is held when this function is
6620410302eSdanielk1977 ** called.
6630410302eSdanielk1977 */
backupUpdate(sqlite3_backup * p,Pgno iPage,const u8 * aData)66414681b73Sdrh static SQLITE_NOINLINE void backupUpdate(
66514681b73Sdrh sqlite3_backup *p,
66614681b73Sdrh Pgno iPage,
66714681b73Sdrh const u8 *aData
66814681b73Sdrh ){
66914681b73Sdrh assert( p!=0 );
67014681b73Sdrh do{
6710410302eSdanielk1977 assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) );
67203ab0357Sdanielk1977 if( !isFatalError(p->rc) && iPage<p->iNext ){
6730410302eSdanielk1977 /* The backup process p has already copied page iPage. But now it
6740410302eSdanielk1977 ** has been modified by a transaction on the source pager. Copy
6750410302eSdanielk1977 ** the new data into the backup.
6760410302eSdanielk1977 */
6772b89fbcbSdrh int rc;
678806ebcb4Sdrh assert( p->pDestDb );
679806ebcb4Sdrh sqlite3_mutex_enter(p->pDestDb->mutex);
6805cc3bea4Sdan rc = backupOnePage(p, iPage, aData, 1);
681806ebcb4Sdrh sqlite3_mutex_leave(p->pDestDb->mutex);
68203ab0357Sdanielk1977 assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED );
6830410302eSdanielk1977 if( rc!=SQLITE_OK ){
6840410302eSdanielk1977 p->rc = rc;
6850410302eSdanielk1977 }
6860410302eSdanielk1977 }
68714681b73Sdrh }while( (p = p->pNext)!=0 );
6880410302eSdanielk1977 }
sqlite3BackupUpdate(sqlite3_backup * pBackup,Pgno iPage,const u8 * aData)68914681b73Sdrh void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){
69014681b73Sdrh if( pBackup ) backupUpdate(pBackup, iPage, aData);
6910410302eSdanielk1977 }
6920410302eSdanielk1977
6930410302eSdanielk1977 /*
6940410302eSdanielk1977 ** Restart the backup process. This is called when the pager layer
6950410302eSdanielk1977 ** detects that the database has been modified by an external database
6960410302eSdanielk1977 ** connection. In this case there is no way of knowing which of the
6970410302eSdanielk1977 ** pages that have been copied into the destination database are still
6980410302eSdanielk1977 ** valid and which are not, so the entire process needs to be restarted.
6990410302eSdanielk1977 **
7000410302eSdanielk1977 ** It is assumed that the mutex associated with the BtShared object
7010410302eSdanielk1977 ** corresponding to the source database is held when this function is
7020410302eSdanielk1977 ** called.
7030410302eSdanielk1977 */
sqlite3BackupRestart(sqlite3_backup * pBackup)7040410302eSdanielk1977 void sqlite3BackupRestart(sqlite3_backup *pBackup){
7050410302eSdanielk1977 sqlite3_backup *p; /* Iterator variable */
7060410302eSdanielk1977 for(p=pBackup; p; p=p->pNext){
7070410302eSdanielk1977 assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) );
7080410302eSdanielk1977 p->iNext = 1;
7090410302eSdanielk1977 }
7100410302eSdanielk1977 }
7110410302eSdanielk1977
7120410302eSdanielk1977 #ifndef SQLITE_OMIT_VACUUM
7130410302eSdanielk1977 /*
7140410302eSdanielk1977 ** Copy the complete content of pBtFrom into pBtTo. A transaction
7150410302eSdanielk1977 ** must be active for both files.
7160410302eSdanielk1977 **
7170410302eSdanielk1977 ** The size of file pTo may be reduced by this operation. If anything
7180410302eSdanielk1977 ** goes wrong, the transaction on pTo is rolled back. If successful, the
7190410302eSdanielk1977 ** transaction is committed before returning.
7200410302eSdanielk1977 */
sqlite3BtreeCopyFile(Btree * pTo,Btree * pFrom)7210410302eSdanielk1977 int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
7220410302eSdanielk1977 int rc;
723c5f20a00Sdan sqlite3_file *pFd; /* File descriptor for database pTo */
7240410302eSdanielk1977 sqlite3_backup b;
7250410302eSdanielk1977 sqlite3BtreeEnter(pTo);
7260410302eSdanielk1977 sqlite3BtreeEnter(pFrom);
7270410302eSdanielk1977
72899744fa4Sdrh assert( sqlite3BtreeTxnState(pTo)==SQLITE_TXN_WRITE );
729c5f20a00Sdan pFd = sqlite3PagerFile(sqlite3BtreePager(pTo));
730c5f20a00Sdan if( pFd->pMethods ){
731c5f20a00Sdan i64 nByte = sqlite3BtreeGetPageSize(pFrom)*(i64)sqlite3BtreeLastPage(pFrom);
7322bfe5b31Sdrh rc = sqlite3OsFileControl(pFd, SQLITE_FCNTL_OVERWRITE, &nByte);
7332bfe5b31Sdrh if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
7342bfe5b31Sdrh if( rc ) goto copy_finished;
735c5f20a00Sdan }
736c5f20a00Sdan
7370410302eSdanielk1977 /* Set up an sqlite3_backup object. sqlite3_backup.pDestDb must be set
7380410302eSdanielk1977 ** to 0. This is used by the implementations of sqlite3_backup_step()
7390410302eSdanielk1977 ** and sqlite3_backup_finish() to detect that they are being called
7400410302eSdanielk1977 ** from this function, not directly by the user.
7410410302eSdanielk1977 */
7420410302eSdanielk1977 memset(&b, 0, sizeof(b));
7430410302eSdanielk1977 b.pSrcDb = pFrom->db;
7440410302eSdanielk1977 b.pSrc = pFrom;
7450410302eSdanielk1977 b.pDest = pTo;
7460410302eSdanielk1977 b.iNext = 1;
7470410302eSdanielk1977
7480410302eSdanielk1977 /* 0x7FFFFFFF is the hard limit for the number of pages in a database
7490410302eSdanielk1977 ** file. By passing this as the number of pages to copy to
7500410302eSdanielk1977 ** sqlite3_backup_step(), we can guarantee that the copy finishes
7510410302eSdanielk1977 ** within a single call (unless an error occurs). The assert() statement
7520410302eSdanielk1977 ** checks this assumption - (p->rc) should be set to either SQLITE_DONE
75343c1ce39Sdan ** or an error code. */
7540410302eSdanielk1977 sqlite3_backup_step(&b, 0x7FFFFFFF);
7550410302eSdanielk1977 assert( b.rc!=SQLITE_OK );
75643c1ce39Sdan
7570410302eSdanielk1977 rc = sqlite3_backup_finish(&b);
7580410302eSdanielk1977 if( rc==SQLITE_OK ){
759c9166349Sdrh pTo->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED;
76043c1ce39Sdan }else{
76143c1ce39Sdan sqlite3PagerClearCache(sqlite3BtreePager(b.pDest));
7620410302eSdanielk1977 }
7630410302eSdanielk1977
76499744fa4Sdrh assert( sqlite3BtreeTxnState(pTo)!=SQLITE_TXN_WRITE );
7652bfe5b31Sdrh copy_finished:
7660410302eSdanielk1977 sqlite3BtreeLeave(pFrom);
7670410302eSdanielk1977 sqlite3BtreeLeave(pTo);
7680410302eSdanielk1977 return rc;
7690410302eSdanielk1977 }
7700410302eSdanielk1977 #endif /* SQLITE_OMIT_VACUUM */
771