]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Require that the database handle be in autocommit mode for
authordan <dan@noemail.net>
Fri, 18 Nov 2016 18:43:39 +0000 (18:43 +0000)
committerdan <dan@noemail.net>
Fri, 18 Nov 2016 18:43:39 +0000 (18:43 +0000)
sqlite3_snapshot_get() to succeed. This is because it may open a read
transaction on the database file.

FossilOrigin-Name: 83b658dad091211ade3594d1e8d00ce525882506

manifest
manifest.uuid
src/main.c
src/sqlite.h.in
test/snapshot.test

index 066a12a0baae1ef1006f7d59bcd87534277c5dd2..955a7b77e9bb952644589dca8fc69a270f15d8d2 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\stests\sfor\ssnapshot\sinterfaces.
-D 2016-11-18T18:22:05.618
+C Require\sthat\sthe\sdatabase\shandle\sbe\sin\sautocommit\smode\sfor\nsqlite3_snapshot_get()\sto\ssucceed.\sThis\sis\sbecause\sit\smay\sopen\sa\sread\ntransaction\son\sthe\sdatabase\sfile.
+D 2016-11-18T18:43:39.100
 F Makefile.in 6b572807415d3f0a379cebc9461416d8df4a12c8
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc bb4d970894abbbe0e88d00aac29bd52af8bc95f4
@@ -352,7 +352,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
 F src/insert.c 0d6e59f9eea62db772eabc0f07901ec26fe01968
 F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e
 F src/loadext.c 5d6642d141c07d366e43d359e94ec9de47add41d
-F src/main.c 694ac90557abdaa62151a6090670e107b0f2c2ab
+F src/main.c 602d7179fda1879d688174dcd74c69c8579045b5
 F src/malloc.c 5ee7c2d3dcb1b0a902c9c6d0115deef54736bdfa
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
@@ -389,7 +389,7 @@ F src/resolve.c bb070cf5f23611c44ab7e4788803684e385fc3fb
 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
 F src/select.c 672b1af237ad257149fc5189f3277dcbca036eeb
 F src/shell.c f04e4af75c5517735397d060ed0b4a874104bb41
-F src/sqlite.h.in dfe8c1b4ac66635495ec9a6a7205fcb0f27f4451
+F src/sqlite.h.in cc6e3f38d4c1e4df4f569af49c5deb7c32f1ea10
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae
 F src/sqliteInt.h c471d791b10c0f2164c8b7a87adc338e703c09cc
@@ -1102,7 +1102,7 @@ F test/skipscan2.test d1d1450952b7275f0b0a3a981f0230532743951a
 F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5
 F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2
 F test/skipscan6.test 5866039d03a56f5bd0b3d172a012074a1d90a15b
-F test/snapshot.test bb34cc38828bf2e86a49207995fa7dfacd303832
+F test/snapshot.test 85735bd997a4f6d710140c28fd860519a299649f
 F test/snapshot2.test 30bd95f6fefa8be7f29421e27745cac90b66c74d
 F test/snapshot_fault.test 062ff0438a074978d45e9f9a92e7ad459b74ee73
 F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
@@ -1535,7 +1535,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 16b9bf92741e4c62874cffd7c6a61763c5054c7a
-R aa1ba4f87ce4a1d41c6deb879752303b
+P 1f7ee7af7b620262ae663d65889b6a87415d4a34
+R 94e3e6505e79390151b9cd467eca8236
 U dan
