-C Swap\stwo\slines\sto\sget\sthe\samalgamation\sbuilding\sagain\swith\sSQLITE_OMIT_FLOATING_POINT,\snoting\sthat\sneither\sthe\sshell\snor\sthe\scanonical\slibrary\sbuild\swith\sthat\sflag.\sReported\sin\s[forum:8c3df4da0d|forum\spost\s2026-06-24T07:21:05Z].
-D 2026-06-24T10:22:36.339
+C Revert\sthe\sfixes\sto\sbackup\sin\s[1f940357f7]\sand\s[e5db80350c]\sand\sinstead\sfix\sthe\sproblem\sreported\sby\sforum\spost\s[forum:15d82885e2\s|\s15d82885e2]\s(that\sa\scall\sto\ssqlite3_deserialize()\safter\ssqlite3_backup_init()\sbut\sbefore\sthe\sfirst\scall\sto\ssqlite3_backup_step()\son\sthe\sdestination\sdb\sof\sa\sbackup\scould\scause\sa\scrash)\sby\sdeferring\scaching\sthe\spointer\sto\sthe\sdestination\sBtree\suntil\safter\sit\sis\slocked.\sThis\saddresses\sbug\s[bugs:/info/2026-06-24T08:41:13Z\s|\s2026-06-24T08:41:13Z].
+D 2026-06-24T11:50:08.765
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F src/analyze.c 73162482c656187823217f4c00758c9ee13a420c8745bc542129e0279b792287
F src/attach.c c58278c7d2d954785591c4fde81669ec3e4d52f348c453b028a19ae8adf4f338
F src/auth.c b5ece4e1edccad082c0332fa0087df225473bae0feea9269f824312201377185
-F src/backup.c 2f5f350c714407a04fadc9c812b8fcbb47d472c543c492f9fc03043c94255406
+F src/backup.c 89de631678bcbb3ad46f8a8bb43fe4b87b8ada42accd1fe5def363d352ac26d3
F src/bitvec.c e242d4496774dfc88fa278177dd23b607dce369ccafb3f61b41638eea2c9b399
F src/btmutex.c 30dada73a819a1ef5b7583786370dce1842e12e1ad941e4d05ac29695528daea
F src/btree.c 515cf62220ceb483ba9a31ebb3d7565ea9d63ffc3d61bb974b2815fef393df0e
-F src/btree.h c3ba6ba663e185b265a327165bd795e6dc7806fe5a75fe9f547a8459c96f73a7
+F src/btree.h 2ee0ddfdf4f8530ad1d46afffd7da21a0e243bfab10973011ac6f6b7fb4109a1
F src/btreeInt.h 4f512ad31083216b6789762d4c345b73367985d3b39421c9ba7c0902d09fb38b
-F src/build.c 09946336c3011c2ae2faccdf04e33336e1cd51fd836651be0cd7eb5814f7f6a0
+F src/build.c 0a06d413b17a5d7ff80a8499c413e7e3e50cd96f161c4d400462cb8416698c06
F src/callback.c 3605bbf02bd7ed46c79cd48346db4a32fc51d67624400539c0532f4eead804ad
F src/carray.c 3efe3982d5fb323334c29328a4e189ccaef6b95612a6084ad5fa124fd5db1179
F src/complete.c f216b970ce99c5a657556cf1f17e7ddd494515d3beb63df426bf59ff43bd3d9a
F src/upsert.c dd9f0fcccbfb4f20e1026a21a7254ba3f2c08e9cfa92affaff5b5ec3b00ea549
F src/utf.c 7267c3fb9e2467020507601af3354c2446c61f444387e094c779dccd5ca62165
F src/util.c c069caa2e85389deeda302b792161dc536d50c401dd447269e4934aca8f6790c
-F src/vacuum.c 4eda73a75a15f939b45b26e189f5b25757b39d7cb6d5e972a7f754e75d019189
+F src/vacuum.c d3d35d8ae893d419ade5fa196d761a83bddcbb62137a1a157ae751ef38b26e82
F src/vdbe.c 6397694fa506aa1841dc8bb6a17c514aa602a4ad2515024fcd5880558c1ef57f
F src/vdbe.h 70e862ac8a11b590f8c1eaac17a0078429d42bc4ea3f757a9af0f451dd966a71
F src/vdbeInt.h c31ba4dc8d280c2b1dc89c6fcee68f2555e3813ab34279552c20b964c0e338b1
F test/backup.test 3b08fd4af69f0fa786931103a31f4542b184aba16e239e5f22b18c3c2476697f
F test/backup2.test b153553ee5667b0748b43346b0725fbf80ce1f5544613bf087d669778b60ec56
F test/backup4.test 8f6fd48e0dfde77b9a3bb26dc471ede3e101df32
-F test/backup5.test 3e16065dc45c40030378702aac3e92f4d6e7d8853f0328f0390c9e7a71d8c712
+F test/backup5.test a0716934a41bea622c5f1928d00c23093e986c3dfc58aaca9db3b431c66276dc
F test/backup_ioerr.test 4c3c7147cee85b024ecf6e150e090c32fdbb5135
F test/backup_malloc.test 0c9abdf74c51e7bedb66d504cd684f28d4bd4027
F test/badutf.test cff75b714866a4ffa0cdda252eb8fe8765483f5872c0076223c92d52b4fffd1b
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P e458ed9cc9d46dfdade3b4e99eb209d8aefd40a245e002d68df1813f9f99e2d7
-R 592bd4e6bc47a54bee1f0be621a913e3
-U stephan
-Z 56bbc5d496907534eef40aa7c99dc40d
+P 23936786e680131af644510eb50b7ad20ee39221d1fb29732dea76483aed2273
+R e0e0f7b38815f812e27f687f577ea44f
+T *branch * attach-backup-fix
+T *sym-attach-backup-fix *
+T -sym-trunk *
+U dan
+Z df2c9c70dcdd169082f93f43b6437c36
# Remove this line to create a well-formed Fossil manifest.
*/
struct sqlite3_backup {
sqlite3* pDestDb; /* Destination database handle */
- int iDest; /* Destination db file */
+ char *zDestDb;
+ Btree *pDest; /* Destination b-tree file */
u32 iDestSchema; /* Original schema cookie in destination */
int bDestLocked; /* True once a write-transaction is open on pDest */
Pgno iNext; /* Page number of the next source page to copy */
sqlite3* pSrcDb; /* Source database handle */
- int iSrc; /* Source db file */
+ Btree *pSrc; /* Source b-tree file */
int rc; /* Backup process error code */
sqlite3_backup *pNext; /* Next backup associated with source pager */
};
-/*
-** Return the source (Btree*) used by backup object b.
-*/
-#define getSourceBtree(b) ((b)->pSrcDb->aDb[(b)->iSrc].pBt)
-
-/*
-** Return the destination (Btree*) used by backup object b.
-*/
-#define getDestBtree(b) ( (b)->pDestDb ? \
- (b)->pDestDb->aDb[(b)->iDest].pBt : \
- (b)->pSrcDb->aDb[(b)->iDest].pBt \
-)
-
-
/*
** THREAD SAFETY NOTES:
**
*/
/*
-** Return an integer corresponding to database zDb (i.e. "main", "temp")
+** Return a pointer corresponding to database zDb (i.e. "main", "temp")
** in connection handle pDb. If such a database cannot be found, return
-** a negative value and write an error message to pErrorDb.
+** a NULL pointer and write an error message to pErrorDb.
**
** If the "temp" database is requested, it may need to be opened by this
-** function. If an error occurs while doing so, return -1 and write an
+** function. If an error occurs while doing so, return 0 and write an
** error message to pErrorDb.
*/
-static int findDatabase(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
+static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
int i = sqlite3FindDbName(pDb, zDb);
if( i==1 ){
sqlite3DbFree(pErrorDb, sParse.zErrMsg);
sqlite3ParseObjectReset(&sParse);
if( rc ){
- return -1;
+ return 0;
}
}
if( i<0 ){
sqlite3ErrorWithMsg(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb);
+ return 0;
}
- return i;
+ return pDb->aDb[i].pBt;
}
/*
** Attempt to set the page size of the destination to match the page size
** of the source.
*/
-static int setDestPgsz(sqlite3_backup *p){
- return sqlite3BtreeSetPageSize(getDestBtree(p),
- sqlite3BtreeGetPageSize(getSourceBtree(p)), 0, 0
- );
+static int setDestPgsz(Btree *pDest, Btree *pSrc){
+ return sqlite3BtreeSetPageSize(pDest, sqlite3BtreeGetPageSize(pSrc), 0, 0);
}
/*
);
p = 0;
}else {
+ int nDest = sqlite3Strlen30(zDestDb);
+
/* Allocate space for a new sqlite3_backup object...
** EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a
** call to sqlite3_backup_init() and is destroyed by a call to
** sqlite3_backup_finish(). */
- p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup));
+ p = (sqlite3_backup*)sqlite3MallocZero(sizeof(sqlite3_backup)+nDest+1);
if( !p ){
sqlite3Error(pDestDb, SQLITE_NOMEM_BKPT);
+ }else{
+ p->zDestDb = (char*)&p[1];
+ memcpy(p->zDestDb, zDestDb, nDest);
}
}
/* If the allocation succeeded, populate the new object. */
if( p ){
- p->iDest = findDatabase(pDestDb, pDestDb, zDestDb);
- p->iSrc = findDatabase(pDestDb, pSrcDb, zSrcDb);
+ /* Do not store the pointer to the destination b-tree at this point.
+ ** This is because there is nothing preventing it from being detached
+ ** or otherwise freed before the first call to sqlite3_backup_step()
+ ** on this object. The source b-tree does not have this problem, as
+ ** incrementing Btree.nBackup (see below) effectively locks the object. */
+ Btree *pDest = findBtree(pDestDb, pDestDb, zDestDb);
+ p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb);
p->pDestDb = pDestDb;
p->pSrcDb = pSrcDb;
p->iNext = 1;
p->isAttached = 0;
- if( p->iSrc<0 || p->iDest<0
- || checkReadTransaction(pDestDb, getDestBtree(p))!=SQLITE_OK
+ if( 0==p->pSrc || 0==pDest
+ || checkReadTransaction(pDestDb, pDest)!=SQLITE_OK
){
/* One (or both) of the named databases did not exist or an OOM
** error was hit. Or there is a transaction open on the destination
}
}
if( p ){
- getSourceBtree(p)->nBackup++;
+ p->pSrc->nBackup++;
}
sqlite3_mutex_leave(pDestDb->mutex);
const u8 *zSrcData, /* Source database page data */
int bUpdate /* True for an update, false otherwise */
){
- Btree *pDestBt = getDestBtree(p);
- Pager * const pDestPager = sqlite3BtreePager(pDestBt);
- const int nSrcPgsz = sqlite3BtreeGetPageSize(getSourceBtree(p));
- int nDestPgsz = sqlite3BtreeGetPageSize(pDestBt);
+ Pager * const pDestPager = sqlite3BtreePager(p->pDest);
+ const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc);
+ int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
const int nCopy = MIN(nSrcPgsz, nDestPgsz);
const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
int rc = SQLITE_OK;
i64 iOff;
- assert( sqlite3BtreeGetReserveNoMutex(getSourceBtree(p))>=0 );
+ assert( sqlite3BtreeGetReserveNoMutex(p->pSrc)>=0 );
assert( p->bDestLocked );
assert( !isFatalError(p->rc) );
- assert( iSrcPg!=PENDING_BYTE_PAGE(getSourceBtree(p)->pBt) );
+ assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) );
assert( zSrcData );
assert( nSrcPgsz==nDestPgsz || sqlite3PagerIsMemdb(pDestPager)==0 );
for(iOff=iEnd-(i64)nSrcPgsz; rc==SQLITE_OK && iOff<iEnd; iOff+=nDestPgsz){
DbPage *pDestPg = 0;
Pgno iDest = (Pgno)(iOff/nDestPgsz)+1;
- if( iDest==PENDING_BYTE_PAGE(pDestBt->pBt) ) continue;
+ if( iDest==PENDING_BYTE_PAGE(p->pDest->pBt) ) continue;
if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg, 0))
&& SQLITE_OK==(rc = sqlite3PagerWrite(pDestPg))
){
memcpy(zOut, zIn, nCopy);
((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0;
if( iOff==0 && bUpdate==0 ){
- sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(getSourceBtree(p)));
+ sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc));
}
}
sqlite3PagerUnref(pDestPg);
*/
static void attachBackupObject(sqlite3_backup *p){
sqlite3_backup **pp;
- assert( sqlite3BtreeHoldsMutex(getSourceBtree(p)) );
- pp = sqlite3PagerBackupPtr(sqlite3BtreePager(getSourceBtree(p)));
+ assert( sqlite3BtreeHoldsMutex(p->pSrc) );
+ pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));
p->pNext = *pp;
*pp = p;
p->isAttached = 1;
int destMode; /* Destination journal mode */
int pgszSrc = 0; /* Source page size */
int pgszDest = 0; /* Destination page size */
- Btree *pDest;
- Btree *pSrc;
#ifdef SQLITE_ENABLE_API_ARMOR
if( p==0 ) return SQLITE_MISUSE_BKPT;
#endif
- assert( p->iDest>=0 );
- assert( p->iSrc>=0 );
- pDest = getDestBtree(p);
- pSrc = getSourceBtree(p);
sqlite3_mutex_enter(p->pSrcDb->mutex);
- sqlite3BtreeEnter(pSrc);
+ sqlite3BtreeEnter(p->pSrc);
if( p->pDestDb ){
sqlite3_mutex_enter(p->pDestDb->mutex);
}
rc = p->rc;
if( !isFatalError(rc) ){
- Pager * const pSrcPager = sqlite3BtreePager(pSrc); /* Source pager */
- Pager * const pDestPager = sqlite3BtreePager(pDest); /* Dest pager */
+ Pager * const pSrcPager = sqlite3BtreePager(p->pSrc); /* Source pager */
+ Btree * pDest = 0; /* Dest btree */
+ Pager * pDestPager = 0; /* Dest pager */
int ii; /* Iterator variable */
int nSrcPage = -1; /* Size of source db in pages */
int bCloseTrans = 0; /* True if src db requires unlocking */
/* If the source pager is currently in a write-transaction, return
** SQLITE_BUSY immediately.
*/
- if( p->pDestDb && pSrc->pBt->inTransaction==TRANS_WRITE ){
+ if( p->pDestDb && p->pSrc->pBt->inTransaction==TRANS_WRITE ){
rc = SQLITE_BUSY;
}else{
rc = SQLITE_OK;
}
+
/* If there is no open read-transaction on the source database, open
** one now. If a transaction is opened here, then it will be closed
** before this function exits.
*/
- if( rc==SQLITE_OK && SQLITE_TXN_NONE==sqlite3BtreeTxnState(pSrc) ){
- rc = sqlite3BtreeBeginTrans(pSrc, 0, 0);
+ if( rc==SQLITE_OK && SQLITE_TXN_NONE==sqlite3BtreeTxnState(p->pSrc) ){
+ rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0);
bCloseTrans = 1;
}
+ /* Locate the destination btree and pager. */
+ if( (pDest = p->pDest)==0 ){
+ pDest = findBtree(p->pDestDb, p->pDestDb, p->zDestDb);
+ }
+ if( pDest==0 ){
+ rc = SQLITE_ERROR;
+ }else{
+ pDestPager = sqlite3BtreePager(pDest);
+ }
+
/* If the destination database has not yet been locked (i.e. if this
** is the first call to backup_step() for the current backup operation),
** try to set its page size to the same as the source database. This
** is especially important on ZipVFS systems, as in that case it is
** not possible to create a database file that uses one page size by
** writing to it with another. */
- if( p->bDestLocked==0 && rc==SQLITE_OK && setDestPgsz(p)==SQLITE_NOMEM ){
+ if( p->bDestLocked==0 && rc==SQLITE_OK
+ && setDestPgsz(pDest, p->pSrc)==SQLITE_NOMEM
+ ){
rc = SQLITE_NOMEM;
}
(int*)&p->iDestSchema))
){
p->bDestLocked = 1;
+ p->pDest = pDest;
}
/* Do not allow backup if the destination database is in WAL mode
** and the page sizes are different between source and destination */
- pgszSrc = sqlite3BtreeGetPageSize(pSrc);
- pgszDest = sqlite3BtreeGetPageSize(pDest);
- destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(pDest));
- if( SQLITE_OK==rc
- && (destMode==PAGER_JOURNALMODE_WAL || sqlite3PagerIsMemdb(pDestPager))
- && pgszSrc!=pgszDest
- ){
- rc = SQLITE_READONLY;
+ if( rc==SQLITE_OK ){
+ pgszSrc = sqlite3BtreeGetPageSize(p->pSrc);
+ pgszDest = sqlite3BtreeGetPageSize(p->pDest);
+ destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest));
+ if( (destMode==PAGER_JOURNALMODE_WAL || sqlite3PagerIsMemdb(pDestPager))
+ && pgszSrc!=pgszDest
+ ){
+ rc = SQLITE_READONLY;
+ }
}
/* Now that there is a read-lock on the source database, query the
** source pager for the number of pages in the database.
*/
- nSrcPage = (int)sqlite3BtreeLastPage(pSrc);
+ nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc);
assert( nSrcPage>=0 );
for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){
const Pgno iSrcPg = p->iNext; /* Source page number */
- if( iSrcPg!=PENDING_BYTE_PAGE(pSrc->pBt) ){
+ if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
DbPage *pSrcPg; /* Source page object */
rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg,PAGER_GET_READONLY);
if( rc==SQLITE_OK ){
*/
if( rc==SQLITE_DONE ){
if( nSrcPage==0 ){
- rc = sqlite3BtreeNewDb(pDest);
+ rc = sqlite3BtreeNewDb(p->pDest);
nSrcPage = 1;
}
if( rc==SQLITE_OK || rc==SQLITE_DONE ){
- rc = sqlite3BtreeUpdateMeta(pDest,1,p->iDestSchema+1);
+ rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1);
}
if( rc==SQLITE_OK ){
if( p->pDestDb ){
sqlite3ResetAllSchemasOfConnection(p->pDestDb);
}
if( destMode==PAGER_JOURNALMODE_WAL ){
- rc = sqlite3BtreeSetVersion(pDest, 2);
+ rc = sqlite3BtreeSetVersion(p->pDest, 2);
}
}
if( rc==SQLITE_OK ){
** journalled by PagerCommitPhaseOne() before they are destroyed
** by the file truncation.
*/
- assert( pgszSrc==sqlite3BtreeGetPageSize(pSrc) );
- assert( pgszDest==sqlite3BtreeGetPageSize(pDest) );
+ assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) );
+ assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) );
if( pgszSrc<pgszDest ){
int ratio = pgszDest/pgszSrc;
nDestTruncate = (nSrcPage+ratio-1)/ratio;
- if( nDestTruncate==(int)PENDING_BYTE_PAGE(pDest->pBt) ){
+ if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
nDestTruncate--;
}
}else{
assert( pFile );
assert( nDestTruncate==0
|| (i64)nDestTruncate*(i64)pgszDest >= iSize || (
- nDestTruncate==(int)(PENDING_BYTE_PAGE(pDest->pBt)-1)
+ nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1)
&& iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
));
** journal file. */
sqlite3PagerPagecount(pDestPager, &nDstPage);
for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){
- if( iPg!=PENDING_BYTE_PAGE(pDest->pBt) ){
+ if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){
DbPage *pPg;
rc = sqlite3PagerGet(pDestPager, iPg, &pPg, 0);
if( rc==SQLITE_OK ){
/* Finish committing the transaction to the destination database. */
if( SQLITE_OK==rc
- && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(pDest, 0))
+ && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0))
){
rc = SQLITE_DONE;
}
*/
if( bCloseTrans ){
TESTONLY( int rc2 );
- TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(pSrc, 0);
- TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(pSrc, 0);
+ TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(p->pSrc, 0);
+ TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc, 0);
assert( rc2==SQLITE_OK );
}
if( p->pDestDb ){
sqlite3_mutex_leave(p->pDestDb->mutex);
}
- sqlite3BtreeLeave(pSrc);
+ sqlite3BtreeLeave(p->pSrc);
sqlite3_mutex_leave(p->pSrcDb->mutex);
return rc;
}
sqlite3_backup **pp; /* Ptr to head of pagers backup list */
sqlite3 *pSrcDb; /* Source database connection */
int rc; /* Value to return */
- Btree *pSrcBt = 0;
/* Enter the mutexes */
if( p==0 ) return SQLITE_OK;
- pSrcBt = getSourceBtree(p);
pSrcDb = p->pSrcDb;
sqlite3_mutex_enter(pSrcDb->mutex);
- sqlite3BtreeEnter(pSrcBt);
+ sqlite3BtreeEnter(p->pSrc);
if( p->pDestDb ){
sqlite3_mutex_enter(p->pDestDb->mutex);
}
/* Detach this backup from the source pager. */
if( p->pDestDb ){
- pSrcBt->nBackup--;
+ p->pSrc->nBackup--;
}
if( p->isAttached ){
- pp = sqlite3PagerBackupPtr(sqlite3BtreePager(pSrcBt));
+ pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));
assert( pp!=0 );
while( *pp!=p ){
pp = &(*pp)->pNext;
}
/* If a transaction is still open on the Btree, roll it back. */
- sqlite3BtreeRollback(getDestBtree(p), SQLITE_OK, 0);
+ if( p->pDest ){
+ sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0);
+ }
/* Set the error code of the destination database handle. */
rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
/* Exit the mutexes and free the backup context structure. */
sqlite3LeaveMutexAndCloseZombie(p->pDestDb);
}
- sqlite3BtreeLeave(pSrcBt);
+ sqlite3BtreeLeave(p->pSrc);
if( p->pDestDb ){
/* EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a
** call to sqlite3_backup_init() and is destroyed by a call to
){
assert( p!=0 );
do{
- assert( sqlite3_mutex_held(getSourceBtree(p)->pBt->mutex) );
+ assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) );
if( !isFatalError(p->rc) && iPage<p->iNext ){
/* The backup process p has already copied page iPage. But now it
** has been modified by a transaction on the source pager. Copy
void sqlite3BackupRestart(sqlite3_backup *pBackup){
sqlite3_backup *p; /* Iterator variable */
for(p=pBackup; p; p=p->pNext){
- assert( sqlite3_mutex_held(getSourceBtree(p)->pBt->mutex) );
+ assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) );
p->iNext = 1;
}
}
** goes wrong, the transaction on pTo is rolled back. If successful, the
** transaction is committed before returning.
*/
-int sqlite3BtreeCopyFile(sqlite3 *db, int iTo, int iFrom){
+int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){
int rc;
sqlite3_file *pFd; /* File descriptor for database pTo */
sqlite3_backup b;
- Btree *pFrom = db->aDb[iFrom].pBt;
- Btree *pTo = db->aDb[iTo].pBt;
sqlite3BtreeEnter(pTo);
sqlite3BtreeEnter(pFrom);
** from this function, not directly by the user.
*/
memset(&b, 0, sizeof(b));
- b.pSrcDb = db;
- b.iSrc = iFrom;
- b.iDest = iTo;
+ b.pSrcDb = pFrom->db;
+ b.pSrc = pFrom;
+ b.pDest = pTo;
b.iNext = 1;
/* 0x7FFFFFFF is the hard limit for the number of pages in a database
if( rc==SQLITE_OK ){
pTo->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED;
}else{
- sqlite3PagerClearCache(sqlite3BtreePager(pTo));
+ sqlite3PagerClearCache(sqlite3BtreePager(b.pDest));
}
assert( sqlite3BtreeTxnState(pTo)!=SQLITE_TXN_WRITE );