From: dan Date: Fri, 18 Nov 2016 18:43:39 +0000 (+0000) Subject: Require that the database handle be in autocommit mode for X-Git-Tag: version-3.16.0~96^2~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=edace5d4f16897f813564259afe5200acd03ce0d;p=thirdparty%2Fsqlite.git Require that the database handle be in autocommit mode for sqlite3_snapshot_get() to succeed. This is because it may open a read transaction on the database file. FossilOrigin-Name: 83b658dad091211ade3594d1e8d00ce525882506 --- diff --git a/manifest b/manifest index 066a12a0ba..955a7b77e9 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index 891d62480c..0a12e01e25 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1f7ee7af7b620262ae663d65889b6a87415d4a34 \ No newline at end of file +83b658dad091211ade3594d1e8d00ce525882506 \ No newline at end of file diff --git a/src/main.c b/src/main.c index 666a72547b..29e166447e 100644 --- a/src/main.c +++ b/src/main.c @@ -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); + } } } } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 7987cfae5e..8f3b40292d 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -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. +** +** +** +** 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()] diff --git a/test/snapshot.test b/test/snapshot.test index 1143c14962..99d3ed47c3 100644 --- a/test/snapshot.test +++ b/test/snapshot.test @@ -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 }