OLD | NEW |
1 /* | 1 /* |
2 ** 2009 January 28 | 2 ** 2009 January 28 |
3 ** | 3 ** |
4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
6 ** | 6 ** |
7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
10 ** | 10 ** |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
76 ** a NULL pointer and write an error message to pErrorDb. | 76 ** a NULL pointer and write an error message to pErrorDb. |
77 ** | 77 ** |
78 ** If the "temp" database is requested, it may need to be opened by this | 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 | 79 ** function. If an error occurs while doing so, return 0 and write an |
80 ** error message to pErrorDb. | 80 ** error message to pErrorDb. |
81 */ | 81 */ |
82 static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ | 82 static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){ |
83 int i = sqlite3FindDbName(pDb, zDb); | 83 int i = sqlite3FindDbName(pDb, zDb); |
84 | 84 |
85 if( i==1 ){ | 85 if( i==1 ){ |
86 Parse *pParse; | 86 Parse sParse; |
87 int rc = 0; | 87 int rc = 0; |
88 pParse = sqlite3StackAllocZero(pErrorDb, sizeof(*pParse)); | 88 memset(&sParse, 0, sizeof(sParse)); |
89 if( pParse==0 ){ | 89 sParse.db = pDb; |
90 sqlite3ErrorWithMsg(pErrorDb, SQLITE_NOMEM, "out of memory"); | 90 if( sqlite3OpenTempDatabase(&sParse) ){ |
91 rc = SQLITE_NOMEM; | 91 sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg); |
92 }else{ | 92 rc = SQLITE_ERROR; |
93 pParse->db = pDb; | |
94 if( sqlite3OpenTempDatabase(pParse) ){ | |
95 sqlite3ErrorWithMsg(pErrorDb, pParse->rc, "%s", pParse->zErrMsg); | |
96 rc = SQLITE_ERROR; | |
97 } | |
98 sqlite3DbFree(pErrorDb, pParse->zErrMsg); | |
99 sqlite3ParserReset(pParse); | |
100 sqlite3StackFree(pErrorDb, pParse); | |
101 } | 93 } |
| 94 sqlite3DbFree(pErrorDb, sParse.zErrMsg); |
| 95 sqlite3ParserReset(&sParse); |
102 if( rc ){ | 96 if( rc ){ |
103 return 0; | 97 return 0; |
104 } | 98 } |
105 } | 99 } |
106 | 100 |
107 if( i<0 ){ | 101 if( i<0 ){ |
108 sqlite3ErrorWithMsg(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb); | 102 sqlite3ErrorWithMsg(pErrorDb, SQLITE_ERROR, "unknown database %s", zDb); |
109 return 0; | 103 return 0; |
110 } | 104 } |
111 | 105 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 pDestDb, SQLITE_ERROR, "source and destination must be distinct" | 169 pDestDb, SQLITE_ERROR, "source and destination must be distinct" |
176 ); | 170 ); |
177 p = 0; | 171 p = 0; |
178 }else { | 172 }else { |
179 /* Allocate space for a new sqlite3_backup object... | 173 /* Allocate space for a new sqlite3_backup object... |
180 ** EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a | 174 ** EVIDENCE-OF: R-64852-21591 The sqlite3_backup object is created by a |
181 ** call to sqlite3_backup_init() and is destroyed by a call to | 175 ** call to sqlite3_backup_init() and is destroyed by a call to |
182 ** sqlite3_backup_finish(). */ | 176 ** sqlite3_backup_finish(). */ |
183 p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup)); | 177 p = (sqlite3_backup *)sqlite3MallocZero(sizeof(sqlite3_backup)); |
184 if( !p ){ | 178 if( !p ){ |
185 sqlite3Error(pDestDb, SQLITE_NOMEM); | 179 sqlite3Error(pDestDb, SQLITE_NOMEM_BKPT); |
186 } | 180 } |
187 } | 181 } |
188 | 182 |
189 /* If the allocation succeeded, populate the new object. */ | 183 /* If the allocation succeeded, populate the new object. */ |
190 if( p ){ | 184 if( p ){ |
191 p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb); | 185 p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb); |
192 p->pDest = findBtree(pDestDb, pDestDb, zDestDb); | 186 p->pDest = findBtree(pDestDb, pDestDb, zDestDb); |
193 p->pDestDb = pDestDb; | 187 p->pDestDb = pDestDb; |
194 p->pSrcDb = pSrcDb; | 188 p->pSrcDb = pSrcDb; |
195 p->iNext = 1; | 189 p->iNext = 1; |
196 p->isAttached = 0; | 190 p->isAttached = 0; |
197 | 191 |
198 if( 0==p->pSrc || 0==p->pDest | 192 if( 0==p->pSrc || 0==p->pDest |
199 || setDestPgsz(p)==SQLITE_NOMEM | |
200 || checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK | 193 || checkReadTransaction(pDestDb, p->pDest)!=SQLITE_OK |
201 ){ | 194 ){ |
202 /* One (or both) of the named databases did not exist or an OOM | 195 /* One (or both) of the named databases did not exist or an OOM |
203 ** error was hit. Or there is a transaction open on the destination | 196 ** error was hit. Or there is a transaction open on the destination |
204 ** database. The error has already been written into the pDestDb | 197 ** database. The error has already been written into the pDestDb |
205 ** handle. All that is left to do here is free the sqlite3_backup | 198 ** handle. All that is left to do here is free the sqlite3_backup |
206 ** structure. */ | 199 ** structure. */ |
207 sqlite3_free(p); | 200 sqlite3_free(p); |
208 p = 0; | 201 p = 0; |
209 } | 202 } |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
377 | 370 |
378 /* If the source pager is currently in a write-transaction, return | 371 /* If the source pager is currently in a write-transaction, return |
379 ** SQLITE_BUSY immediately. | 372 ** SQLITE_BUSY immediately. |
380 */ | 373 */ |
381 if( p->pDestDb && p->pSrc->pBt->inTransaction==TRANS_WRITE ){ | 374 if( p->pDestDb && p->pSrc->pBt->inTransaction==TRANS_WRITE ){ |
382 rc = SQLITE_BUSY; | 375 rc = SQLITE_BUSY; |
383 }else{ | 376 }else{ |
384 rc = SQLITE_OK; | 377 rc = SQLITE_OK; |
385 } | 378 } |
386 | 379 |
387 /* Lock the destination database, if it is not locked already. */ | |
388 if( SQLITE_OK==rc && p->bDestLocked==0 | |
389 && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2)) | |
390 ){ | |
391 p->bDestLocked = 1; | |
392 sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema); | |
393 } | |
394 | |
395 /* If there is no open read-transaction on the source database, open | 380 /* If there is no open read-transaction on the source database, open |
396 ** one now. If a transaction is opened here, then it will be closed | 381 ** one now. If a transaction is opened here, then it will be closed |
397 ** before this function exits. | 382 ** before this function exits. |
398 */ | 383 */ |
399 if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){ | 384 if( rc==SQLITE_OK && 0==sqlite3BtreeIsInReadTrans(p->pSrc) ){ |
400 rc = sqlite3BtreeBeginTrans(p->pSrc, 0); | 385 rc = sqlite3BtreeBeginTrans(p->pSrc, 0); |
401 bCloseTrans = 1; | 386 bCloseTrans = 1; |
402 } | 387 } |
403 | 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 ){ |
| 396 rc = SQLITE_NOMEM; |
| 397 } |
| 398 |
| 399 /* Lock the destination database, if it is not locked already. */ |
| 400 if( SQLITE_OK==rc && p->bDestLocked==0 |
| 401 && SQLITE_OK==(rc = sqlite3BtreeBeginTrans(p->pDest, 2)) |
| 402 ){ |
| 403 p->bDestLocked = 1; |
| 404 sqlite3BtreeGetMeta(p->pDest, BTREE_SCHEMA_VERSION, &p->iDestSchema); |
| 405 } |
| 406 |
404 /* Do not allow backup if the destination database is in WAL mode | 407 /* Do not allow backup if the destination database is in WAL mode |
405 ** and the page sizes are different between source and destination */ | 408 ** and the page sizes are different between source and destination */ |
406 pgszSrc = sqlite3BtreeGetPageSize(p->pSrc); | 409 pgszSrc = sqlite3BtreeGetPageSize(p->pSrc); |
407 pgszDest = sqlite3BtreeGetPageSize(p->pDest); | 410 pgszDest = sqlite3BtreeGetPageSize(p->pDest); |
408 destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest)); | 411 destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest)); |
409 if( SQLITE_OK==rc && destMode==PAGER_JOURNALMODE_WAL && pgszSrc!=pgszDest ){ | 412 if( SQLITE_OK==rc && destMode==PAGER_JOURNALMODE_WAL && pgszSrc!=pgszDest ){ |
410 rc = SQLITE_READONLY; | 413 rc = SQLITE_READONLY; |
411 } | 414 } |
412 | 415 |
413 /* Now that there is a read-lock on the source database, query the | 416 /* Now that there is a read-lock on the source database, query the |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
574 ** "committing" a read-only transaction cannot fail. | 577 ** "committing" a read-only transaction cannot fail. |
575 */ | 578 */ |
576 if( bCloseTrans ){ | 579 if( bCloseTrans ){ |
577 TESTONLY( int rc2 ); | 580 TESTONLY( int rc2 ); |
578 TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(p->pSrc, 0); | 581 TESTONLY( rc2 = ) sqlite3BtreeCommitPhaseOne(p->pSrc, 0); |
579 TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc, 0); | 582 TESTONLY( rc2 |= ) sqlite3BtreeCommitPhaseTwo(p->pSrc, 0); |
580 assert( rc2==SQLITE_OK ); | 583 assert( rc2==SQLITE_OK ); |
581 } | 584 } |
582 | 585 |
583 if( rc==SQLITE_IOERR_NOMEM ){ | 586 if( rc==SQLITE_IOERR_NOMEM ){ |
584 rc = SQLITE_NOMEM; | 587 rc = SQLITE_NOMEM_BKPT; |
585 } | 588 } |
586 p->rc = rc; | 589 p->rc = rc; |
587 } | 590 } |
588 if( p->pDestDb ){ | 591 if( p->pDestDb ){ |
589 sqlite3_mutex_leave(p->pDestDb->mutex); | 592 sqlite3_mutex_leave(p->pDestDb->mutex); |
590 } | 593 } |
591 sqlite3BtreeLeave(p->pSrc); | 594 sqlite3BtreeLeave(p->pSrc); |
592 sqlite3_mutex_leave(p->pSrcDb->mutex); | 595 sqlite3_mutex_leave(p->pSrcDb->mutex); |
593 return rc; | 596 return rc; |
594 } | 597 } |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
770 | 773 |
771 #ifdef SQLITE_HAS_CODEC | 774 #ifdef SQLITE_HAS_CODEC |
772 sqlite3PagerAlignReserve(sqlite3BtreePager(pTo), sqlite3BtreePager(pFrom)); | 775 sqlite3PagerAlignReserve(sqlite3BtreePager(pTo), sqlite3BtreePager(pFrom)); |
773 #endif | 776 #endif |
774 | 777 |
775 /* 0x7FFFFFFF is the hard limit for the number of pages in a database | 778 /* 0x7FFFFFFF is the hard limit for the number of pages in a database |
776 ** file. By passing this as the number of pages to copy to | 779 ** file. By passing this as the number of pages to copy to |
777 ** sqlite3_backup_step(), we can guarantee that the copy finishes | 780 ** sqlite3_backup_step(), we can guarantee that the copy finishes |
778 ** within a single call (unless an error occurs). The assert() statement | 781 ** within a single call (unless an error occurs). The assert() statement |
779 ** checks this assumption - (p->rc) should be set to either SQLITE_DONE | 782 ** checks this assumption - (p->rc) should be set to either SQLITE_DONE |
780 ** or an error code. | 783 ** or an error code. */ |
781 */ | |
782 sqlite3_backup_step(&b, 0x7FFFFFFF); | 784 sqlite3_backup_step(&b, 0x7FFFFFFF); |
783 assert( b.rc!=SQLITE_OK ); | 785 assert( b.rc!=SQLITE_OK ); |
| 786 |
784 rc = sqlite3_backup_finish(&b); | 787 rc = sqlite3_backup_finish(&b); |
785 if( rc==SQLITE_OK ){ | 788 if( rc==SQLITE_OK ){ |
786 pTo->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED; | 789 pTo->pBt->btsFlags &= ~BTS_PAGESIZE_FIXED; |
787 }else{ | 790 }else{ |
788 sqlite3PagerClearCache(sqlite3BtreePager(b.pDest)); | 791 sqlite3PagerClearCache(sqlite3BtreePager(b.pDest)); |
789 } | 792 } |
790 | 793 |
791 assert( sqlite3BtreeIsInTrans(pTo)==0 ); | 794 assert( sqlite3BtreeIsInTrans(pTo)==0 ); |
792 copy_finished: | 795 copy_finished: |
793 sqlite3BtreeLeave(pFrom); | 796 sqlite3BtreeLeave(pFrom); |
794 sqlite3BtreeLeave(pTo); | 797 sqlite3BtreeLeave(pTo); |
795 return rc; | 798 return rc; |
796 } | 799 } |
797 #endif /* SQLITE_OMIT_VACUUM */ | 800 #endif /* SQLITE_OMIT_VACUUM */ |
OLD | NEW |