Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Have calls to sqlite3_backup_init() fail if there is already a read or read-write transaction open on the destination database. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
169b5505498c0a7ee2b5dbb2ba13c41d |
User & Date: | dan 2014-11-13 14:18:25 |
Context
2014-11-13
| ||
14:30 | Modify the documentation for sqlite3_backup_init() to indicate that it will fail if there is already a read or read-write transaction open on the destination database. (check-in: ef03a203 user: dan tags: trunk) | |
14:18 | Have calls to sqlite3_backup_init() fail if there is already a read or read-write transaction open on the destination database. (check-in: 169b5505 user: dan tags: trunk) | |
2014-11-12
| ||
17:45 | Add further tests for rollback operations in the presence of ongoing selects. (check-in: eaf3aae0 user: dan tags: trunk) | |
Changes
Changes to src/backup.c.
︙ | ︙ | |||
117 118 119 120 121 122 123 124 125 126 127 128 129 130 | ** of the source. */ static int setDestPgsz(sqlite3_backup *p){ int rc; rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),-1,0); return rc; } /* ** Create an sqlite3_backup process to copy the contents of zSrcDb from ** connection handle pSrcDb to zDestDb in pDestDb. If successful, return ** a pointer to the new sqlite3_backup object. ** ** If an error occurs, NULL is returned and an error code and error message | > > > > > > > > > > > > > > | 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | ** of the source. */ static int setDestPgsz(sqlite3_backup *p){ int rc; rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),-1,0); return rc; } /* ** Check that there is no open read-transaction on the b-tree passed as the ** second argument. If there is not, return SQLITE_OK. Otherwise, if there ** is an open read-transaction, return SQLITE_ERROR and leave an error ** message in database handle db. */ static int checkReadTransaction(sqlite3 *db, Btree *p){ if( sqlite3BtreeIsInReadTrans(p) ){ sqlite3ErrorWithMsg(db, SQLITE_ERROR, "destination database is in use"); return SQLITE_ERROR; } return SQLITE_OK; } /* ** Create an sqlite3_backup process to copy the contents of zSrcDb from ** connection handle pSrcDb to zDestDb in pDestDb. If successful, return ** a pointer to the new sqlite3_backup object. ** ** If an error occurs, NULL is returned and an error code and error message |
︙ | ︙ | |||
177 178 179 180 181 182 183 | p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb); p->pDest = findBtree(pDestDb, pDestDb, zDestDb); p->pDestDb = pDestDb; p->pSrcDb = pSrcDb; p->iNext = 1; p->isAttached = 0; | | > > > > | | | < | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | p->pSrc = findBtree(pDestDb, pSrcDb, zSrcDb); p->pDest = findBtree(pDestDb, pDestDb, zDestDb); p->pDestDb = pDestDb; p->pSrcDb = pSrcDb; p->iNext = 1; p->isAttached = 0; if( 0==p->pSrc || 0==p->pDest || setDestPgsz(p)==SQLITE_NOMEM || checkReadTransaction(pDestDb, p->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 ** database. The error has already been written into the pDestDb ** handle. All that is left to do here is free the sqlite3_backup ** structure. */ sqlite3_free(p); p = 0; } } if( p ){ p->pSrc->nBackup++; } |
︙ | ︙ |
Changes to test/backup.test.
︙ | ︙ | |||
213 214 215 216 217 218 219 220 221 222 223 224 225 226 | CREATE INDEX ${file_dest}.i1 ON t1(a, b); " $db_dest for {set ii 0} {$ii < $rows_dest} {incr ii} { execsql " INSERT INTO ${file_dest}.t1 VALUES(1, randstr(1000,1000)) " $db_dest } } # Backup the source database. do_test backup-2.$iTest.1 { sqlite3_backup B $db_dest $file_dest db main while {[B step $nPagePerStep]=="SQLITE_OK"} {} B finish | > | 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | CREATE INDEX ${file_dest}.i1 ON t1(a, b); " $db_dest for {set ii 0} {$ii < $rows_dest} {incr ii} { execsql " INSERT INTO ${file_dest}.t1 VALUES(1, randstr(1000,1000)) " $db_dest } execsql COMMIT $db_dest } # Backup the source database. do_test backup-2.$iTest.1 { sqlite3_backup B $db_dest $file_dest db main while {[B step $nPagePerStep]=="SQLITE_OK"} {} B finish |
︙ | ︙ |
Added test/backup5.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | # 2014 November 13 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix backup5 forcedelete test2.db do_execsql_test 1.0 { CREATE TABLE t1(a, b); CREATE TABLE t2(a, b); INSERT INTO t2 VALUES(1, 1); INSERT INTO t2 VALUES(2, 2); INSERT INTO t2 VALUES(3, 3); } do_test 1.1 { forcecopy test.db test.db2 db eval { DROP TABLE t2; INSERT INTO t1 VALUES(zeroblob(1000), zeroblob(1000)); INSERT INTO t1 VALUES(randomblob(1000), randomblob(1000)); } } {} do_test 1.2 { sqlite3 db2 test.db2 set stmt [sqlite3_prepare_v2 db2 "SELECT * FROM t2" -1 dummy] sqlite3_step $stmt } {SQLITE_ROW} do_test 1.3 { list [catch { sqlite3_backup B db2 main db main } msg] $msg } {1 {sqlite3_backup_init() failed}} do_test 1.4 { sqlite3_errmsg db2 } {destination database is in use} do_test 1.5 { sqlite3_reset $stmt sqlite3_backup B db2 main db main B step 200 B finish } {SQLITE_OK} do_test 1.6 { list [sqlite3_step $stmt] [sqlite3_finalize $stmt] } {SQLITE_ERROR SQLITE_ERROR} do_test 1.7 { sqlite3_errmsg db2 } {no such table: t2} finish_test |