]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Have calls to sqlite3_backup_init() fail if there is already a read or read-write...
authordan <dan@noemail.net>
Thu, 13 Nov 2014 14:18:25 +0000 (14:18 +0000)
committerdan <dan@noemail.net>
Thu, 13 Nov 2014 14:18:25 +0000 (14:18 +0000)
FossilOrigin-Name: 169b5505498c0a7ee2b5dbb2ba13c41dfaa7c62f

manifest
manifest.uuid
src/backup.c
test/backup.test
test/backup5.test [new file with mode: 0644]

index dddb788b2de007af7f237ffe3d2f46790098f5ba..4f0d48c405d1b1f6a212f0319f4f5462c0aca495 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sfurther\stests\sfor\srollback\soperations\sin\sthe\spresence\sof\songoing\sselects.
-D 2014-11-12T17:45:37.113
+C Have\scalls\sto\ssqlite3_backup_init()\sfail\sif\sthere\sis\salready\sa\sread\sor\sread-write\stransaction\sopen\son\sthe\sdestination\sdatabase.
+D 2014-11-13T14:18:25.531
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in a226317fdf3f4c895fb3cfedc355b4d0868ce1fb
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -170,7 +170,7 @@ F src/alter.c ba266a779bc7ce10e52e59e7d3dc79fa342e8fdb
 F src/analyze.c afbcca663c3f3625340b8e30d440cd7a97ded6bc
 F src/attach.c f4e94df2d1826feda65eb0939f7f6f5f923a0ad9
 F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
-F src/backup.c 86b311af1ad35decd1f2f0cee457d344acb83c3b
+F src/backup.c 7ddee9c7d505e07e959a575b18498f17c71e53ea
 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
 F src/btmutex.c 49ca66250c7dfa844a4d4cb8272b87420d27d3a5
 F src/btree.c d5d991b518fa5bebc64037dfeb98a48051d864d7
@@ -353,9 +353,10 @@ F test/autovacuum.test 941892505d2c0f410a0cb5970dfa1c7c4e5f6e74
 F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
 F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
 F test/backcompat.test 19a1f337c68419b020a7481dd272a472c4ad8ef4
-F test/backup.test c9cdd23a495864b9edf75a9fa66f5cb7e10fcf62
+F test/backup.test b79299a536a4c6d919094786595b95be56d02014
 F test/backup2.test 34986ef926ea522911a51dfdb2f8e99b7b75ebcf
 F test/backup4.test 2a2e4a64388090b152de753fd9e123f28f6a3bd4
+F test/backup5.test ee5da6d7fe5082f5b9b0bbfa31d016f52412a2e4
 F test/backup_ioerr.test 4c3c7147cee85b024ecf6e150e090c32fdbb5135
 F test/backup_malloc.test 7162d604ec2b4683c4b3799a48657fb8b5e2d450
 F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
@@ -1220,7 +1221,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P dd03a2802f3f276525f3cef9a93f825dd8606626
-R c0a8c133338658022754212d7071964f
+P eaf3aae014f59c8d37aa20aa31d54cf13f9e86fc
+R cf416376a3614eef6301ba322bd3cc43
 U dan
-Z c8dc7391cf2e61af731936b53ad2fd87
+Z 499ccc085277a0250fd3c5f22e93f6be
index 634cdcad8d6c955a08d69faa65353d92d6a8beaa..73dcaa8447d0f004d196307507034aa5092b22e5 100644 (file)
@@ -1 +1 @@
-eaf3aae014f59c8d37aa20aa31d54cf13f9e86fc
\ No newline at end of file
+169b5505498c0a7ee2b5dbb2ba13c41dfaa7c62f
\ No newline at end of file
index 57f7f447ead88b88960eca2b82f3be3daffce53d..e3f869035eef1e537ac435fdc3835d174e6ad1e8 100644 (file)
@@ -122,6 +122,20 @@ static int setDestPgsz(sqlite3_backup *p){
   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
@@ -181,12 +195,15 @@ sqlite3_backup *sqlite3_backup_init(
     p->iNext = 1;
     p->isAttached = 0;
 
-    if( 0==p->pSrc || 0==p->pDest || setDestPgsz(p)==SQLITE_NOMEM ){
+    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.  The error has already been written into the
-      ** pDestDb handle.  All that is left to do here is free the
-      ** sqlite3_backup structure.
-      */
+      ** 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;
     }
index 444619c68c41b4fe6a1a9b156df11d9075993fa6..3b1e1db9e588a44289ee7653ecd01ebad4745bd6 100644 (file)
@@ -217,6 +217,7 @@ foreach nPagePerStep {1 200} {
           INSERT INTO ${file_dest}.t1 VALUES(1, randstr(1000,1000))
         " $db_dest
       }
+      execsql COMMIT $db_dest
     }
   
     # Backup the source database.
diff --git a/test/backup5.test b/test/backup5.test
new file mode 100644 (file)
index 0000000..c789adf
--- /dev/null
@@ -0,0 +1,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