| Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/sqlite/src/src/backup.c |
| Source code | Switch to Preprocessed file |
| Line | Source | Count | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | /* | - | ||||||||||||||||||||||||
| 2 | ** 2009 January 28 | - | ||||||||||||||||||||||||
| 3 | ** | - | ||||||||||||||||||||||||
| 4 | ** The author disclaims copyright to this source code. In place of | - | ||||||||||||||||||||||||
| 5 | ** a legal notice, here is a blessing: | - | ||||||||||||||||||||||||
| 6 | ** | - | ||||||||||||||||||||||||
| 7 | ** May you do good and not evil. | - | ||||||||||||||||||||||||
| 8 | ** May you find forgiveness for yourself and forgive others. | - | ||||||||||||||||||||||||
| 9 | ** May you share freely, never taking more than you give. | - | ||||||||||||||||||||||||
| 10 | ** | - | ||||||||||||||||||||||||
| 11 | ************************************************************************* | - | ||||||||||||||||||||||||
| 12 | ** This file contains the implementation of the sqlite3_backup_XXX() | - | ||||||||||||||||||||||||
| 13 | ** API functions and the related features. | - | ||||||||||||||||||||||||
| 14 | */ | - | ||||||||||||||||||||||||
| 15 | #include "sqliteInt.h" | - | ||||||||||||||||||||||||
| 16 | #include "btreeInt.h" | - | ||||||||||||||||||||||||
| 17 | - | |||||||||||||||||||||||||
| 18 | /* | - | ||||||||||||||||||||||||
| 19 | ** Structure allocated for each backup operation. | - | ||||||||||||||||||||||||
| 20 | */ | - | ||||||||||||||||||||||||
| 21 | struct sqlite3_backup { | - | ||||||||||||||||||||||||
| 22 | sqlite3* pDestDb; /* Destination database handle */ | - | ||||||||||||||||||||||||
| 23 | Btree *pDest; /* Destination b-tree file */ | - | ||||||||||||||||||||||||
| 24 | u32 iDestSchema; /* Original schema cookie in destination */ | - | ||||||||||||||||||||||||
| 25 | int bDestLocked; /* True once a write-transaction is open on pDest */ | - | ||||||||||||||||||||||||
| 26 | - | |||||||||||||||||||||||||
| 27 | Pgno iNext; /* Page number of the next source page to copy */ | - | ||||||||||||||||||||||||
| 28 | sqlite3* pSrcDb; /* Source database handle */ | - | ||||||||||||||||||||||||
| 29 | Btree *pSrc; /* Source b-tree file */ | - | ||||||||||||||||||||||||
| 30 | - | |||||||||||||||||||||||||
| 31 | int rc; /* Backup process error code */ | - | ||||||||||||||||||||||||
| 32 | - | |||||||||||||||||||||||||
| 33 | /* These two variables are set by every call to backup_step(). They are | - | ||||||||||||||||||||||||
| 34 | ** read by calls to backup_remaining() and backup_pagecount(). | - | ||||||||||||||||||||||||
| 35 | */ | - | ||||||||||||||||||||||||
| 36 | Pgno nRemaining; /* Number of pages left to copy */ | - | ||||||||||||||||||||||||
| 37 | Pgno nPagecount; /* Total number of pages to copy */ | - | ||||||||||||||||||||||||
| 38 | - | |||||||||||||||||||||||||
| 39 | int isAttached; /* True once backup has been registered with pager */ | - | ||||||||||||||||||||||||
| 40 | sqlite3_backup *pNext; /* Next backup associated with source pager */ | - | ||||||||||||||||||||||||
| 41 | }; | - | ||||||||||||||||||||||||
| 42 | - | |||||||||||||||||||||||||
| 43 | /* | - | ||||||||||||||||||||||||
| 44 | ** THREAD SAFETY NOTES: | - | ||||||||||||||||||||||||
| 45 | ** | - | ||||||||||||||||||||||||
| 46 | ** Once it has been created using backup_init(), a single sqlite3_backup | - | ||||||||||||||||||||||||
| 47 | ** structure may be accessed via two groups of thread-safe entry points: | - | ||||||||||||||||||||||||
| 48 | ** | - | ||||||||||||||||||||||||
| 49 | ** * Via the sqlite3_backup_XXX() API function backup_step() and | - | ||||||||||||||||||||||||
| 50 | ** backup_finish(). Both these functions obtain the source database | - | ||||||||||||||||||||||||
| 51 | ** handle mutex and the mutex associated with the source BtShared | - | ||||||||||||||||||||||||
| 52 | ** structure, in that order. | - | ||||||||||||||||||||||||
| 53 | ** | - | ||||||||||||||||||||||||
| 54 | ** * Via the BackupUpdate() and BackupRestart() functions, which are | - | ||||||||||||||||||||||||
| 55 | ** invoked by the pager layer to report various state changes in | - | ||||||||||||||||||||||||
| 56 | ** the page cache associated with the source database. The mutex | - | ||||||||||||||||||||||||
| 57 | ** associated with the source database BtShared structure will always | - | ||||||||||||||||||||||||
| 58 | ** be held when either of these functions are invoked. | - | ||||||||||||||||||||||||
| 59 | ** | - | ||||||||||||||||||||||||
| 60 | ** The other sqlite3_backup_XXX() API functions, backup_remaining() and | - | ||||||||||||||||||||||||
| 61 | ** backup_pagecount() are not thread-safe functions. If they are called | - | ||||||||||||||||||||||||
| 62 | ** while some other thread is calling backup_step() or backup_finish(), | - | ||||||||||||||||||||||||
| 63 | ** the values returned may be invalid. There is no way for a call to | - | ||||||||||||||||||||||||
| 64 | ** BackupUpdate() or BackupRestart() to interfere with backup_remaining() | - | ||||||||||||||||||||||||
| 65 | ** or backup_pagecount(). | - | ||||||||||||||||||||||||
| 66 | ** | - | ||||||||||||||||||||||||
| 67 | ** Depending on the SQLite configuration, the database handles and/or | - | ||||||||||||||||||||||||
| 68 | ** the Btree objects may have their own mutexes that require locking. | - | ||||||||||||||||||||||||
| 69 | ** Non-sharable Btrees (in-memory databases for example), do not have | - | ||||||||||||||||||||||||
| 70 | ** associated mutexes. | - | ||||||||||||||||||||||||
| 71 | */ | - | ||||||||||||||||||||||||
| 72 | - | |||||||||||||||||||||||||
| 73 | /* | - | ||||||||||||||||||||||||
| 74 | ** Return a pointer corresponding to database zDb (i.e. "main", "temp") | - | ||||||||||||||||||||||||
| 75 | ** in connection handle pDb. If such a database cannot be found, return | - | ||||||||||||||||||||||||
| 76 | ** a NULL pointer and write an error message to pErrorDb. | - | ||||||||||||||||||||||||
| 77 | ** | - | ||||||||||||||||||||||||
| 78 | ** If the "temp" database is requested, it may need to be opened by this | - | ||||||||||||||||||||||||
| 79 | ** function. If an error occurs while doing so, return 0 and write an | - | ||||||||||||||||||||||||
| 80 | ** error message to pErrorDb. | - | ||||||||||||||||||||||||
| 81 | */ | - | ||||||||||||||||||||||||
| 82 | static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ | - | ||||||||||||||||||||||||
| 83 | int i = sqlite3FindDbName(pDb, zDb); | - | ||||||||||||||||||||||||
| 84 | - | |||||||||||||||||||||||||
| 85 | if( i==1 ){
| 5-79 | ||||||||||||||||||||||||
| 86 | Parse sParse; | - | ||||||||||||||||||||||||
| 87 | int rc = 0; | - | ||||||||||||||||||||||||
| 88 | memset(&sParse, 0, sizeof(sParse)); | - | ||||||||||||||||||||||||
| 89 | sParse.db = pDb; | - | ||||||||||||||||||||||||
| 90 | if( sqlite3OpenTempDatabase(&sParse) ){
| 0-5 | ||||||||||||||||||||||||
| 91 | sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg); | - | ||||||||||||||||||||||||
| 92 | rc = SQLITE_ERROR; | - | ||||||||||||||||||||||||
| 93 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 94 | sqlite3DbFree(pErrorDb, sParse.zErrMsg); | - | ||||||||||||||||||||||||
| 95 | sqlite3ParserReset(&sParse); | - | ||||||||||||||||||||||||
| 96 | if( rc ){
| 0-5 | ||||||||||||||||||||||||
| 97 | return 0; never executed: return 0; | 0 | ||||||||||||||||||||||||
| 98 | } | - | ||||||||||||||||||||||||
| 99 | } executed 5 times by 1 test: end of blockExecuted by:
| 5 | ||||||||||||||||||||||||
| 100 | - | |||||||||||||||||||||||||
| 101 | if( i<0 ){
| 2-82 | ||||||||||||||||||||||||
| 102 | sqlite3ErrorWithMsg(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb); | - | ||||||||||||||||||||||||
| 103 | return 0; executed 2 times by 1 test: return 0;Executed by:
| 2 | ||||||||||||||||||||||||
| 104 | } | - | ||||||||||||||||||||||||
| 105 | - | |||||||||||||||||||||||||
| 106 | return pDb->aDb[i].pBt; executed 82 times by 1 test: return pDb->aDb[i].pBt;Executed by:
| 82 | ||||||||||||||||||||||||
| 107 | } | - | ||||||||||||||||||||||||
| 108 | - | |||||||||||||||||||||||||
| 109 | /* | - | ||||||||||||||||||||||||
| 110 | ** Attempt to set the page size of the destination to match the page size | - | ||||||||||||||||||||||||
| 111 | ** of the source. | - | ||||||||||||||||||||||||
| 112 | */ | - | ||||||||||||||||||||||||
| 113 | static int setDestPgsz(sqlite3_backup *p){ | - | ||||||||||||||||||||||||
| 114 | int rc; | - | ||||||||||||||||||||||||
| 115 | rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),-1,0); | - | ||||||||||||||||||||||||
| 116 | return rc; executed 535 times by 2 tests: return rc;Executed by:
| 535 | ||||||||||||||||||||||||
| 117 | } | - | ||||||||||||||||||||||||
| 118 | - | |||||||||||||||||||||||||
| 119 | /* | - | ||||||||||||||||||||||||
| 120 | ** Check that there is no open read-transaction on the b-tree passed as the | - | ||||||||||||||||||||||||
| 121 | ** second argument. If there is not, return SQLITE_OK. Otherwise, if there | - | ||||||||||||||||||||||||
| 122 | ** is an open read-transaction, return SQLITE_ERROR and leave an error | - | ||||||||||||||||||||||||
| 123 | ** message in database handle db. | - | ||||||||||||||||||||||||
| 124 | */ | - | ||||||||||||||||||||||||
| 125 | static int checkReadTransaction(sqlite3 *db, Btree *p){ | - | ||||||||||||||||||||||||
| 126 | if( sqlite3BtreeIsInReadTrans(p) ){
| 1-39 | ||||||||||||||||||||||||
| 127 | sqlite3ErrorWithMsg(db, SQLITE_ERROR, "destination database is in use"); | - | ||||||||||||||||||||||||
| 128 | return SQLITE_ERROR; executed 1 time by 1 test: return 1;Executed by:
| 1 | ||||||||||||||||||||||||
| 129 | } | - | ||||||||||||||||||||||||
| 130 | return SQLITE_OK; executed 39 times by 1 test: return 0;Executed by:
| 39 | ||||||||||||||||||||||||
| 131 | } | - | ||||||||||||||||||||||||
| 132 | - | |||||||||||||||||||||||||
| 133 | /* | - | ||||||||||||||||||||||||
| 134 | ** Create an sqlite3_backup process to copy the contents of zSrcDb from | - | ||||||||||||||||||||||||
| 135 | ** connection handle pSrcDb to zDestDb in pDestDb. If successful, return | - | ||||||||||||||||||||||||
| 136 | ** a pointer to the new sqlite3_backup object. | - | ||||||||||||||||||||||||
| 137 | ** | - | ||||||||||||||||||||||||
| 138 | ** If an error occurs, NULL is returned and an error code and error message | - | ||||||||||||||||||||||||
| 139 | ** stored in database handle pDestDb. | - | ||||||||||||||||||||||||
| 140 | */ | - | ||||||||||||||||||||||||
| 141 | sqlite3_backup *sqlite3_backup_init( | - | ||||||||||||||||||||||||
| 142 | sqlite3* pDestDb, /* Database to write to */ | - | ||||||||||||||||||||||||
| 143 | const char *zDestDb, /* Name of database within pDestDb */ | - | ||||||||||||||||||||||||
| 144 | sqlite3* pSrcDb, /* Database connection to read from */ | - | ||||||||||||||||||||||||
| 145 | const char *zSrcDb /* Name of database within pSrcDb */ | - | ||||||||||||||||||||||||
| 146 | ){ | - | ||||||||||||||||||||||||
| 147 | sqlite3_backup *p; /* Value to return */ | - | ||||||||||||||||||||||||
| 148 | - | |||||||||||||||||||||||||
| 149 | #ifdef SQLITE_ENABLE_API_ARMOR | - | ||||||||||||||||||||||||
| 150 | if( !sqlite3SafetyCheckOk(pSrcDb)||!sqlite3SafetyCheckOk(pDestDb) ){ | - | ||||||||||||||||||||||||
| 151 | (void)SQLITE_MISUSE_BKPT; | - | ||||||||||||||||||||||||
| 152 | return 0; | - | ||||||||||||||||||||||||
| 153 | } | - | ||||||||||||||||||||||||
| 154 | #endif | - | ||||||||||||||||||||||||
| 155 | - | |||||||||||||||||||||||||
| 156 | /* Lock the source database handle. The destination database | - | ||||||||||||||||||||||||
| 157 | ** handle is not locked in this routine, but it is locked in | - | ||||||||||||||||||||||||
| 158 | ** sqlite3_backup_step(). The user is required to ensure that no | - | ||||||||||||||||||||||||
| 159 | ** other thread accesses the destination handle for the duration | - | ||||||||||||||||||||||||
| 160 | ** of the backup operation. Any attempt to use the destination | - | ||||||||||||||||||||||||
| 161 | ** database connection while a backup is in progress may cause | - | ||||||||||||||||||||||||
| 162 | ** a malfunction or a deadlock. | - | ||||||||||||||||||||||||
| 163 | */ | - | ||||||||||||||||||||||||
| 164 | sqlite3_mutex_enter(pSrcDb->mutex); | - | ||||||||||||||||||||||||
| 165 | sqlite3_mutex_enter(pDestDb->mutex); | - | ||||||||||||||||||||||||
| 166 | - | |||||||||||||||||||||||||
| 167 | if( pSrcDb==pDestDb ){
| 0-42 | ||||||||||||||||||||||||
| 168 | sqlite3ErrorWithMsg( | - | ||||||||||||||||||||||||
| 169 | pDestDb, SQLITE_ERROR, "source and destination must be distinct" | - | ||||||||||||||||||||||||
| 170 | ); | - | ||||||||||||||||||||||||
| 171 | p = 0; | - | ||||||||||||||||||||||||
| 172 | }else { never executed: end of block | 0 | ||||||||||||||||||||||||
| 173 | /* Allocate space for a new sqlite3_backup object... | - | ||||||||||||||||||||||||
| 174 | ** EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a | - | ||||||||||||||||||||||||
| 175 | ** call to sqlite3_backup_init() and is destroyed by a call to | - | ||||||||||||||||||||||||
| 176 | ** sqlite3_backup_finish(). */ | - | ||||||||||||||||||||||||
| 177 | p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup)); | - | ||||||||||||||||||||||||
| 178 | if( !p ){
| 0-42 | ||||||||||||||||||||||||
| 179 | sqlite3Error(pDestDb, SQLITE_NOMEM_BKPT); | - | ||||||||||||||||||||||||
| 180 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 181 | } executed 42 times by 1 test: end of blockExecuted by:
| 42 | ||||||||||||||||||||||||
| 182 | - | |||||||||||||||||||||||||
| 183 | /* If the allocation succeeded, populate the new object. */ | - | ||||||||||||||||||||||||
| 184 | if( p ){
| 0-42 | ||||||||||||||||||||||||
| 185 | p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb); | - | ||||||||||||||||||||||||
| 186 | p->pDest = findBtree(pDestDb, pDestDb, zDestDb); | - | ||||||||||||||||||||||||
| 187 | p->pDestDb = pDestDb; | - | ||||||||||||||||||||||||
| 188 | p->pSrcDb = pSrcDb; | - | ||||||||||||||||||||||||
| 189 | p->iNext = 1; | - | ||||||||||||||||||||||||
| 190 | p->isAttached = 0; | - | ||||||||||||||||||||||||
| 191 | - | |||||||||||||||||||||||||
| 192 | if( 0==p->pSrc || 0==p->pDest
| 1-41 | ||||||||||||||||||||||||
| 193 | || checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK
| 1-39 | ||||||||||||||||||||||||
| 194 | ){ | - | ||||||||||||||||||||||||
| 195 | /* One (or both) of the named databases did not exist or an OOM | - | ||||||||||||||||||||||||
| 196 | ** error was hit. Or there is a transaction open on the destination | - | ||||||||||||||||||||||||
| 197 | ** database. The error has already been written into the pDestDb | - | ||||||||||||||||||||||||
| 198 | ** handle. All that is left to do here is free the sqlite3_backup | - | ||||||||||||||||||||||||
| 199 | ** structure. */ | - | ||||||||||||||||||||||||
| 200 | sqlite3_free(p); | - | ||||||||||||||||||||||||
| 201 | p = 0; | - | ||||||||||||||||||||||||
| 202 | } executed 3 times by 1 test: end of blockExecuted by:
| 3 | ||||||||||||||||||||||||
| 203 | } executed 42 times by 1 test: end of blockExecuted by:
| 42 | ||||||||||||||||||||||||
| 204 | if( p ){
| 3-39 | ||||||||||||||||||||||||
| 205 | p->pSrc->nBackup++; | - | ||||||||||||||||||||||||
| 206 | } executed 39 times by 1 test: end of blockExecuted by:
| 39 | ||||||||||||||||||||||||
| 207 | - | |||||||||||||||||||||||||
| 208 | sqlite3_mutex_leave(pDestDb->mutex); | - | ||||||||||||||||||||||||
| 209 | sqlite3_mutex_leave(pSrcDb->mutex); | - | ||||||||||||||||||||||||
| 210 | return p; executed 42 times by 1 test: return p;Executed by:
| 42 | ||||||||||||||||||||||||
| 211 | } | - | ||||||||||||||||||||||||
| 212 | - | |||||||||||||||||||||||||
| 213 | /* | - | ||||||||||||||||||||||||
| 214 | ** Argument rc is an SQLite error code. Return true if this error is | - | ||||||||||||||||||||||||
| 215 | ** considered fatal if encountered during a backup operation. All errors | - | ||||||||||||||||||||||||
| 216 | ** are considered fatal except for SQLITE_BUSY and SQLITE_LOCKED. | - | ||||||||||||||||||||||||
| 217 | */ | - | ||||||||||||||||||||||||
| 218 | static int isFatalError(int rc){ | - | ||||||||||||||||||||||||
| 219 | return (rc!=SQLITE_OK && rc!=SQLITE_BUSY && ALWAYS(rc!=SQLITE_LOCKED)); executed 3091 times by 2 tests: return (rc!=0 && rc!=5 && (rc!=6));Executed by:
| 0-3091 | ||||||||||||||||||||||||
| 220 | } | - | ||||||||||||||||||||||||
| 221 | - | |||||||||||||||||||||||||
| 222 | /* | - | ||||||||||||||||||||||||
| 223 | ** Parameter zSrcData points to a buffer containing the data for | - | ||||||||||||||||||||||||
| 224 | ** page iSrcPg from the source database. Copy this data into the | - | ||||||||||||||||||||||||
| 225 | ** destination database. | - | ||||||||||||||||||||||||
| 226 | */ | - | ||||||||||||||||||||||||
| 227 | static int backupOnePage( | - | ||||||||||||||||||||||||
| 228 | sqlite3_backup *p, /* Backup handle */ | - | ||||||||||||||||||||||||
| 229 | Pgno iSrcPg, /* Source database page to backup */ | - | ||||||||||||||||||||||||
| 230 | const u8 *zSrcData, /* Source database page data */ | - | ||||||||||||||||||||||||
| 231 | int bUpdate /* True for an update, false otherwise */ | - | ||||||||||||||||||||||||
| 232 | ){ | - | ||||||||||||||||||||||||
| 233 | Pager * const pDestPager = sqlite3BtreePager(p->pDest); | - | ||||||||||||||||||||||||
| 234 | const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc); | - | ||||||||||||||||||||||||
| 235 | int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest); | - | ||||||||||||||||||||||||
| 236 | const int nCopy = MIN(nSrcPgsz, nDestPgsz);
| 17-98732 | ||||||||||||||||||||||||
| 237 | const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz; | - | ||||||||||||||||||||||||
| 238 | #ifdef SQLITE_HAS_CODEC | - | ||||||||||||||||||||||||
| 239 | /* Use BtreeGetReserveNoMutex() for the source b-tree, as although it is | - | ||||||||||||||||||||||||
| 240 | ** guaranteed that the shared-mutex is held by this thread, handle | - | ||||||||||||||||||||||||
| 241 | ** p->pSrc may not actually be the owner. */ | - | ||||||||||||||||||||||||
| 242 | int nSrcReserve = sqlite3BtreeGetReserveNoMutex(p->pSrc); | - | ||||||||||||||||||||||||
| 243 | int nDestReserve = sqlite3BtreeGetOptimalReserve(p->pDest); | - | ||||||||||||||||||||||||
| 244 | #endif | - | ||||||||||||||||||||||||
| 245 | int rc = SQLITE_OK; | - | ||||||||||||||||||||||||
| 246 | i64 iOff; | - | ||||||||||||||||||||||||
| 247 | - | |||||||||||||||||||||||||
| 248 | assert( sqlite3BtreeGetReserveNoMutex(p->pSrc)>=0 ); | - | ||||||||||||||||||||||||
| 249 | assert( p->bDestLocked ); | - | ||||||||||||||||||||||||
| 250 | assert( !isFatalError(p->rc) ); | - | ||||||||||||||||||||||||
| 251 | assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ); | - | ||||||||||||||||||||||||
| 252 | assert( zSrcData ); | - | ||||||||||||||||||||||||
| 253 | - | |||||||||||||||||||||||||
| 254 | /* Catch the case where the destination is an in-memory database and the | - | ||||||||||||||||||||||||
| 255 | ** page sizes of the source and destination differ. | - | ||||||||||||||||||||||||
| 256 | */ | - | ||||||||||||||||||||||||
| 257 | if( nSrcPgsz!=nDestPgsz && sqlite3PagerIsMemdb(pDestPager) ){
| 2-98584 | ||||||||||||||||||||||||
| 258 | rc = SQLITE_READONLY; | - | ||||||||||||||||||||||||
| 259 | } executed 2 times by 1 test: end of blockExecuted by:
| 2 | ||||||||||||||||||||||||
| 260 | - | |||||||||||||||||||||||||
| 261 | #ifdef SQLITE_HAS_CODEC | - | ||||||||||||||||||||||||
| 262 | /* Backup is not possible if the page size of the destination is changing | - | ||||||||||||||||||||||||
| 263 | ** and a codec is in use. | - | ||||||||||||||||||||||||
| 264 | */ | - | ||||||||||||||||||||||||
| 265 | if( nSrcPgsz!=nDestPgsz && sqlite3PagerGetCodec(pDestPager)!=0 ){ | - | ||||||||||||||||||||||||
| 266 | rc = SQLITE_READONLY; | - | ||||||||||||||||||||||||
| 267 | } | - | ||||||||||||||||||||||||
| 268 | - | |||||||||||||||||||||||||
| 269 | /* Backup is not possible if the number of bytes of reserve space differ | - | ||||||||||||||||||||||||
| 270 | ** between source and destination. If there is a difference, try to | - | ||||||||||||||||||||||||
| 271 | ** fix the destination to agree with the source. If that is not possible, | - | ||||||||||||||||||||||||
| 272 | ** then the backup cannot proceed. | - | ||||||||||||||||||||||||
| 273 | */ | - | ||||||||||||||||||||||||
| 274 | if( nSrcReserve!=nDestReserve ){ | - | ||||||||||||||||||||||||
| 275 | u32 newPgsz = nSrcPgsz; | - | ||||||||||||||||||||||||
| 276 | rc = sqlite3PagerSetPagesize(pDestPager, &newPgsz, nSrcReserve); | - | ||||||||||||||||||||||||
| 277 | if( rc==SQLITE_OK && newPgsz!=nSrcPgsz ) rc = SQLITE_READONLY; | - | ||||||||||||||||||||||||
| 278 | } | - | ||||||||||||||||||||||||
| 279 | #endif | - | ||||||||||||||||||||||||
| 280 | - | |||||||||||||||||||||||||
| 281 | /* This loop runs once for each destination page spanned by the source | - | ||||||||||||||||||||||||
| 282 | ** page. For each iteration, variable iOff is set to the byte offset | - | ||||||||||||||||||||||||
| 283 | ** of the destination page. | - | ||||||||||||||||||||||||
| 284 | */ | - | ||||||||||||||||||||||||
| 285 | for(iOff=iEnd-(i64)nSrcPgsz; rc==SQLITE_OK && iOff<iEnd; iOff+=nDestPgsz){
| 275-197387 | ||||||||||||||||||||||||
| 286 | DbPage *pDestPg = 0; | - | ||||||||||||||||||||||||
| 287 | Pgno iDest = (Pgno)(iOff/nDestPgsz)+1; | - | ||||||||||||||||||||||||
| 288 | if( iDest==PENDING_BYTE_PAGE(p->pDest->pBt) ) continue; never executed: continue;
| 0-98913 | ||||||||||||||||||||||||
| 289 | if( SQLITE_OK==(rc = sqlite3PagerGet(pDestPager, iDest, &pDestPg, 0))
| 0-98913 | ||||||||||||||||||||||||
| 290 | && SQLITE_OK==(rc = sqlite3PagerWrite(pDestPg))
| 273-98640 | ||||||||||||||||||||||||
| 291 | ){ | - | ||||||||||||||||||||||||
| 292 | const u8 *zIn = &zSrcData[iOff%nSrcPgsz]; | - | ||||||||||||||||||||||||
| 293 | u8 *zDestData = sqlite3PagerGetData(pDestPg); | - | ||||||||||||||||||||||||
| 294 | u8 *zOut = &zDestData[iOff%nDestPgsz]; | - | ||||||||||||||||||||||||
| 295 | - | |||||||||||||||||||||||||
| 296 | /* Copy the data from the source page into the destination page. | - | ||||||||||||||||||||||||
| 297 | ** Then clear the Btree layer MemPage.isInit flag. Both this module | - | ||||||||||||||||||||||||
| 298 | ** and the pager code use this trick (clearing the first byte | - | ||||||||||||||||||||||||
| 299 | ** of the page 'extra' space to invalidate the Btree layers | - | ||||||||||||||||||||||||
| 300 | ** cached parse of the page). MemPage.isInit is marked | - | ||||||||||||||||||||||||
| 301 | ** "MUST BE FIRST" for this purpose. | - | ||||||||||||||||||||||||
| 302 | */ | - | ||||||||||||||||||||||||
| 303 | memcpy(zOut, zIn, nCopy); | - | ||||||||||||||||||||||||
| 304 | ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0; | - | ||||||||||||||||||||||||
| 305 | if( iOff==0 && bUpdate==0 ){
| 4-98111 | ||||||||||||||||||||||||
| 306 | sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc)); | - | ||||||||||||||||||||||||
| 307 | } executed 525 times by 2 tests: end of blockExecuted by:
| 525 | ||||||||||||||||||||||||
| 308 | } executed 98640 times by 2 tests: end of blockExecuted by:
| 98640 | ||||||||||||||||||||||||
| 309 | sqlite3PagerUnref(pDestPg); | - | ||||||||||||||||||||||||
| 310 | } executed 98913 times by 2 tests: end of blockExecuted by:
| 98913 | ||||||||||||||||||||||||
| 311 | - | |||||||||||||||||||||||||
| 312 | return rc; executed 98749 times by 2 tests: return rc;Executed by:
| 98749 | ||||||||||||||||||||||||
| 313 | } | - | ||||||||||||||||||||||||
| 314 | - | |||||||||||||||||||||||||
| 315 | /* | - | ||||||||||||||||||||||||
| 316 | ** If pFile is currently larger than iSize bytes, then truncate it to | - | ||||||||||||||||||||||||
| 317 | ** exactly iSize bytes. If pFile is not larger than iSize bytes, then | - | ||||||||||||||||||||||||
| 318 | ** this function is a no-op. | - | ||||||||||||||||||||||||
| 319 | ** | - | ||||||||||||||||||||||||
| 320 | ** Return SQLITE_OK if everything is successful, or an SQLite error | - | ||||||||||||||||||||||||
| 321 | ** code if an error occurs. | - | ||||||||||||||||||||||||
| 322 | */ | - | ||||||||||||||||||||||||
| 323 | static int backupTruncateFile(sqlite3_file *pFile, i64 iSize){ | - | ||||||||||||||||||||||||
| 324 | i64 iCurrent; | - | ||||||||||||||||||||||||
| 325 | int rc = sqlite3OsFileSize(pFile, &iCurrent); | - | ||||||||||||||||||||||||
| 326 | if( rc==SQLITE_OK && iCurrent>iSize ){
| 0-8 | ||||||||||||||||||||||||
| 327 | rc = sqlite3OsTruncate(pFile, iSize); | - | ||||||||||||||||||||||||
| 328 | } executed 8 times by 1 test: end of blockExecuted by:
| 8 | ||||||||||||||||||||||||
| 329 | return rc; executed 8 times by 1 test: return rc;Executed by:
| 8 | ||||||||||||||||||||||||
| 330 | } | - | ||||||||||||||||||||||||
| 331 | - | |||||||||||||||||||||||||
| 332 | /* | - | ||||||||||||||||||||||||
| 333 | ** Register this backup object with the associated source pager for | - | ||||||||||||||||||||||||
| 334 | ** callbacks when pages are changed or the cache invalidated. | - | ||||||||||||||||||||||||
| 335 | */ | - | ||||||||||||||||||||||||
| 336 | static void attachBackupObject(sqlite3_backup *p){ | - | ||||||||||||||||||||||||
| 337 | sqlite3_backup **pp; | - | ||||||||||||||||||||||||
| 338 | assert( sqlite3BtreeHoldsMutex(p->pSrc) ); | - | ||||||||||||||||||||||||
| 339 | pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc)); | - | ||||||||||||||||||||||||
| 340 | p->pNext = *pp; | - | ||||||||||||||||||||||||
| 341 | *pp = p; | - | ||||||||||||||||||||||||
| 342 | p->isAttached = 1; | - | ||||||||||||||||||||||||
| 343 | } executed 7 times by 1 test: end of blockExecuted by:
| 7 | ||||||||||||||||||||||||
| 344 | - | |||||||||||||||||||||||||
| 345 | /* | - | ||||||||||||||||||||||||
| 346 | ** Copy nPage pages from the source b-tree to the destination. | - | ||||||||||||||||||||||||
| 347 | */ | - | ||||||||||||||||||||||||
| 348 | int sqlite3_backup_step(sqlite3_backup *p, int nPage){ | - | ||||||||||||||||||||||||
| 349 | int rc; | - | ||||||||||||||||||||||||
| 350 | int destMode; /* Destination journal mode */ | - | ||||||||||||||||||||||||
| 351 | int pgszSrc = 0; /* Source page size */ | - | ||||||||||||||||||||||||
| 352 | int pgszDest = 0; /* Destination page size */ | - | ||||||||||||||||||||||||
| 353 | - | |||||||||||||||||||||||||
| 354 | #ifdef SQLITE_ENABLE_API_ARMOR | - | ||||||||||||||||||||||||
| 355 | if( p==0 ) return SQLITE_MISUSE_BKPT; | - | ||||||||||||||||||||||||
| 356 | #endif | - | ||||||||||||||||||||||||
| 357 | sqlite3_mutex_enter(p->pSrcDb->mutex); | - | ||||||||||||||||||||||||
| 358 | sqlite3BtreeEnter(p->pSrc); | - | ||||||||||||||||||||||||
| 359 | if( p->pDestDb ){
| 52-498 | ||||||||||||||||||||||||
| 360 | sqlite3_mutex_enter(p->pDestDb->mutex); | - | ||||||||||||||||||||||||
| 361 | } executed 52 times by 1 test: end of blockExecuted by:
| 52 | ||||||||||||||||||||||||
| 362 | - | |||||||||||||||||||||||||
| 363 | rc = p->rc; | - | ||||||||||||||||||||||||
| 364 | if( !isFatalError(rc) ){
| 1-549 | ||||||||||||||||||||||||
| 365 | Pager * const pSrcPager = sqlite3BtreePager(p->pSrc); /* Source pager */ | - | ||||||||||||||||||||||||
| 366 | Pager * const pDestPager = sqlite3BtreePager(p->pDest); /* Dest pager */ | - | ||||||||||||||||||||||||
| 367 | int ii; /* Iterator variable */ | - | ||||||||||||||||||||||||
| 368 | int nSrcPage = -1; /* Size of source db in pages */ | - | ||||||||||||||||||||||||
| 369 | int bCloseTrans = 0; /* True if src db requires unlocking */ | - | ||||||||||||||||||||||||
| 370 | - | |||||||||||||||||||||||||
| 371 | /* If the source pager is currently in a write-transaction, return | - | ||||||||||||||||||||||||
| 372 | ** SQLITE_BUSY immediately. | - | ||||||||||||||||||||||||
| 373 | */ | - | ||||||||||||||||||||||||
| 374 | if( p->pDestDb && p->pSrc->pBt->inTransaction==TRANS_WRITE ){
| 2-498 | ||||||||||||||||||||||||
| 375 | rc = SQLITE_BUSY; | - | ||||||||||||||||||||||||
| 376 | }else{ executed 2 times by 1 test: end of blockExecuted by:
| 2 | ||||||||||||||||||||||||
| 377 | rc = SQLITE_OK; | - | ||||||||||||||||||||||||
| 378 | } executed 547 times by 2 tests: end of blockExecuted by:
| 547 | ||||||||||||||||||||||||
| 379 | - | |||||||||||||||||||||||||
| 380 | /* If there is no open read-transaction on the source database, open | - | ||||||||||||||||||||||||
| 381 | ** one now. If a transaction is opened here, then it will be closed | - | ||||||||||||||||||||||||
| 382 | ** before this function exits. | - | ||||||||||||||||||||||||
| 383 | */ | - | ||||||||||||||||||||||||
| 384 | if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){
| 2-547 | ||||||||||||||||||||||||
| 385 | rc = sqlite3BtreeBeginTrans(p->pSrc, 0, 0); | - | ||||||||||||||||||||||||
| 386 | bCloseTrans = 1; | - | ||||||||||||||||||||||||
| 387 | } executed 49 times by 1 test: end of blockExecuted by:
| 49 | ||||||||||||||||||||||||
| 388 | - | |||||||||||||||||||||||||
| 389 | /* If the destination database has not yet been locked (i.e. if this | - | ||||||||||||||||||||||||
| 390 | ** is the first call to backup_step() for the current backup operation), | - | ||||||||||||||||||||||||
| 391 | ** try to set its page size to the same as the source database. This | - | ||||||||||||||||||||||||
| 392 | ** is especially important on ZipVFS systems, as in that case it is | - | ||||||||||||||||||||||||
| 393 | ** not possible to create a database file that uses one page size by | - | ||||||||||||||||||||||||
| 394 | ** writing to it with another. */ | - | ||||||||||||||||||||||||
| 395 | if( p->bDestLocked==0 && rc==SQLITE_OK && setDestPgsz(p)==SQLITE_NOMEM ){
| 0-540 | ||||||||||||||||||||||||
| 396 | rc = SQLITE_NOMEM; | - | ||||||||||||||||||||||||
| 397 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 398 | - | |||||||||||||||||||||||||
| 399 | /* Lock the destination database, if it is not locked already. */ | - | ||||||||||||||||||||||||
| 400 | if( SQLITE_OK==rc && p->bDestLocked==0
| 7-542 | ||||||||||||||||||||||||
| 401 | && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2,
| 2-533 | ||||||||||||||||||||||||
| 402 | (int*)&p->iDestSchema))
| 2-533 | ||||||||||||||||||||||||
| 403 | ){ | - | ||||||||||||||||||||||||
| 404 | p->bDestLocked = 1; | - | ||||||||||||||||||||||||
| 405 | } executed 533 times by 2 tests: end of blockExecuted by:
| 533 | ||||||||||||||||||||||||
| 406 | - | |||||||||||||||||||||||||
| 407 | /* Do not allow backup if the destination database is in WAL mode | - | ||||||||||||||||||||||||
| 408 | ** and the page sizes are different between source and destination */ | - | ||||||||||||||||||||||||
| 409 | pgszSrc = sqlite3BtreeGetPageSize(p->pSrc); | - | ||||||||||||||||||||||||
| 410 | pgszDest = sqlite3BtreeGetPageSize(p->pDest); | - | ||||||||||||||||||||||||
| 411 | destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest)); | - | ||||||||||||||||||||||||
| 412 | if( SQLITE_OK==rc && destMode==PAGER_JOURNALMODE_WAL && pgszSrc!=pgszDest ){
| 0-540 | ||||||||||||||||||||||||
| 413 | rc = SQLITE_READONLY; | - | ||||||||||||||||||||||||
| 414 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 415 | - | |||||||||||||||||||||||||
| 416 | /* Now that there is a read-lock on the source database, query the | - | ||||||||||||||||||||||||
| 417 | ** source pager for the number of pages in the database. | - | ||||||||||||||||||||||||
| 418 | */ | - | ||||||||||||||||||||||||
| 419 | nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc); | - | ||||||||||||||||||||||||
| 420 | assert( nSrcPage>=0 ); | - | ||||||||||||||||||||||||
| 421 | for(ii=0; (nPage<0 || ii<nPage) && p->iNext<=(Pgno)nSrcPage && !rc; ii++){
| 0-98035 | ||||||||||||||||||||||||
| 422 | const Pgno iSrcPg = p->iNext; /* Source page number */ | - | ||||||||||||||||||||||||
| 423 | if( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ){
| 202-97284 | ||||||||||||||||||||||||
| 424 | DbPage *pSrcPg; /* Source page object */ | - | ||||||||||||||||||||||||
| 425 | rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg,PAGER_GET_READONLY); | - | ||||||||||||||||||||||||
| 426 | if( rc==SQLITE_OK ){
| 0-97284 | ||||||||||||||||||||||||
| 427 | rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0); | - | ||||||||||||||||||||||||
| 428 | sqlite3PagerUnref(pSrcPg); | - | ||||||||||||||||||||||||
| 429 | } executed 97284 times by 2 tests: end of blockExecuted by:
| 97284 | ||||||||||||||||||||||||
| 430 | } executed 97284 times by 2 tests: end of blockExecuted by:
| 97284 | ||||||||||||||||||||||||
| 431 | p->iNext++; | - | ||||||||||||||||||||||||
| 432 | } executed 97486 times by 2 tests: end of blockExecuted by:
| 97486 | ||||||||||||||||||||||||
| 433 | if( rc==SQLITE_OK ){
| 265-284 | ||||||||||||||||||||||||
| 434 | p->nPagecount = nSrcPage; | - | ||||||||||||||||||||||||
| 435 | p->nRemaining = nSrcPage+1-p->iNext; | - | ||||||||||||||||||||||||
| 436 | if( p->iNext>(Pgno)nSrcPage ){
| 7-258 | ||||||||||||||||||||||||
| 437 | rc = SQLITE_DONE; | - | ||||||||||||||||||||||||
| 438 | }else if( !p->isAttached ){ executed 258 times by 2 tests: end of blockExecuted by:
| 0-258 | ||||||||||||||||||||||||
| 439 | attachBackupObject(p); | - | ||||||||||||||||||||||||
| 440 | } executed 7 times by 1 test: end of blockExecuted by:
| 7 | ||||||||||||||||||||||||
| 441 | } executed 265 times by 2 tests: end of blockExecuted by:
| 265 | ||||||||||||||||||||||||
| 442 | - | |||||||||||||||||||||||||
| 443 | /* Update the schema version field in the destination database. This | - | ||||||||||||||||||||||||
| 444 | ** is to make sure that the schema-version really does change in | - | ||||||||||||||||||||||||
| 445 | ** the case where the source and destination databases have the | - | ||||||||||||||||||||||||
| 446 | ** same schema version. | - | ||||||||||||||||||||||||
| 447 | */ | - | ||||||||||||||||||||||||
| 448 | if( rc==SQLITE_DONE ){
| 258-291 | ||||||||||||||||||||||||
| 449 | if( nSrcPage==0 ){
| 4-254 | ||||||||||||||||||||||||
| 450 | rc = sqlite3BtreeNewDb(p->pDest); | - | ||||||||||||||||||||||||
| 451 | nSrcPage = 1; | - | ||||||||||||||||||||||||
| 452 | } executed 4 times by 1 test: end of blockExecuted by:
| 4 | ||||||||||||||||||||||||
| 453 | if( rc==SQLITE_OK || rc==SQLITE_DONE ){
| 0-254 | ||||||||||||||||||||||||
| 454 | rc = sqlite3BtreeUpdateMeta(p->pDest,1,p->iDestSchema+1); | - | ||||||||||||||||||||||||
| 455 | } executed 258 times by 2 tests: end of blockExecuted by:
| 258 | ||||||||||||||||||||||||
| 456 | if( rc==SQLITE_OK ){
| 0-258 | ||||||||||||||||||||||||
| 457 | if( p->pDestDb ){
| 33-225 | ||||||||||||||||||||||||
| 458 | sqlite3ResetAllSchemasOfConnection(p->pDestDb); | - | ||||||||||||||||||||||||
| 459 | } executed 33 times by 1 test: end of blockExecuted by:
| 33 | ||||||||||||||||||||||||
| 460 | if( destMode==PAGER_JOURNALMODE_WAL ){
| 23-235 | ||||||||||||||||||||||||
| 461 | rc = sqlite3BtreeSetVersion(p->pDest, 2); | - | ||||||||||||||||||||||||
| 462 | } executed 23 times by 1 test: end of blockExecuted by:
| 23 | ||||||||||||||||||||||||
| 463 | } executed 258 times by 2 tests: end of blockExecuted by:
| 258 | ||||||||||||||||||||||||
| 464 | if( rc==SQLITE_OK ){
| 0-258 | ||||||||||||||||||||||||
| 465 | int nDestTruncate; | - | ||||||||||||||||||||||||
| 466 | /* Set nDestTruncate to the final number of pages in the destination | - | ||||||||||||||||||||||||
| 467 | ** database. The complication here is that the destination page | - | ||||||||||||||||||||||||
| 468 | ** size may be different to the source page size. | - | ||||||||||||||||||||||||
| 469 | ** | - | ||||||||||||||||||||||||
| 470 | ** If the source page size is smaller than the destination page size, | - | ||||||||||||||||||||||||
| 471 | ** round up. In this case the call to sqlite3OsTruncate() below will | - | ||||||||||||||||||||||||
| 472 | ** fix the size of the file. However it is important to call | - | ||||||||||||||||||||||||
| 473 | ** sqlite3PagerTruncateImage() here so that any pages in the | - | ||||||||||||||||||||||||
| 474 | ** destination file that lie beyond the nDestTruncate page mark are | - | ||||||||||||||||||||||||
| 475 | ** journalled by PagerCommitPhaseOne() before they are destroyed | - | ||||||||||||||||||||||||
| 476 | ** by the file truncation. | - | ||||||||||||||||||||||||
| 477 | */ | - | ||||||||||||||||||||||||
| 478 | assert( pgszSrc==sqlite3BtreeGetPageSize(p->pSrc) ); | - | ||||||||||||||||||||||||
| 479 | assert( pgszDest==sqlite3BtreeGetPageSize(p->pDest) ); | - | ||||||||||||||||||||||||
| 480 | if( pgszSrc<pgszDest ){
| 8-250 | ||||||||||||||||||||||||
| 481 | int ratio = pgszDest/pgszSrc; | - | ||||||||||||||||||||||||
| 482 | nDestTruncate = (nSrcPage+ratio-1)/ratio; | - | ||||||||||||||||||||||||
| 483 | if( nDestTruncate==(int)PENDING_BYTE_PAGE(p->pDest->pBt) ){
| 0-8 | ||||||||||||||||||||||||
| 484 | nDestTruncate--; | - | ||||||||||||||||||||||||
| 485 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 486 | }else{ executed 8 times by 1 test: end of blockExecuted by:
| 8 | ||||||||||||||||||||||||
| 487 | nDestTruncate = nSrcPage * (pgszSrc/pgszDest); | - | ||||||||||||||||||||||||
| 488 | } executed 250 times by 2 tests: end of blockExecuted by:
| 250 | ||||||||||||||||||||||||
| 489 | assert( nDestTruncate>0 ); | - | ||||||||||||||||||||||||
| 490 | - | |||||||||||||||||||||||||
| 491 | if( pgszSrc<pgszDest ){
| 8-250 | ||||||||||||||||||||||||
| 492 | /* If the source page-size is smaller than the destination page-size, | - | ||||||||||||||||||||||||
| 493 | ** two extra things may need to happen: | - | ||||||||||||||||||||||||
| 494 | ** | - | ||||||||||||||||||||||||
| 495 | ** * The destination may need to be truncated, and | - | ||||||||||||||||||||||||
| 496 | ** | - | ||||||||||||||||||||||||
| 497 | ** * Data stored on the pages immediately following the | - | ||||||||||||||||||||||||
| 498 | ** pending-byte page in the source database may need to be | - | ||||||||||||||||||||||||
| 499 | ** copied into the destination database. | - | ||||||||||||||||||||||||
| 500 | */ | - | ||||||||||||||||||||||||
| 501 | const i64 iSize = (i64)pgszSrc * (i64)nSrcPage; | - | ||||||||||||||||||||||||
| 502 | sqlite3_file * const pFile = sqlite3PagerFile(pDestPager); | - | ||||||||||||||||||||||||
| 503 | Pgno iPg; | - | ||||||||||||||||||||||||
| 504 | int nDstPage; | - | ||||||||||||||||||||||||
| 505 | i64 iOff; | - | ||||||||||||||||||||||||
| 506 | i64 iEnd; | - | ||||||||||||||||||||||||
| 507 | - | |||||||||||||||||||||||||
| 508 | assert( pFile ); | - | ||||||||||||||||||||||||
| 509 | assert( nDestTruncate==0 | - | ||||||||||||||||||||||||
| 510 | || (i64)nDestTruncate*(i64)pgszDest >= iSize || ( | - | ||||||||||||||||||||||||
| 511 | nDestTruncate==(int)(PENDING_BYTE_PAGE(p->pDest->pBt)-1) | - | ||||||||||||||||||||||||
| 512 | && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest | - | ||||||||||||||||||||||||
| 513 | )); | - | ||||||||||||||||||||||||
| 514 | - | |||||||||||||||||||||||||
| 515 | /* This block ensures that all data required to recreate the original | - | ||||||||||||||||||||||||
| 516 | ** database has been stored in the journal for pDestPager and the | - | ||||||||||||||||||||||||
| 517 | ** journal synced to disk. So at this point we may safely modify | - | ||||||||||||||||||||||||
| 518 | ** the database file in any way, knowing that if a power failure | - | ||||||||||||||||||||||||
| 519 | ** occurs, the original database will be reconstructed from the | - | ||||||||||||||||||||||||
| 520 | ** journal file. */ | - | ||||||||||||||||||||||||
| 521 | sqlite3PagerPagecount(pDestPager, &nDstPage); | - | ||||||||||||||||||||||||
| 522 | for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){
| 0-26 | ||||||||||||||||||||||||
| 523 | if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){
| 0-18 | ||||||||||||||||||||||||
| 524 | DbPage *pPg; | - | ||||||||||||||||||||||||
| 525 | rc = sqlite3PagerGet(pDestPager, iPg, &pPg, 0); | - | ||||||||||||||||||||||||
| 526 | if( rc==SQLITE_OK ){
| 0-18 | ||||||||||||||||||||||||
| 527 | rc = sqlite3PagerWrite(pPg); | - | ||||||||||||||||||||||||
| 528 | sqlite3PagerUnref(pPg); | - | ||||||||||||||||||||||||
| 529 | } executed 18 times by 1 test: end of blockExecuted by:
| 18 | ||||||||||||||||||||||||
| 530 | } executed 18 times by 1 test: end of blockExecuted by:
| 18 | ||||||||||||||||||||||||
| 531 | } executed 18 times by 1 test: end of blockExecuted by:
| 18 | ||||||||||||||||||||||||
| 532 | if( rc==SQLITE_OK ){
| 0-8 | ||||||||||||||||||||||||
| 533 | rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1); | - | ||||||||||||||||||||||||
| 534 | } executed 8 times by 1 test: end of blockExecuted by:
| 8 | ||||||||||||||||||||||||
| 535 | - | |||||||||||||||||||||||||
| 536 | /* Write the extra pages and truncate the database file as required */ | - | ||||||||||||||||||||||||
| 537 | iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
| 0-8 | ||||||||||||||||||||||||
| 538 | for( | - | ||||||||||||||||||||||||
| 539 | iOff=PENDING_BYTE+pgszSrc; | - | ||||||||||||||||||||||||
| 540 | rc==SQLITE_OK && iOff<iEnd;
| 0-8 | ||||||||||||||||||||||||
| 541 | iOff+=pgszSrc | - | ||||||||||||||||||||||||
| 542 | ){ | - | ||||||||||||||||||||||||
| 543 | PgHdr *pSrcPg = 0; | - | ||||||||||||||||||||||||
| 544 | const Pgno iSrcPg = (Pgno)((iOff/pgszSrc)+1); | - | ||||||||||||||||||||||||
| 545 | rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg, 0); | - | ||||||||||||||||||||||||
| 546 | if( rc==SQLITE_OK ){
| 0 | ||||||||||||||||||||||||
| 547 | u8 *zData = sqlite3PagerGetData(pSrcPg); | - | ||||||||||||||||||||||||
| 548 | rc = sqlite3OsWrite(pFile, zData, pgszSrc, iOff); | - | ||||||||||||||||||||||||
| 549 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 550 | sqlite3PagerUnref(pSrcPg); | - | ||||||||||||||||||||||||
| 551 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 552 | if( rc==SQLITE_OK ){
| 0-8 | ||||||||||||||||||||||||
| 553 | rc = backupTruncateFile(pFile, iSize); | - | ||||||||||||||||||||||||
| 554 | } executed 8 times by 1 test: end of blockExecuted by:
| 8 | ||||||||||||||||||||||||
| 555 | - | |||||||||||||||||||||||||
| 556 | /* Sync the database file to disk. */ | - | ||||||||||||||||||||||||
| 557 | if( rc==SQLITE_OK ){
| 0-8 | ||||||||||||||||||||||||
| 558 | rc = sqlite3PagerSync(pDestPager, 0); | - | ||||||||||||||||||||||||
| 559 | } executed 8 times by 1 test: end of blockExecuted by:
| 8 | ||||||||||||||||||||||||
| 560 | }else{ executed 8 times by 1 test: end of blockExecuted by:
| 8 | ||||||||||||||||||||||||
| 561 | sqlite3PagerTruncateImage(pDestPager, nDestTruncate); | - | ||||||||||||||||||||||||
| 562 | rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0); | - | ||||||||||||||||||||||||
| 563 | } executed 250 times by 2 tests: end of blockExecuted by:
| 250 | ||||||||||||||||||||||||
| 564 | - | |||||||||||||||||||||||||
| 565 | /* Finish committing the transaction to the destination database. */ | - | ||||||||||||||||||||||||
| 566 | if( SQLITE_OK==rc
| 95-163 | ||||||||||||||||||||||||
| 567 | && SQLITE_OK==(rc = sqlite3BtreeCommitPhaseTwo(p->pDest, 0))
| 0-163 | ||||||||||||||||||||||||
| 568 | ){ | - | ||||||||||||||||||||||||
| 569 | rc = SQLITE_DONE; | - | ||||||||||||||||||||||||
| 570 | } executed 163 times by 2 tests: end of blockExecuted by:
| 163 | ||||||||||||||||||||||||
| 571 | } executed 258 times by 2 tests: end of blockExecuted by:
| 258 | ||||||||||||||||||||||||
| 572 | } executed 258 times by 2 tests: end of blockExecuted by:
| 258 | ||||||||||||||||||||||||
| 573 | - | |||||||||||||||||||||||||
| 574 | /* If bCloseTrans is true, then this function opened a read transaction | - | ||||||||||||||||||||||||
| 575 | ** on the source database. Close the read transaction here. There is | - | ||||||||||||||||||||||||
| 576 | ** no need to check the return values of the btree methods here, as | - | ||||||||||||||||||||||||
| 577 | ** "committing" a read-only transaction cannot fail. | - | ||||||||||||||||||||||||
| 578 | */ | - | ||||||||||||||||||||||||
| 579 | if( bCloseTrans ){
| 49-500 | ||||||||||||||||||||||||
| 580 | TESTONLY( int rc2 ); | - | ||||||||||||||||||||||||
| 581 | TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(p->pSrc, 0); | - | ||||||||||||||||||||||||
| 582 | TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc, 0); | - | ||||||||||||||||||||||||
| 583 | assert( rc2==SQLITE_OK ); | - | ||||||||||||||||||||||||
| 584 | } executed 49 times by 1 test: end of blockExecuted by:
| 49 | ||||||||||||||||||||||||
| 585 | - | |||||||||||||||||||||||||
| 586 | if( rc==SQLITE_IOERR_NOMEM ){
| 0-549 | ||||||||||||||||||||||||
| 587 | rc = SQLITE_NOMEM_BKPT; | - | ||||||||||||||||||||||||
| 588 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 589 | p->rc = rc; | - | ||||||||||||||||||||||||
| 590 | } executed 549 times by 2 tests: end of blockExecuted by:
| 549 | ||||||||||||||||||||||||
| 591 | if( p->pDestDb ){
| 52-498 | ||||||||||||||||||||||||
| 592 | sqlite3_mutex_leave(p->pDestDb->mutex); | - | ||||||||||||||||||||||||
| 593 | } executed 52 times by 1 test: end of blockExecuted by:
| 52 | ||||||||||||||||||||||||
| 594 | sqlite3BtreeLeave(p->pSrc); | - | ||||||||||||||||||||||||
| 595 | sqlite3_mutex_leave(p->pSrcDb->mutex); | - | ||||||||||||||||||||||||
| 596 | return rc; executed 550 times by 2 tests: return rc;Executed by:
| 550 | ||||||||||||||||||||||||
| 597 | } | - | ||||||||||||||||||||||||
| 598 | - | |||||||||||||||||||||||||
| 599 | /* | - | ||||||||||||||||||||||||
| 600 | ** Release all resources associated with an sqlite3_backup* handle. | - | ||||||||||||||||||||||||
| 601 | */ | - | ||||||||||||||||||||||||
| 602 | int sqlite3_backup_finish(sqlite3_backup *p){ | - | ||||||||||||||||||||||||
| 603 | sqlite3_backup **pp; /* Ptr to head of pagers backup list */ | - | ||||||||||||||||||||||||
| 604 | sqlite3 *pSrcDb; /* Source database connection */ | - | ||||||||||||||||||||||||
| 605 | int rc; /* Value to return */ | - | ||||||||||||||||||||||||
| 606 | - | |||||||||||||||||||||||||
| 607 | /* Enter the mutexes */ | - | ||||||||||||||||||||||||
| 608 | if( p==0 ) return SQLITE_OK; never executed: return 0;
| 0-537 | ||||||||||||||||||||||||
| 609 | pSrcDb = p->pSrcDb; | - | ||||||||||||||||||||||||
| 610 | sqlite3_mutex_enter(pSrcDb->mutex); | - | ||||||||||||||||||||||||
| 611 | sqlite3BtreeEnter(p->pSrc); | - | ||||||||||||||||||||||||
| 612 | if( p->pDestDb ){
| 39-498 | ||||||||||||||||||||||||
| 613 | sqlite3_mutex_enter(p->pDestDb->mutex); | - | ||||||||||||||||||||||||
| 614 | } executed 39 times by 1 test: end of blockExecuted by:
| 39 | ||||||||||||||||||||||||
| 615 | - | |||||||||||||||||||||||||
| 616 | /* Detach this backup from the source pager. */ | - | ||||||||||||||||||||||||
| 617 | if( p->pDestDb ){
| 39-498 | ||||||||||||||||||||||||
| 618 | p->pSrc->nBackup--; | - | ||||||||||||||||||||||||
| 619 | } executed 39 times by 1 test: end of blockExecuted by:
| 39 | ||||||||||||||||||||||||
| 620 | if( p->isAttached ){
| 7-530 | ||||||||||||||||||||||||
| 621 | pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc)); | - | ||||||||||||||||||||||||
| 622 | while( *pp!=p ){
| 0-7 | ||||||||||||||||||||||||
| 623 | pp = &(*pp)->pNext; | - | ||||||||||||||||||||||||
| 624 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 625 | *pp = p->pNext; | - | ||||||||||||||||||||||||
| 626 | } executed 7 times by 1 test: end of blockExecuted by:
| 7 | ||||||||||||||||||||||||
| 627 | - | |||||||||||||||||||||||||
| 628 | /* If a transaction is still open on the Btree, roll it back. */ | - | ||||||||||||||||||||||||
| 629 | sqlite3BtreeRollback(p->pDest, SQLITE_OK, 0); | - | ||||||||||||||||||||||||
| 630 | - | |||||||||||||||||||||||||
| 631 | /* Set the error code of the destination database handle. */ | - | ||||||||||||||||||||||||
| 632 | rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
| 163-374 | ||||||||||||||||||||||||
| 633 | if( p->pDestDb ){
| 39-498 | ||||||||||||||||||||||||
| 634 | sqlite3Error(p->pDestDb, rc); | - | ||||||||||||||||||||||||
| 635 | - | |||||||||||||||||||||||||
| 636 | /* Exit the mutexes and free the backup context structure. */ | - | ||||||||||||||||||||||||
| 637 | sqlite3LeaveMutexAndCloseZombie(p->pDestDb); | - | ||||||||||||||||||||||||
| 638 | } executed 39 times by 1 test: end of blockExecuted by:
| 39 | ||||||||||||||||||||||||
| 639 | sqlite3BtreeLeave(p->pSrc); | - | ||||||||||||||||||||||||
| 640 | if( p->pDestDb ){
| 39-498 | ||||||||||||||||||||||||
| 641 | /* EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a | - | ||||||||||||||||||||||||
| 642 | ** call to sqlite3_backup_init() and is destroyed by a call to | - | ||||||||||||||||||||||||
| 643 | ** sqlite3_backup_finish(). */ | - | ||||||||||||||||||||||||
| 644 | sqlite3_free(p); | - | ||||||||||||||||||||||||
| 645 | } executed 39 times by 1 test: end of blockExecuted by:
| 39 | ||||||||||||||||||||||||
| 646 | sqlite3LeaveMutexAndCloseZombie(pSrcDb); | - | ||||||||||||||||||||||||
| 647 | return rc; executed 537 times by 2 tests: return rc;Executed by:
| 537 | ||||||||||||||||||||||||
| 648 | } | - | ||||||||||||||||||||||||
| 649 | - | |||||||||||||||||||||||||
| 650 | /* | - | ||||||||||||||||||||||||
| 651 | ** Return the number of pages still to be backed up as of the most recent | - | ||||||||||||||||||||||||
| 652 | ** call to sqlite3_backup_step(). | - | ||||||||||||||||||||||||
| 653 | */ | - | ||||||||||||||||||||||||
| 654 | int sqlite3_backup_remaining(sqlite3_backup *p){ | - | ||||||||||||||||||||||||
| 655 | #ifdef SQLITE_ENABLE_API_ARMOR | - | ||||||||||||||||||||||||
| 656 | if( p==0 ){ | - | ||||||||||||||||||||||||
| 657 | (void)SQLITE_MISUSE_BKPT; | - | ||||||||||||||||||||||||
| 658 | return 0; | - | ||||||||||||||||||||||||
| 659 | } | - | ||||||||||||||||||||||||
| 660 | #endif | - | ||||||||||||||||||||||||
| 661 | return p->nRemaining; never executed: return p->nRemaining; | 0 | ||||||||||||||||||||||||
| 662 | } | - | ||||||||||||||||||||||||
| 663 | - | |||||||||||||||||||||||||
| 664 | /* | - | ||||||||||||||||||||||||
| 665 | ** Return the total number of pages in the source database as of the most | - | ||||||||||||||||||||||||
| 666 | ** recent call to sqlite3_backup_step(). | - | ||||||||||||||||||||||||
| 667 | */ | - | ||||||||||||||||||||||||
| 668 | int sqlite3_backup_pagecount(sqlite3_backup *p){ | - | ||||||||||||||||||||||||
| 669 | #ifdef SQLITE_ENABLE_API_ARMOR | - | ||||||||||||||||||||||||
| 670 | if( p==0 ){ | - | ||||||||||||||||||||||||
| 671 | (void)SQLITE_MISUSE_BKPT; | - | ||||||||||||||||||||||||
| 672 | return 0; | - | ||||||||||||||||||||||||
| 673 | } | - | ||||||||||||||||||||||||
| 674 | #endif | - | ||||||||||||||||||||||||
| 675 | return p->nPagecount; never executed: return p->nPagecount; | 0 | ||||||||||||||||||||||||
| 676 | } | - | ||||||||||||||||||||||||
| 677 | - | |||||||||||||||||||||||||
| 678 | /* | - | ||||||||||||||||||||||||
| 679 | ** This function is called after the contents of page iPage of the | - | ||||||||||||||||||||||||
| 680 | ** source database have been modified. If page iPage has already been | - | ||||||||||||||||||||||||
| 681 | ** copied into the destination database, then the data written to the | - | ||||||||||||||||||||||||
| 682 | ** destination is now invalidated. The destination copy of iPage needs | - | ||||||||||||||||||||||||
| 683 | ** to be updated with the new data before the backup operation is | - | ||||||||||||||||||||||||
| 684 | ** complete. | - | ||||||||||||||||||||||||
| 685 | ** | - | ||||||||||||||||||||||||
| 686 | ** It is assumed that the mutex associated with the BtShared object | - | ||||||||||||||||||||||||
| 687 | ** corresponding to the source database is held when this function is | - | ||||||||||||||||||||||||
| 688 | ** called. | - | ||||||||||||||||||||||||
| 689 | */ | - | ||||||||||||||||||||||||
| 690 | static SQLITE_NOINLINE void backupUpdate( | - | ||||||||||||||||||||||||
| 691 | sqlite3_backup *p, | - | ||||||||||||||||||||||||
| 692 | Pgno iPage, | - | ||||||||||||||||||||||||
| 693 | const u8 *aData | - | ||||||||||||||||||||||||
| 694 | ){ | - | ||||||||||||||||||||||||
| 695 | assert( p!=0 ); | - | ||||||||||||||||||||||||
| 696 | do{ | - | ||||||||||||||||||||||||
| 697 | assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) ); | - | ||||||||||||||||||||||||
| 698 | if( !isFatalError(p->rc) && iPage<p->iNext ){
| 0-2541 | ||||||||||||||||||||||||
| 699 | /* The backup process p has already copied page iPage. But now it | - | ||||||||||||||||||||||||
| 700 | ** has been modified by a transaction on the source pager. Copy | - | ||||||||||||||||||||||||
| 701 | ** the new data into the backup. | - | ||||||||||||||||||||||||
| 702 | */ | - | ||||||||||||||||||||||||
| 703 | int rc; | - | ||||||||||||||||||||||||
| 704 | assert( p->pDestDb ); | - | ||||||||||||||||||||||||
| 705 | sqlite3_mutex_enter(p->pDestDb->mutex); | - | ||||||||||||||||||||||||
| 706 | rc = backupOnePage(p, iPage, aData, 1); | - | ||||||||||||||||||||||||
| 707 | sqlite3_mutex_leave(p->pDestDb->mutex); | - | ||||||||||||||||||||||||
| 708 | assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED ); | - | ||||||||||||||||||||||||
| 709 | if( rc!=SQLITE_OK ){
| 0-1465 | ||||||||||||||||||||||||
| 710 | p->rc = rc; | - | ||||||||||||||||||||||||
| 711 | } never executed: end of block | 0 | ||||||||||||||||||||||||
| 712 | } executed 1465 times by 1 test: end of blockExecuted by:
| 1465 | ||||||||||||||||||||||||
| 713 | }while( (p = p->pNext)!=0 ); executed 2541 times by 1 test: end of blockExecuted by:
| 0-2541 | ||||||||||||||||||||||||
| 714 | } executed 2541 times by 1 test: end of blockExecuted by:
| 2541 | ||||||||||||||||||||||||
| 715 | void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, const u8 *aData){ | - | ||||||||||||||||||||||||
| 716 | if( pBackup ) backupUpdate(pBackup, iPage, aData); executed 2541 times by 1 test: backupUpdate(pBackup, iPage, aData);Executed by:
| 2541-1492489 | ||||||||||||||||||||||||
| 717 | } executed 1495030 times by 131 tests: end of blockExecuted by:
| 1495030 | ||||||||||||||||||||||||
| 718 | - | |||||||||||||||||||||||||
| 719 | /* | - | ||||||||||||||||||||||||
| 720 | ** Restart the backup process. This is called when the pager layer | - | ||||||||||||||||||||||||
| 721 | ** detects that the database has been modified by an external database | - | ||||||||||||||||||||||||
| 722 | ** connection. In this case there is no way of knowing which of the | - | ||||||||||||||||||||||||
| 723 | ** pages that have been copied into the destination database are still | - | ||||||||||||||||||||||||
| 724 | ** valid and which are not, so the entire process needs to be restarted. | - | ||||||||||||||||||||||||
| 725 | ** | - | ||||||||||||||||||||||||
| 726 | ** It is assumed that the mutex associated with the BtShared object | - | ||||||||||||||||||||||||
| 727 | ** corresponding to the source database is held when this function is | - | ||||||||||||||||||||||||
| 728 | ** called. | - | ||||||||||||||||||||||||
| 729 | */ | - | ||||||||||||||||||||||||
| 730 | void sqlite3BackupRestart(sqlite3_backup *pBackup){ | - | ||||||||||||||||||||||||
| 731 | sqlite3_backup *p; /* Iterator variable */ | - | ||||||||||||||||||||||||
| 732 | for(p=pBackup; p; p=p->pNext){
| 64-205694 | ||||||||||||||||||||||||
| 733 | assert( sqlite3_mutex_held(p->pSrc->pBt->mutex) ); | - | ||||||||||||||||||||||||
| 734 | p->iNext = 1; | - | ||||||||||||||||||||||||
| 735 | } executed 64 times by 1 test: end of blockExecuted by:
| 64 | ||||||||||||||||||||||||
| 736 | } executed 205694 times by 438 tests: end of blockExecuted by:
| 205694 | ||||||||||||||||||||||||
| 737 | - | |||||||||||||||||||||||||
| 738 | #ifndef SQLITE_OMIT_VACUUM | - | ||||||||||||||||||||||||
| 739 | /* | - | ||||||||||||||||||||||||
| 740 | ** Copy the complete content of pBtFrom into pBtTo. A transaction | - | ||||||||||||||||||||||||
| 741 | ** must be active for both files. | - | ||||||||||||||||||||||||
| 742 | ** | - | ||||||||||||||||||||||||
| 743 | ** The size of file pTo may be reduced by this operation. If anything | - | ||||||||||||||||||||||||
| 744 | ** goes wrong, the transaction on pTo is rolled back. If successful, the | - | ||||||||||||||||||||||||
| 745 | ** transaction is committed before returning. | - | ||||||||||||||||||||||||
| 746 | */ | - | ||||||||||||||||||||||||
| 747 | int sqlite3BtreeCopyFile(Btree *pTo, Btree *pFrom){ | - | ||||||||||||||||||||||||
| 748 | int rc; | - | ||||||||||||||||||||||||
| 749 | sqlite3_file *pFd; /* File descriptor for database pTo */ | - | ||||||||||||||||||||||||
| 750 | sqlite3_backup b; | - | ||||||||||||||||||||||||
| 751 | sqlite3BtreeEnter(pTo); | - | ||||||||||||||||||||||||
| 752 | sqlite3BtreeEnter(pFrom); | - | ||||||||||||||||||||||||
| 753 | - | |||||||||||||||||||||||||
| 754 | assert( sqlite3BtreeIsInTrans(pTo) ); | - | ||||||||||||||||||||||||
| 755 | pFd = sqlite3PagerFile(sqlite3BtreePager(pTo)); | - | ||||||||||||||||||||||||
| 756 | if( pFd->pMethods ){
| 6-492 | ||||||||||||||||||||||||
| 757 | i64 nByte = sqlite3BtreeGetPageSize(pFrom)*(i64)sqlite3BtreeLastPage(pFrom); | - | ||||||||||||||||||||||||
| 758 | rc = sqlite3OsFileControl(pFd, SQLITE_FCNTL_OVERWRITE, &nByte); | - | ||||||||||||||||||||||||
| 759 | if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK; executed 492 times by 2 tests: rc = 0;Executed by:
| 0-492 | ||||||||||||||||||||||||
| 760 | if( rc ) goto copy_finished; never executed: goto copy_finished;
| 0-492 | ||||||||||||||||||||||||
| 761 | } executed 492 times by 2 tests: end of blockExecuted by:
| 492 | ||||||||||||||||||||||||
| 762 | - | |||||||||||||||||||||||||
| 763 | /* Set up an sqlite3_backup object. sqlite3_backup.pDestDb must be set | - | ||||||||||||||||||||||||
| 764 | ** to 0. This is used by the implementations of sqlite3_backup_step() | - | ||||||||||||||||||||||||
| 765 | ** and sqlite3_backup_finish() to detect that they are being called | - | ||||||||||||||||||||||||
| 766 | ** from this function, not directly by the user. | - | ||||||||||||||||||||||||
| 767 | */ | - | ||||||||||||||||||||||||
| 768 | memset(&b, 0, sizeof(b)); | - | ||||||||||||||||||||||||
| 769 | b.pSrcDb = pFrom->db; | - | ||||||||||||||||||||||||
| 770 | b.pSrc = pFrom; | - | ||||||||||||||||||||||||
| 771 | b.pDest = pTo; | - | ||||||||||||||||||||||||
| 772 | b.iNext = 1; | - | ||||||||||||||||||||||||
| 773 | - | |||||||||||||||||||||||||
| 774 | #ifdef SQLITE_HAS_CODEC | - | ||||||||||||||||||||||||
| 775 | sqlite3PagerAlignReserve(sqlite3BtreePager(pTo), sqlite3BtreePager(pFrom)); | - | ||||||||||||||||||||||||
| 776 | #endif | - | ||||||||||||||||||||||||
| 777 | - | |||||||||||||||||||||||||
| 778 | /* 0x7FFFFFFF is the hard limit for the number of pages in a database | - | ||||||||||||||||||||||||
| 779 | ** file. By passing this as the number of pages to copy to | - | ||||||||||||||||||||||||
| 780 | ** sqlite3_backup_step(), we can guarantee that the copy finishes | - | ||||||||||||||||||||||||
| 781 | ** within a single call (unless an error occurs). The assert() statement | - | ||||||||||||||||||||||||
| 782 | ** checks this assumption - (p->rc) should be set to either SQLITE_DONE | - | ||||||||||||||||||||||||
| 783 | ** or an error code. */ | - | ||||||||||||||||||||||||
| 784 | sqlite3_backup_step(&b, 0x7FFFFFFF); | - | ||||||||||||||||||||||||
| 785 | assert( b.rc!=SQLITE_OK ); | - | ||||||||||||||||||||||||
| 786 | - | |||||||||||||||||||||||||
| 787 | rc = sqlite3_backup_finish(&b); | - | ||||||||||||||||||||||||
| 788 | if( rc==SQLITE_OK ){
| 130-368 | ||||||||||||||||||||||||
| 789 | pTo->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED; | - | ||||||||||||||||||||||||
| 790 | }else{ executed 130 times by 2 tests: end of blockExecuted by:
| 130 | ||||||||||||||||||||||||
| 791 | sqlite3PagerClearCache(sqlite3BtreePager(b.pDest)); | - | ||||||||||||||||||||||||
| 792 | } executed 368 times by 1 test: end of blockExecuted by:
| 368 | ||||||||||||||||||||||||
| 793 | - | |||||||||||||||||||||||||
| 794 | assert( sqlite3BtreeIsInTrans(pTo)==0 ); | - | ||||||||||||||||||||||||
| 795 | copy_finished: code before this statement executed 498 times by 2 tests: copy_finished:Executed by:
| 498 | ||||||||||||||||||||||||
| 796 | sqlite3BtreeLeave(pFrom); | - | ||||||||||||||||||||||||
| 797 | sqlite3BtreeLeave(pTo); | - | ||||||||||||||||||||||||
| 798 | return rc; executed 498 times by 2 tests: return rc;Executed by:
| 498 | ||||||||||||||||||||||||
| 799 | } | - | ||||||||||||||||||||||||
| 800 | #endif /* SQLITE_OMIT_VACUUM */ | - | ||||||||||||||||||||||||
| Source code | Switch to Preprocessed file |