-Z ee11b90501c467e7c32bf0deb14250e6
+Z 084fdf6a46a9563f3a18164c0feb0d49
index 891d62480c0ddb403a4938f8792b822d0e1a8ccf..0a12e01e25f7700106cfaa696f3ea853e7ecfd43 100644 (file)
@@ -1 +1 @@
-1f7ee7af7b620262ae663d65889b6a87415d4a34
\ No newline at end of file
+83b658dad091211ade3594d1e8d00ce525882506
\ No newline at end of file
index 666a72547b6aa64a47803907b66e349f700c8a1f..29e166447ea1d663bb7782c3fdfc6a39b46bb080 100644 (file)
@@ -3981,7 +3981,6 @@ int sqlite3_snapshot_get(
 ){
   int rc = SQLITE_ERROR;
 #ifndef SQLITE_OMIT_WAL
-  int iDb;
 
 #ifdef SQLITE_ENABLE_API_ARMOR
   if( !sqlite3SafetyCheckOk(db) ){
@@ -3990,13 +3989,15 @@ int sqlite3_snapshot_get(
 #endif
   sqlite3_mutex_enter(db->mutex);
 
-  iDb = sqlite3FindDbName(db, zDb);
-  if( iDb==0 || iDb>1 ){
-    Btree *pBt = db->aDb[iDb].pBt;
-    if( 0==sqlite3BtreeIsInTrans(pBt) ){
-      rc = sqlite3BtreeBeginTrans(pBt, 0);
-      if( rc==SQLITE_OK ){
-        rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot);
+  if( db->autoCommit==0 ){
+    int iDb = sqlite3FindDbName(db, zDb);
+    if( iDb==0 || iDb>1 ){
+      Btree *pBt = db->aDb[iDb].pBt;
+      if( 0==sqlite3BtreeIsInTrans(pBt) ){
+        rc = sqlite3BtreeBeginTrans(pBt, 0);
+        if( rc==SQLITE_OK ){
+          rc = sqlite3PagerSnapshotGet(sqlite3BtreePager(pBt), ppSnapshot);
+        }
       }
     }
   }
index 7987cfae5e003f55281aced5229d69c069de3f52..8f3b40292dcc62bc5bbb9cf780b4ca6f61e26506 100644 (file)
@@ -8296,9 +8296,32 @@ typedef struct sqlite3_snapshot {
 ** schema S in database connection D.  ^On success, the
 ** [sqlite3_snapshot_get(D,S,P)] interface writes a pointer to the newly
 ** created [sqlite3_snapshot] object into *P and returns SQLITE_OK.
-** ^If schema S of [database connection] D is not a [WAL mode] database
-** that is in a read transaction, then [sqlite3_snapshot_get(D,S,P)]
-** leaves the *P value unchanged and returns an appropriate [error code].
+** If there is not already a read-transaction open on schema S when
+** this function is called, one is opened automatically. 
+**
+** The following must be true for this function to succeed. If any of
+** the following statements are false when sqlite3_snapshot_get() is
+** called, SQLITE_ERROR is returned. The final value of *P is undefined
+** in this case. 
+**
+** <ul>
+**   <li> The database handle must be in [autocommit mode].
+**
+**   <li> Schema S of [database connection] D must be a [WAL mode] database.
+**
+**   <li> There must not be a write transaction open on schema S of database
+**        connection D.
+**
+**   <li> One or more transactions must have been written to the current wal
+**        file since it was created on disk (by any connection). This means
+**        that a snapshot cannot be taken on a wal mode database with no wal 
+**        file immediately after it is first opened. At least one transaction
+**        must be written to it first.
+** </ul>
+**
+** This function may also return SQLITE_NOMEM.  If it is called with the
+** database handle in autocommit mode but fails for some other reason, 
+** whether or not a read transaction is opened on schema S is undefined.
 **
 ** The [sqlite3_snapshot] object returned from a successful call to
 ** [sqlite3_snapshot_get()] must be freed using [sqlite3_snapshot_free()]
index 1143c149623512bfd650d9ceee8e794c6ca24e61..99d3ed47c366387e3ef46789ea0e214a20fd325f 100644 (file)
@@ -65,6 +65,7 @@ foreach {tn tcl} {
   #
   #  1) snapshot_get() is called on a non-WAL database, or
   #  2) there is an open write transaction on the database.
+  #  3) the database handle is in auto-commit mode
   #
   do_execsql_test $tn.1.0 {
     CREATE TABLE t1(a, b);
@@ -76,7 +77,7 @@ foreach {tn tcl} {
     execsql { BEGIN; SELECT * FROM t1; }
     list [catch { snapshot_get db main } msg] $msg
   } {1 SQLITE_ERROR}
-  do_execsql_test 1.1.2 COMMIT
+  do_execsql_test $tn.1.1.2 COMMIT
 
   do_test $tn.1.2.1 {
     execsql {
@@ -87,7 +88,15 @@ foreach {tn tcl} {
     }
     list [catch { snapshot_get db main } msg] $msg
   } {1 SQLITE_ERROR}
-  do_execsql_test $tn.1.3.2 COMMIT
+  do_execsql_test $tn.1.2.2 COMMIT
+
+  do_test $tn.1.3.1 {
+    list [catch { snapshot_get db main } msg] $msg
+  } {1 SQLITE_ERROR}
+  do_test $tn.1.3.2 {
+    db trans { set snap [snapshot_get db main] }
+    snapshot_free $snap
+  } {}
 
   #-------------------------------------------------------------------------
   # Check that a simple case works. Reuse the database created by the
@@ -153,7 +162,7 @@ foreach {tn tcl} {
 
   do_test $tn.2.3.1 {
     execsql { DELETE FROM t1 WHERE a>6 }
-    set snapshot [snapshot_get db main]
+    db trans { set snapshot [snapshot_get db main] }
     execsql {
       INSERT INTO t1 VALUES('a', 'b');
       INSERT INTO t1 VALUES('c', 'd');
@@ -220,7 +229,7 @@ foreach {tn tcl} {
     }
     list [catch {snapshot_open db main $snapshot } msg] $msg
   } {1 SQLITE_ERROR}
-  do_execsql_test 3.2.4 COMMIT
+  do_execsql_test $tn.3.2.4 COMMIT
 
   do_test $tn.3.3.1 {
     execsql { PRAGMA journal_mode = DELETE }