From 186ebd41cf7c7c8ba7bce7fb8a8136b7a6c153e4 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 23 May 2018 16:50:21 +0000 Subject: [PATCH 1/9] Verify that the sqlite_sequence table exists and is in approximately the correct format prior to using it to process an autoincrement table. Fix for ticket [d8dc2b3a58cd5dc2918a1d4a]. FossilOrigin-Name: e199e859ace4f8381c6380175206e7a276e3f2228fadbbca9341bca8d2fc445d --- manifest | 17 +++-- manifest.uuid | 2 +- src/insert.c | 15 +++++ src/sqlite.h.in | 1 + test/autoinc.test | 155 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 180 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index a4a4960c57..aaa97903f9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\ssupport\sfor\sauxiliary\scolumns\sto\sthe\srtree\sextension. -D 2018-05-18T17:58:33.081 +C Verify\sthat\sthe\ssqlite_sequence\stable\sexists\sand\sis\sin\sapproximately\sthe\ncorrect\sformat\sprior\sto\susing\sit\sto\sprocess\san\sautoincrement\stable.\nFix\sfor\sticket\s[d8dc2b3a58cd5dc2918a1d4a]. +D 2018-05-23T16:50:21.007 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -455,7 +455,7 @@ F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4 F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c 33a2c72b6182e8ddf697d604cc087c77ff5fc512a32b8b624641d41b390e249e +F src/insert.c 25f2e3cb93821944dec28921c4cfb7729b3ac6e75d860fd7cd934265404a35b0 F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e F src/loadext.c 6aae5739198d96c51ae6eb97c4a5b1744c22ed7a5a565a5399a717780d48a36b F src/main.c b56b2d62d5d11e3f5100b25fca34c13c62a0fe73941f6873454a7fa8a454170d @@ -496,7 +496,7 @@ F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c a35d462ee7a3c0856ad7a9d9c8921fbf3d91d911a8f39ad9d61302eb43b24a71 F src/shell.c.in 51c100206f4b7f86cd9affd80b764825e0edc36ca0190c442e4ca7994611bfe2 -F src/sqlite.h.in 34be2d0d18bf4726538793bdc9854cd87f689fda4b3789515134cdbd68188cf4 +F src/sqlite.h.in 7b3e0f3a5f86eb8c43cf4924171de993210a207f2c51ca59b03f86a0d33c59d5 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7 F src/sqliteInt.h 5abdade4744cf3bd567afb65bb144bb3c61f6132f86813b995a5ca79c7b584e8 @@ -626,7 +626,7 @@ F test/auth.test 3d6cd8f3978ba55b1202574e6ecd79c6e00914ca44b9bfd6c1fe6fb873fcac8 F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1 F test/auth3.test db21405b95257c24d29273b6b31d0efc59e1d337e3d5804ba2d1fd4897b1ae49 F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec -F test/autoinc.test 83aad64411583aac9ff0b629159ab4662029ab4e3f47090fce4efd132b304484 +F test/autoinc.test c6df81f1de9a5499f912c58e5389d0bcb8d42459df832b65aee24338ad422a42 F test/autoindex1.test a09958fa756129af10b6582bcbf3cbdf11e305e027b393f393caef801159dee0 F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df F test/autoindex3.test 2dd997d6590438b53e4f715f9278aa91c9299cf3f81246a0915269c35beb790e @@ -1729,8 +1729,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 e3b2e0a078b82ac6cd3c3312e8ac0983c1375e1052f1e324476d2f8d1b227c30 a350040a3bb962823f92908fb31cade52baf13eab90ef608ca3a8349e4c28c9d -R c67fcd3e8c429daa0c0bf5aeb356dbf0 -T +closed a350040a3bb962823f92908fb31cade52baf13eab90ef608ca3a8349e4c28c9d +P c6071ac99cfa4b6272ac4d739fc61a85acb544f6c1c2ae67b31e92aadcc995bd +R 58a75d6f197e6b4ac0aaca4c0364c2b3 U drh -Z 6ceb3a28c710c648a7e5cb8343e1c6ba +Z c05e2c3d89e368267a2a8ee44da7d50d diff --git a/manifest.uuid b/manifest.uuid index 9a25a0b869..1d775eab81 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c6071ac99cfa4b6272ac4d739fc61a85acb544f6c1c2ae67b31e92aadcc995bd \ No newline at end of file +e199e859ace4f8381c6380175206e7a276e3f2228fadbbca9341bca8d2fc445d \ No newline at end of file diff --git a/src/insert.c b/src/insert.c index d2ac028d91..76293c6018 100644 --- a/src/insert.c +++ b/src/insert.c @@ -226,11 +226,26 @@ static int autoIncBegin( Table *pTab /* The table we are writing to */ ){ int memId = 0; /* Register holding maximum rowid */ + assert( pParse->db->aDb[iDb].pSchema!=0 ); if( (pTab->tabFlags & TF_Autoincrement)!=0 && (pParse->db->mDbFlags & DBFLAG_Vacuum)==0 ){ Parse *pToplevel = sqlite3ParseToplevel(pParse); AutoincInfo *pInfo; + Table *pSeqTab = pParse->db->aDb[iDb].pSchema->pSeqTab; + + /* Verify that the sqlite_sequence table exists and is an ordinary + ** rowid table with exactly two columns. + ** Ticket d8dc2b3a58cd5dc2918a1d4acb 2018-05-23 */ + if( pSeqTab==0 + || !HasRowid(pSeqTab) + || IsVirtual(pSeqTab) + || pSeqTab->nCol!=2 + ){ + pParse->nErr++; + pParse->rc = SQLITE_CORRUPT_SEQUENCE; + return 0; + } pInfo = pToplevel->pAinc; while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 0cd06d09f0..fe0f14e292 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -511,6 +511,7 @@ int sqlite3_exec( #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) +#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) #define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8)) #define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8)) diff --git a/test/autoinc.test b/test/autoinc.test index 196743576b..0ce09b223c 100644 --- a/test/autoinc.test +++ b/test/autoinc.test @@ -684,4 +684,159 @@ do_execsql_test autoinc-11.1 { SELECT seq FROM sqlite_sequence WHERE name='t11'; } {5} +# 2018-05-23 ticket d8dc2b3a58cd5dc2918a1d4acbba4676a23ada4c +# Does not crash if the sqlite_sequence table schema is missing +# or corrupt. +# +do_test autoinc-12.1 { + db close + forcedelete test.db + sqlite3 db test.db + db eval { + CREATE TABLE fake_sequence(name TEXT PRIMARY KEY,seq) WITHOUT ROWID; + PRAGMA writable_schema=on; + UPDATE sqlite_master SET + sql=replace(sql,'fake_','sqlite_'), + name='sqlite_sequence', + tbl_name='sqlite_sequence' + WHERE name='fake_sequence'; + } + db close + sqlite3 db test.db + set res [catch {db eval { + CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); + INSERT INTO t1(b) VALUES('one'); + }} msg] + lappend res $msg +} {1 {database disk image is malformed}} +do_test autoinc-12.2 { + db close + forcedelete test.db + sqlite3 db test.db + db eval { + CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); + INSERT INTO t1(b) VALUES('one'); + PRAGMA writable_schema=on; + UPDATE sqlite_master SET + sql=replace(sql,'sqlite_','x_'), + name='x_sequence', + tbl_name='x_sequence' + WHERE name='sqlite_sequence'; + } + db close + sqlite3 db test.db + set res [catch {db eval { + INSERT INTO t1(b) VALUES('two'); + }} msg] + lappend res $msg +} {1 {database disk image is malformed}} +do_test autoinc-12.3 { + db close + forcedelete test.db + sqlite3 db test.db + db eval { + CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); + INSERT INTO t1(b) VALUES('one'); + PRAGMA writable_schema=on; + UPDATE sqlite_master SET + sql='CREATE VIRTUAL TABLE sqlite_sequence USING sqlite_dbpage' + WHERE name='sqlite_sequence'; + } + db close + sqlite3 db test.db + set res [catch {db eval { + INSERT INTO t1(b) VALUES('two'); + }} msg] + lappend res $msg +} {1 {database disk image is malformed}} +do_test autoinc-12.4 { + db close + forcedelete test.db + sqlite3 db test.db + db eval { + CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); + INSERT INTO t1(b) VALUES('one'); + CREATE TABLE fake(name TEXT PRIMARY KEY,seq) WITHOUT ROWID; + } + set root1 [db one {SELECT rootpage FROM sqlite_master + WHERE name='sqlite_sequence'}] + set root2 [db one {SELECT rootpage FROM sqlite_master + WHERE name='fake'}] + db eval { + PRAGMA writable_schema=on; + UPDATE sqlite_master SET rootpage=$root2 + WHERE name='sqlite_sequence'; + UPDATE sqlite_master SET rootpage=$root1 + WHERE name='fake'; + } + db close + sqlite3 db test.db + set res [catch {db eval { + INSERT INTO t1(b) VALUES('two'); + }} msg] + lappend res $msg +} {1 {database disk image is malformed}} +breakpoint +do_test autoinc-12.5 { + db close + forcedelete test.db + sqlite3 db test.db + db eval { + CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); + INSERT INTO t1(b) VALUES('one'); + PRAGMA writable_schema=on; + UPDATE sqlite_master SET + sql='CREATE TABLE sqlite_sequence(x)' + WHERE name='sqlite_sequence'; + } + db close + sqlite3 db test.db + set res [catch {db eval { + INSERT INTO t1(b) VALUES('two'); + }} msg] + lappend res $msg +} {1 {database disk image is malformed}} +do_test autoinc-12.6 { + db close + forcedelete test.db + sqlite3 db test.db + db eval { + CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); + INSERT INTO t1(b) VALUES('one'); + PRAGMA writable_schema=on; + UPDATE sqlite_master SET + sql='CREATE TABLE sqlite_sequence(x,y INTEGER PRIMARY KEY)' + WHERE name='sqlite_sequence'; + } + db close + sqlite3 db test.db + set res [catch {db eval { + INSERT INTO t1(b) VALUES('two'),('three'),('four'); + INSERT INTO t1(b) VALUES('five'); + PRAGMA integrity_check; + }} msg] + lappend res $msg +} {0 ok} +do_test autoinc-12.7 { + db close + forcedelete test.db + sqlite3 db test.db + db eval { + CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT); + INSERT INTO t1(b) VALUES('one'); + PRAGMA writable_schema=on; + UPDATE sqlite_master SET + sql='CREATE TABLE sqlite_sequence(y INTEGER PRIMARY KEY,x)' + WHERE name='sqlite_sequence'; + } + db close + sqlite3 db test.db + set res [catch {db eval { + INSERT INTO t1(b) VALUES('two'),('three'),('four'); + INSERT INTO t1(b) VALUES('five'); + PRAGMA integrity_check; + }} msg] + lappend res $msg +} {0 ok} + finish_test From 4c57e326efb4d4b5ad20dcb7058abd8ebf48aa42 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 23 May 2018 17:53:07 +0000 Subject: [PATCH 2/9] Remove a branch that is no longer used due to the fix to the sqlite_sequence schema problem, ticket [d8dc2b3a58cd5dc2918a1d4acbba4676a23ada4c] FossilOrigin-Name: 066742692a9e8735b814c6a145545f97a7fb10b29cead78e68e25324e79aabaa --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbe.c | 5 +---- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index aaa97903f9..f8f5a5b12b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Verify\sthat\sthe\ssqlite_sequence\stable\sexists\sand\sis\sin\sapproximately\sthe\ncorrect\sformat\sprior\sto\susing\sit\sto\sprocess\san\sautoincrement\stable.\nFix\sfor\sticket\s[d8dc2b3a58cd5dc2918a1d4a]. -D 2018-05-23T16:50:21.007 +C Remove\sa\sbranch\sthat\sis\sno\slonger\sused\sdue\sto\sthe\sfix\sto\sthe\nsqlite_sequence\sschema\sproblem,\sticket\n[d8dc2b3a58cd5dc2918a1d4acbba4676a23ada4c] +D 2018-05-23T17:53:07.408 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -564,7 +564,7 @@ F src/upsert.c ae4a4823b45c4daf87e8aea8c0f582a8844763271f5ed54ee5956c4c612734f4 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 F src/vacuum.c 37730af7540033135909ecaee3667dddec043293428d8718546d0d64ba4a5025 -F src/vdbe.c 066a4e1de2ed83e253adfd2e97a684cf562eaa41d31ee7f3d3e4c8aea4485a55 +F src/vdbe.c b67ec60fe6cb42040a000c30e135ddfb4b1536979ed85a329442bd1c8df77962 F src/vdbe.h d970d9738efdd09cb2df73e3a40856e7df13e88a3486789c49fcdd322c9eb8a2 F src/vdbeInt.h 95f7adfdc5c8f1353321f55a6c5ec00a90877e3b85af5159e393afb41ff54110 F src/vdbeapi.c 29d2baf9c1233131ec467d7bed1b7c8a03c27579048d768c4b04acf427838858 @@ -1729,7 +1729,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 c6071ac99cfa4b6272ac4d739fc61a85acb544f6c1c2ae67b31e92aadcc995bd -R 58a75d6f197e6b4ac0aaca4c0364c2b3 +P e199e859ace4f8381c6380175206e7a276e3f2228fadbbca9341bca8d2fc445d +R fcb7bb3e89a5dc882c6d8d40fd26a899 U drh -Z c05e2c3d89e368267a2a8ee44da7d50d +Z 26f7d6a5cd51317fc5937ffe2a0456c5 diff --git a/manifest.uuid b/manifest.uuid index 1d775eab81..f288d229ab 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e199e859ace4f8381c6380175206e7a276e3f2228fadbbca9341bca8d2fc445d \ No newline at end of file +066742692a9e8735b814c6a145545f97a7fb10b29cead78e68e25324e79aabaa \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 70537ce114..006fae3d69 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -4287,11 +4287,8 @@ case OP_NewRowid: { /* out2 */ pOut = out2Prerelease(p, pOp); assert( pOp->p1>=0 && pOp->p1nCursor ); pC = p->apCsr[pOp->p1]; - if( !pC->isTable ){ - rc = SQLITE_CORRUPT_BKPT; - goto abort_due_to_error; - } assert( pC!=0 ); + assert( pC->isTable ); assert( pC->eCurType==CURTYPE_BTREE ); assert( pC->uc.pCursor!=0 ); { From 7458a9f3f75212f798b8a48515497ad7613623b2 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 24 May 2018 13:59:45 +0000 Subject: [PATCH 3/9] Updates to the sqlite3_vtab_nochange() documentation. No changes to code. FossilOrigin-Name: 5bd99abc10b8153aadff5f815ae15fbe375f34f043c65def4be03014d2efdb50 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/sqlite.h.in | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index f8f5a5b12b..94a83df1d8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sa\sbranch\sthat\sis\sno\slonger\sused\sdue\sto\sthe\sfix\sto\sthe\nsqlite_sequence\sschema\sproblem,\sticket\n[d8dc2b3a58cd5dc2918a1d4acbba4676a23ada4c] -D 2018-05-23T17:53:07.408 +C Updates\sto\sthe\ssqlite3_vtab_nochange()\sdocumentation.\s\sNo\schanges\sto\scode. +D 2018-05-24T13:59:45.761 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -496,7 +496,7 @@ F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c a35d462ee7a3c0856ad7a9d9c8921fbf3d91d911a8f39ad9d61302eb43b24a71 F src/shell.c.in 51c100206f4b7f86cd9affd80b764825e0edc36ca0190c442e4ca7994611bfe2 -F src/sqlite.h.in 7b3e0f3a5f86eb8c43cf4924171de993210a207f2c51ca59b03f86a0d33c59d5 +F src/sqlite.h.in ac6aec2abe10585733c1fea06622df5d73f7725c36c6cf054e89affeaccfa42b F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7 F src/sqliteInt.h 5abdade4744cf3bd567afb65bb144bb3c61f6132f86813b995a5ca79c7b584e8 @@ -1729,7 +1729,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 e199e859ace4f8381c6380175206e7a276e3f2228fadbbca9341bca8d2fc445d -R fcb7bb3e89a5dc882c6d8d40fd26a899 +P 066742692a9e8735b814c6a145545f97a7fb10b29cead78e68e25324e79aabaa +R 2b6c7c21a55e5d907e8d89643c483eb6 U drh -Z 26f7d6a5cd51317fc5937ffe2a0456c5 +Z 20be9535b952178763a98e0fa1717892 diff --git a/manifest.uuid b/manifest.uuid index f288d229ab..6b15cbaa98 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -066742692a9e8735b814c6a145545f97a7fb10b29cead78e68e25324e79aabaa \ No newline at end of file +5bd99abc10b8153aadff5f815ae15fbe375f34f043c65def4be03014d2efdb50 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index fe0f14e292..7296597ea3 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -8534,11 +8534,11 @@ int sqlite3_vtab_on_conflict(sqlite3 *); ** method of a [virtual table], then it returns true if and only if the ** column is being fetched as part of an UPDATE operation during which the ** column value will not change. Applications might use this to substitute -** a lighter-weight value to return that the corresponding [xUpdate] method -** understands as a "no-change" value. +** a return value that is less expensive to compute and that the corresponding +** [xUpdate] method understands as a "no-change" value. ** ** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that -** the column is not changed by the UPDATE statement, they the xColumn +** the column is not changed by the UPDATE statement, then the xColumn ** method can optionally return without setting a result, without calling ** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces]. ** In that case, [sqlite3_value_nochange(X)] will return true for the From cf8784cd8f4a5e3a55194a88c07525f7f13f9e9d Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 24 May 2018 16:18:35 +0000 Subject: [PATCH 4/9] Addition cases for rtree preformance testing in speedtest1.c. Add the --nodiff option to the speed-check.sh script. FossilOrigin-Name: 95f2d62cf3cf8dbe0f12b652b47fe1f8e0f52bc269e269955fafdf802afc47c1 --- manifest | 14 +++++------ manifest.uuid | 2 +- test/speedtest1.c | 59 ++++++++++++++++++++++++++++++++++++++++----- tool/speed-check.sh | 6 ++++- 4 files changed, 66 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index 94a83df1d8..8f577211b4 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Updates\sto\sthe\ssqlite3_vtab_nochange()\sdocumentation.\s\sNo\schanges\sto\scode. -D 2018-05-24T13:59:45.761 +C Addition\scases\sfor\srtree\spreformance\stesting\sin\sspeedtest1.c.\s\sAdd\sthe\n--nodiff\soption\sto\sthe\sspeed-check.sh\sscript. +D 2018-05-24T16:18:35.844 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -1278,7 +1278,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715 F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c -F test/speedtest1.c 20cc4028b0e88392b5a635c2ea5d5e777d569bf7258aead37f8be7a886c38344 +F test/speedtest1.c cc7e6b4a7c9f3e3d1a497ae3f75236a832a2ce0f6a9b017f95d996c821605bfb F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3 F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33 @@ -1687,7 +1687,7 @@ F tool/showstat4.c 0682ebea7abf4d3657f53c4a243f2e7eab48eab344ed36a94bb75dcd19a5c F tool/showwal.c ad9d768f96ca6199ad3a8c9562d679680bd032dd01204ea3e5ea6fb931d81847 F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe F tool/spaceanal.tcl 4bfd19aad7eb3ce0372ef0255f58035e0bba4ff5e9acfd763a10c6fb365c8dec -F tool/speed-check.sh 4ff9b095cf1a7643f0264e7fb7d23f0b12b7cce587a9de315877c378e90eeaf4 +F tool/speed-check.sh 27c7fe178d5b2f7c90a04a127907acda0bfe637fa85b13c43e03e5ed39b008b6 F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355 F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff @@ -1729,7 +1729,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 066742692a9e8735b814c6a145545f97a7fb10b29cead78e68e25324e79aabaa -R 2b6c7c21a55e5d907e8d89643c483eb6 +P 5bd99abc10b8153aadff5f815ae15fbe375f34f043c65def4be03014d2efdb50 +R 591bbb7140fdca180e7f617066a14131 U drh -Z 20be9535b952178763a98e0fa1717892 +Z c305b65d30ddf3884d93283494a49287 diff --git a/manifest.uuid b/manifest.uuid index 6b15cbaa98..5abf26cba4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5bd99abc10b8153aadff5f815ae15fbe375f34f043c65def4be03014d2efdb50 \ No newline at end of file +95f2d62cf3cf8dbe0f12b652b47fe1f8e0f52bc269e269955fafdf802afc47c1 \ No newline at end of file diff --git a/test/speedtest1.c b/test/speedtest1.c index 2fcbbebd7f..cf03c5354b 100644 --- a/test/speedtest1.c +++ b/test/speedtest1.c @@ -1247,10 +1247,11 @@ void testset_rtree(int p1, int p2){ unsigned mxCoord; unsigned x0, x1, y0, y1, z0, z1; unsigned iStep; + unsigned mxRowid; int *aCheck = sqlite3_malloc( sizeof(int)*g.szTest*500 ); mxCoord = 15000; - n = g.szTest*500; + mxRowid = n = g.szTest*500; speedtest1_begin_test(100, "%d INSERTs into an r-tree", n); speedtest1_exec("BEGIN"); speedtest1_exec("CREATE VIRTUAL TABLE rt1 USING rtree(id,x0,x1,y0,y1,z0,z1)"); @@ -1277,7 +1278,7 @@ void testset_rtree(int p1, int p2){ speedtest1_exec("INSERT INTO t1 SELECT * FROM rt1"); speedtest1_end_test(); - n = g.szTest*100; + n = g.szTest*200; speedtest1_begin_test(110, "%d one-dimensional intersect slice queries", n); speedtest1_prepare("SELECT count(*) FROM rt1 WHERE x0>=?1 AND x1<=?2"); iStep = mxCoord/n; @@ -1290,7 +1291,7 @@ void testset_rtree(int p1, int p2){ speedtest1_end_test(); if( g.bVerify ){ - n = g.szTest*100; + n = g.szTest*200; speedtest1_begin_test(111, "Verify result from 1-D intersect slice queries"); speedtest1_prepare("SELECT count(*) FROM t1 WHERE x0>=?1 AND x1<=?2"); iStep = mxCoord/n; @@ -1306,7 +1307,7 @@ void testset_rtree(int p1, int p2){ speedtest1_end_test(); } - n = g.szTest*100; + n = g.szTest*200; speedtest1_begin_test(120, "%d one-dimensional overlap slice queries", n); speedtest1_prepare("SELECT count(*) FROM rt1 WHERE y1>=?1 AND y0<=?2"); iStep = mxCoord/n; @@ -1319,7 +1320,7 @@ void testset_rtree(int p1, int p2){ speedtest1_end_test(); if( g.bVerify ){ - n = g.szTest*100; + n = g.szTest*200; speedtest1_begin_test(121, "Verify result from 1-D overlap slice queries"); speedtest1_prepare("SELECT count(*) FROM t1 WHERE y1>=?1 AND y0<=?2"); iStep = mxCoord/n; @@ -1336,7 +1337,7 @@ void testset_rtree(int p1, int p2){ } - n = g.szTest*100; + n = g.szTest*200; speedtest1_begin_test(125, "%d custom geometry callback queries", n); sqlite3_rtree_geometry_callback(g.db, "xslice", xsliceGeometryCallback, 0); speedtest1_prepare("SELECT count(*) FROM rt1 WHERE id MATCH xslice(?1,?2)"); @@ -1373,6 +1374,52 @@ void testset_rtree(int p1, int p2){ speedtest1_run(); } speedtest1_end_test(); + + n = g.szTest*50; + speedtest1_begin_test(150, "%d UPDATEs using rowid", n); + speedtest1_prepare("UPDATE rt1 SET x0=x0+100, x1=x1+100 WHERE id=?1"); + for(i=1; i<=n; i++){ + sqlite3_bind_int(g.pStmt, 1, (i*251)%mxRowid + 1); + speedtest1_run(); + } + speedtest1_end_test(); + + n = g.szTest*5; + speedtest1_begin_test(155, "%d UPDATEs using one-dimensional overlap", n); + speedtest1_prepare("UPDATE rt1 SET x0=x0-100, x1=x1-100" + " WHERE y1>=?1 AND y0<=?1+5"); + iStep = mxCoord/n; + for(i=0; i=?1 AND y0<=?1+5"); + iStep = mxCoord/n; + for(i=0; ivdbeprofile-$NAME.txt open vdbeprofile-$NAME.txt fi -if test "$NAME" != "$BASELINE" -a $doVdbeProfile -ne 1; then +if test "$NAME" != "$BASELINE" -a $doVdbeProfile -ne 1 -a $doDiff -ne 0; then fossil test-diff --tk -c 20 cout-$BASELINE.txt cout-$NAME.txt fi From bbd574bc375bb4414526ec9e26849dd58f212e80 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 24 May 2018 17:25:35 +0000 Subject: [PATCH 5/9] Fix a typo in a comment used to generate VDBE opcode documentation. No code changes. FossilOrigin-Name: 36cdfbf2ce1811691c790fde3eaeed0238c03b4dc97dc3a20d1e0397520145d1 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbe.c | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/manifest b/manifest index 8f577211b4..1071a5813f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Addition\scases\sfor\srtree\spreformance\stesting\sin\sspeedtest1.c.\s\sAdd\sthe\n--nodiff\soption\sto\sthe\sspeed-check.sh\sscript. -D 2018-05-24T16:18:35.844 +C Fix\sa\stypo\sin\sa\scomment\sused\sto\sgenerate\sVDBE\sopcode\sdocumentation.\s\sNo\ncode\schanges. +D 2018-05-24T17:25:35.177 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -564,7 +564,7 @@ F src/upsert.c ae4a4823b45c4daf87e8aea8c0f582a8844763271f5ed54ee5956c4c612734f4 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 F src/vacuum.c 37730af7540033135909ecaee3667dddec043293428d8718546d0d64ba4a5025 -F src/vdbe.c b67ec60fe6cb42040a000c30e135ddfb4b1536979ed85a329442bd1c8df77962 +F src/vdbe.c 565f7ccc4153627ef316bcfc2da86cb0766fac4b7dcd07c45a175c347d480f0a F src/vdbe.h d970d9738efdd09cb2df73e3a40856e7df13e88a3486789c49fcdd322c9eb8a2 F src/vdbeInt.h 95f7adfdc5c8f1353321f55a6c5ec00a90877e3b85af5159e393afb41ff54110 F src/vdbeapi.c 29d2baf9c1233131ec467d7bed1b7c8a03c27579048d768c4b04acf427838858 @@ -1729,7 +1729,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 5bd99abc10b8153aadff5f815ae15fbe375f34f043c65def4be03014d2efdb50 -R 591bbb7140fdca180e7f617066a14131 +P 95f2d62cf3cf8dbe0f12b652b47fe1f8e0f52bc269e269955fafdf802afc47c1 +R feb4f88886f01280dec4144b6c4a9227 U drh -Z c305b65d30ddf3884d93283494a49287 +Z ad2bc326f1608b0e430647ea2c2e00b0 diff --git a/manifest.uuid b/manifest.uuid index 5abf26cba4..35931eb056 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -95f2d62cf3cf8dbe0f12b652b47fe1f8e0f52bc269e269955fafdf802afc47c1 \ No newline at end of file +36cdfbf2ce1811691c790fde3eaeed0238c03b4dc97dc3a20d1e0397520145d1 \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 006fae3d69..81b203dc44 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -6742,7 +6742,7 @@ case OP_VFilter: { /* jump */ ** If the VColumn opcode is being used to fetch the value of ** an unchanging column during an UPDATE operation, then the P5 ** value is 1. Otherwise, P5 is 0. The P5 value is returned -** by sqlite3_vtab_nochange() routine can can be used +** by sqlite3_vtab_nochange() routine and can be used ** by virtual table implementations to return special "no-change" ** marks which can be more efficient, depending on the virtual table. */ From b9cd2c4536880e8588f8f5c90b6e375b98c8697b Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 24 May 2018 17:38:00 +0000 Subject: [PATCH 6/9] In the OOM testing logic, add the sqlite3FirstFault() routine as a place to set a breakpoint the first time any simulated OOM fault occurs for a single test case. FossilOrigin-Name: b4d80bd287ca7f3a6d182ba2435273266035b94fdf6a44047a64a4eff931c571 --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/test_malloc.c | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/manifest b/manifest index 1071a5813f..02f369cbf6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\stypo\sin\sa\scomment\sused\sto\sgenerate\sVDBE\sopcode\sdocumentation.\s\sNo\ncode\schanges. -D 2018-05-24T17:25:35.177 +C In\sthe\sOOM\stesting\slogic,\sadd\sthe\ssqlite3FirstFault()\sroutine\sas\sa\splace\sto\nset\sa\sbreakpoint\sthe\sfirst\stime\sany\ssimulated\sOOM\sfault\soccurs\sfor\sa\ssingle\ntest\scase. +D 2018-05-24T17:38:00.681 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -531,7 +531,7 @@ F src/test_intarray.c 988fc61cb0ff539f4172c0d95f15287c92516f64 F src/test_intarray.h f3b7672f5d1056eac563c0d6ea8480a660b1475c F src/test_journal.c 619f2aa10e0d7a5f87c0f06825bc61dfce1c6b9c7f3ad990fb13de6c3b8874a3 F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd -F src/test_malloc.c 5201422e2403e66a7a9c2b7d8df806acd8d2a0429822adb7e932f324e7b5b3c6 +F src/test_malloc.c dec0aa821b230773aeb3dd11d652c1193f7cedb18a20b25659bc672288115242 F src/test_md5.c 7268e1e8c399d4a5e181b64ac20e1e6f3bc4dd9fc87abac02db145a3d951fa8c F src/test_multiplex.c e054459f7633f3ff8ce1245da724f9a8be189e4e F src/test_multiplex.h 5436d03f2d0501d04f3ed50a75819e190495b635 @@ -1729,7 +1729,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 95f2d62cf3cf8dbe0f12b652b47fe1f8e0f52bc269e269955fafdf802afc47c1 -R feb4f88886f01280dec4144b6c4a9227 +P 36cdfbf2ce1811691c790fde3eaeed0238c03b4dc97dc3a20d1e0397520145d1 +R 085dc0bd34d45e9f6435a293683fda7b U drh -Z ad2bc326f1608b0e430647ea2c2e00b0 +Z 2f994e2ed2922ec0ed95eb384d135eee diff --git a/manifest.uuid b/manifest.uuid index 35931eb056..7278a0f019 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -36cdfbf2ce1811691c790fde3eaeed0238c03b4dc97dc3a20d1e0397520145d1 \ No newline at end of file +b4d80bd287ca7f3a6d182ba2435273266035b94fdf6a44047a64a4eff931c571 \ No newline at end of file diff --git a/src/test_malloc.c b/src/test_malloc.c index 33bc3807ba..32a03e7191 100644 --- a/src/test_malloc.c +++ b/src/test_malloc.c @@ -32,6 +32,8 @@ static struct MemFault { int nRepeat; /* Number of times to repeat the failure */ int nBenign; /* Number of benign failures seen since last config */ int nFail; /* Number of failures seen since last config */ + int nOkBefore; /* Successful allocations prior to the first fault */ + int nOkAfter; /* Successful allocations after a fault */ u8 enable; /* True if enabled */ int isInstalled; /* True if the fault simulation layer is installed */ int isBenignMode; /* True if malloc failures are considered benign */ @@ -47,18 +49,32 @@ static void sqlite3Fault(void){ cnt++; } +/* +** This routine exists as a place to set a breakpoint that will +** fire the first time any malloc() fails on a single test case. +** The sqlite3Fault() routine above runs on every malloc() failure. +** This routine only runs on the first such failure. +*/ +static void sqlite3FirstFault(void){ + static int cnt2 = 0; + cnt2++; +} + /* ** Check to see if a fault should be simulated. Return true to simulate ** the fault. Return false if the fault should not be simulated. */ static int faultsimStep(void){ if( likely(!memfault.enable) ){ + memfault.nOkAfter++; return 0; } if( memfault.iCountdown>0 ){ memfault.iCountdown--; + memfault.nOkBefore++; return 0; } + if( memfault.nFail==0 ) sqlite3FirstFault(); sqlite3Fault(); memfault.nFail++; if( memfault.isBenignMode>0 ){ @@ -133,6 +149,8 @@ static void faultsimConfig(int nDelay, int nRepeat){ memfault.nRepeat = nRepeat; memfault.nBenign = 0; memfault.nFail = 0; + memfault.nOkBefore = 0; + memfault.nOkAfter = 0; memfault.enable = nDelay>=0; /* Sometimes, when running multi-threaded tests, the isBenignMode From c8c9cdd9ddef09a4e42ba7e5590c4dbf9e048dc9 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 24 May 2018 22:31:01 +0000 Subject: [PATCH 7/9] Do not allow RTree writes when a read cursor is active on the same virtual table, as the writes might rebalance and disrupt the read cursors. Return the new SQLITE_LOCKED_VTAB error code if this happens. FossilOrigin-Name: d4ce66610851c825cb712f985216b63e015c753fdd5521f929c67ad18bfd7664 --- ext/rtree/rtree.c | 29 +++++++++++++++++++++++------ ext/rtree/rtree8.test | 15 ++++++++++++--- manifest | 16 ++++++++-------- manifest.uuid | 2 +- src/sqlite.h.in | 1 + 5 files changed, 45 insertions(+), 18 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index c4c536f8ce..54be2f6ced 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -133,6 +133,7 @@ struct Rtree { u32 nBusy; /* Current number of users of this structure */ i64 nRowEst; /* Estimated number of rows in this table */ u32 nCursor; /* Number of open cursors */ + u32 nNodeRef; /* Number RtreeNodes with positive nRef */ char *zReadAuxSql; /* SQL for statement to read aux data */ /* List of nodes removed during a CondenseTree operation. List is @@ -534,6 +535,7 @@ static int writeInt64(u8 *p, i64 i){ */ static void nodeReference(RtreeNode *p){ if( p ){ + assert( p->nRef>0 ); p->nRef++; } } @@ -601,6 +603,7 @@ static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){ memset(pNode, 0, sizeof(RtreeNode) + pRtree->iNodeSize); pNode->zData = (u8 *)&pNode[1]; pNode->nRef = 1; + pRtree->nNodeRef++; pNode->pParent = pParent; pNode->isDirty = 1; nodeReference(pParent); @@ -634,10 +637,10 @@ static int nodeAcquire( /* Check if the requested node is already in the hash table. If so, ** increase its reference count and return it. */ - if( (pNode = nodeHashLookup(pRtree, iNode)) ){ + if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){ assert( !pParent || !pNode->pParent || pNode->pParent==pParent ); if( pParent && !pNode->pParent ){ - nodeReference(pParent); + pParent->nRef++; pNode->pParent = pParent; } pNode->nRef++; @@ -676,6 +679,7 @@ static int nodeAcquire( pNode->pParent = pParent; pNode->zData = (u8 *)&pNode[1]; pNode->nRef = 1; + pRtree->nNodeRef++; pNode->iNode = iNode; pNode->isDirty = 0; pNode->pNext = 0; @@ -716,7 +720,10 @@ static int nodeAcquire( } *ppNode = pNode; }else{ - sqlite3_free(pNode); + if( pNode ){ + pRtree->nNodeRef--; + sqlite3_free(pNode); + } *ppNode = 0; } @@ -813,8 +820,10 @@ static int nodeRelease(Rtree *pRtree, RtreeNode *pNode){ int rc = SQLITE_OK; if( pNode ){ assert( pNode->nRef>0 ); + assert( pRtree->nNodeRef>0 ); pNode->nRef--; if( pNode->nRef==0 ){ + pRtree->nNodeRef--; if( pNode->iNode==1 ){ pRtree->iDepth = -1; } @@ -931,8 +940,9 @@ static void rtreeRelease(Rtree *pRtree){ pRtree->nBusy--; if( pRtree->nBusy==0 ){ pRtree->inWrTrans = 0; - pRtree->nCursor = 0; + assert( pRtree->nCursor==0 ); nodeBlobReset(pRtree); + assert( pRtree->nNodeRef==0 ); sqlite3_finalize(pRtree->pWriteNode); sqlite3_finalize(pRtree->pDeleteNode); sqlite3_finalize(pRtree->pReadRowid); @@ -1403,7 +1413,7 @@ static RtreeSearchPoint *rtreeSearchPointNew( if( iiaNode[ii]==0 ); pCur->aNode[ii] = pCur->aNode[0]; - }else{ + }else{ nodeRelease(RTREE_OF_CURSOR(pCur), pCur->aNode[0]); } pCur->aNode[0] = 0; @@ -2473,7 +2483,7 @@ static int SplitNode( }else{ pLeft = pNode; pRight = nodeNew(pRtree, pLeft->pParent); - nodeReference(pLeft); + pLeft->nRef++; } if( !pLeft || !pRight ){ @@ -2963,6 +2973,7 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){ rc = reinsertNodeContent(pRtree, pLeaf); } pRtree->pDeleted = pLeaf->pNext; + pRtree->nNodeRef--; sqlite3_free(pLeaf); } @@ -3067,6 +3078,12 @@ static int rtreeUpdate( RtreeCell cell; /* New cell to insert if nData>1 */ int bHaveRowid = 0; /* Set to 1 after new rowid is determined */ + if( pRtree->nNodeRef ){ + /* Unable to write to the btree while another cursor is reading from it, + ** since the write might do a rebalance which would disrupt the read + ** cursor. */ + return SQLITE_LOCKED_VTAB; + } rtreeReference(pRtree); assert(nData>=1); diff --git a/ext/rtree/rtree8.test b/ext/rtree/rtree8.test index ac18fb477d..84191eef4c 100644 --- a/ext/rtree/rtree8.test +++ b/ext/rtree/rtree8.test @@ -38,11 +38,20 @@ do_test rtree8-1.1.1 { } {} do_test rtree8-1.1.2 { set res [list] - db eval { SELECT * FROM t1 } { - lappend res $x1 $x2 + set rc [catch { + db eval { SELECT * FROM t1 } { + lappend res $x1 $x2 + if {$id==3} { db eval { DELETE FROM t1 WHERE id>3 } } + } + } msg]; + lappend rc $msg + set rc +} {1 {database table is locked}} +do_test rtree8-1.1.2b { + db eval { SELECT * FROM t1 ORDER BY +id } { if {$id==3} { db eval { DELETE FROM t1 WHERE id>3 } } } - set res + db eval {SELECT x1, x2 FROM t1} } {1 3 2 4 3 5} do_test rtree8-1.1.3 { execsql { SELECT * FROM t1 } diff --git a/manifest b/manifest index 02f369cbf6..2942e21208 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C In\sthe\sOOM\stesting\slogic,\sadd\sthe\ssqlite3FirstFault()\sroutine\sas\sa\splace\sto\nset\sa\sbreakpoint\sthe\sfirst\stime\sany\ssimulated\sOOM\sfault\soccurs\sfor\sa\ssingle\ntest\scase. -D 2018-05-24T17:38:00.681 +C Do\snot\sallow\sRTree\swrites\swhen\sa\sread\scursor\sis\sactive\son\sthe\ssame\svirtual\ntable,\sas\sthe\swrites\smight\srebalance\sand\sdisrupt\sthe\sread\scursors.\s\sReturn\nthe\snew\sSQLITE_LOCKED_VTAB\serror\scode\sif\sthis\shappens. +D 2018-05-24T22:31:01.304 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -355,7 +355,7 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782 F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 148ae743198ca9fe1dfdf2fed74e5c3b0e69330e5b71ddc0d9df9993324dcedc +F ext/rtree/rtree.c 204ddbb7cfe0aab0136aea8c8b68c24f102d54aa38ccb88f6b4782ad5a5c61c9 F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412 F ext/rtree/rtree1.test 587889855b26fb8637417921b0709ca843cb6d36db94a882371fd8b7dcc3aa0b F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2 @@ -364,7 +364,7 @@ F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd F ext/rtree/rtree5.test 49c9041d713d54560b315c2c7ef7207ee287eba1b20f8266968a06f2e55d3142 F ext/rtree/rtree6.test 593e0d36510d5ac1d1fb39b018274ff17604fe8fdca8cf1f8e16559cea1477f4 F ext/rtree/rtree7.test c8fb2e555b128dd0f0bdb520c61380014f497f8a23c40f2e820acc9f9e4fdce5 -F ext/rtree/rtree8.test 649f5a37ec656028a4a32674b9b1183104285a7625a09d2a8f52a1cef72c93f2 +F ext/rtree/rtree8.test f8aefd8b92f92333ae00b93eca7c197ab24522b219390a337f2a0c62a5d5f96a F ext/rtree/rtree9.test c646f12c8c1c68ef015c6c043d86a0c42488e2e68ed1bb1b0771a7ca246cbabf F ext/rtree/rtreeA.test 20623ca337ca3bd7e008cc9fb49e44dbe97f1a80b238e10a12bb4afcd0da3776 F ext/rtree/rtreeB.test 4cec297f8e5c588654bbf3c6ed0903f10612be8a2878055dd25faf8c71758bc9 @@ -496,7 +496,7 @@ F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c a35d462ee7a3c0856ad7a9d9c8921fbf3d91d911a8f39ad9d61302eb43b24a71 F src/shell.c.in 51c100206f4b7f86cd9affd80b764825e0edc36ca0190c442e4ca7994611bfe2 -F src/sqlite.h.in ac6aec2abe10585733c1fea06622df5d73f7725c36c6cf054e89affeaccfa42b +F src/sqlite.h.in e379906b85cc3539c6a37ab972f2c28711b28854a457f54e137d20f75db5db7c F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7 F src/sqliteInt.h 5abdade4744cf3bd567afb65bb144bb3c61f6132f86813b995a5ca79c7b584e8 @@ -1729,7 +1729,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 36cdfbf2ce1811691c790fde3eaeed0238c03b4dc97dc3a20d1e0397520145d1 -R 085dc0bd34d45e9f6435a293683fda7b +P b4d80bd287ca7f3a6d182ba2435273266035b94fdf6a44047a64a4eff931c571 +R 2c56c09e62f3443ca0fffe92fcd36092 U drh -Z 2f994e2ed2922ec0ed95eb384d135eee +Z 5e9f190f156904a95f9a8ccad0e9448c diff --git a/manifest.uuid b/manifest.uuid index 7278a0f019..d73aad0973 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b4d80bd287ca7f3a6d182ba2435273266035b94fdf6a44047a64a4eff931c571 \ No newline at end of file +d4ce66610851c825cb712f985216b63e015c753fdd5521f929c67ad18bfd7664 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 7296597ea3..db2619ef57 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -504,6 +504,7 @@ int sqlite3_exec( #define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8)) #define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) +#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) From 30fc7f80097e9a255ce27f8c16bb9344f069876a Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 24 May 2018 22:42:27 +0000 Subject: [PATCH 8/9] New test case for reading and writing the same rtree concurrently. FossilOrigin-Name: 3ba08e53d54165f5541756ad13a4c2f0b18516cb612a256e056ed1ff76c1fa83 --- ext/rtree/rtree8.test | 24 ++++++++++++++++++++++++ manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/ext/rtree/rtree8.test b/ext/rtree/rtree8.test index 84191eef4c..68b68c45fd 100644 --- a/ext/rtree/rtree8.test +++ b/ext/rtree/rtree8.test @@ -179,5 +179,29 @@ do_test rtree8-5.4 { } {} do_rtree_integrity_test rtree8-5.5 t2 +# 2018-05-24 +# The following script caused an assertion fault and/or segfault +# prior to the fix that prevents simultaneous reads and writes on +# the same rtree virtual table. +# +do_test rtree8-6.1 { + db close + sqlite3 db :memory: + db eval { + PRAGMA page_size=512; + CREATE VIRTUAL TABLE t1 USING rtree(id,x1,x2,y1,y2); + WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<49) + INSERT INTO t1 SELECT x, x, x+1, x, x+1 FROM c; + } + set rc [catch { + db eval {SELECT id FROM t1} x { + db eval {DELETE FROM t1 WHERE id=$x(id)} + } + } msg] + lappend rc $msg +} {1 {database table is locked}} + + + finish_test diff --git a/manifest b/manifest index 2942e21208..8df58b3b86 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Do\snot\sallow\sRTree\swrites\swhen\sa\sread\scursor\sis\sactive\son\sthe\ssame\svirtual\ntable,\sas\sthe\swrites\smight\srebalance\sand\sdisrupt\sthe\sread\scursors.\s\sReturn\nthe\snew\sSQLITE_LOCKED_VTAB\serror\scode\sif\sthis\shappens. -D 2018-05-24T22:31:01.304 +C New\stest\scase\sfor\sreading\sand\swriting\sthe\ssame\srtree\sconcurrently. +D 2018-05-24T22:42:27.872 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -364,7 +364,7 @@ F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd F ext/rtree/rtree5.test 49c9041d713d54560b315c2c7ef7207ee287eba1b20f8266968a06f2e55d3142 F ext/rtree/rtree6.test 593e0d36510d5ac1d1fb39b018274ff17604fe8fdca8cf1f8e16559cea1477f4 F ext/rtree/rtree7.test c8fb2e555b128dd0f0bdb520c61380014f497f8a23c40f2e820acc9f9e4fdce5 -F ext/rtree/rtree8.test f8aefd8b92f92333ae00b93eca7c197ab24522b219390a337f2a0c62a5d5f96a +F ext/rtree/rtree8.test 924926d7c64ac59fcca0809de472d9dd73c612f54daae1cf992bdd7dac90305b F ext/rtree/rtree9.test c646f12c8c1c68ef015c6c043d86a0c42488e2e68ed1bb1b0771a7ca246cbabf F ext/rtree/rtreeA.test 20623ca337ca3bd7e008cc9fb49e44dbe97f1a80b238e10a12bb4afcd0da3776 F ext/rtree/rtreeB.test 4cec297f8e5c588654bbf3c6ed0903f10612be8a2878055dd25faf8c71758bc9 @@ -1729,7 +1729,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 b4d80bd287ca7f3a6d182ba2435273266035b94fdf6a44047a64a4eff931c571 -R 2c56c09e62f3443ca0fffe92fcd36092 +P d4ce66610851c825cb712f985216b63e015c753fdd5521f929c67ad18bfd7664 +R 7c176c4ded679924551c349003268c49 U drh -Z 5e9f190f156904a95f9a8ccad0e9448c +Z 02d192b4b4e1fc5e4499fb6cc57fb084 diff --git a/manifest.uuid b/manifest.uuid index d73aad0973..c94163f18e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d4ce66610851c825cb712f985216b63e015c753fdd5521f929c67ad18bfd7664 \ No newline at end of file +3ba08e53d54165f5541756ad13a4c2f0b18516cb612a256e056ed1ff76c1fa83 \ No newline at end of file From 338e311acb213a772927bac361c7a80b0bf51632 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 24 May 2018 23:51:57 +0000 Subject: [PATCH 9/9] When doing a one-pass UPDATE or DELETE on virtual tables, close the cursor prior to running VUpdate. This allows one-pass to work on virtual tables that do not allow concurrent reads and writes. Enhance rtree to take advantage of this new capability. FossilOrigin-Name: b816023ce07d01024d5769e16db924374a49bf909edd12dc1344a0a1ef693db5 --- ext/rtree/rtree.c | 1 + ext/rtree/rtree1.test | 10 +++++----- manifest | 18 +++++++++--------- manifest.uuid | 2 +- src/delete.c | 11 +++++++---- src/update.c | 14 +++++++++----- 6 files changed, 32 insertions(+), 24 deletions(-) diff --git a/ext/rtree/rtree.c b/ext/rtree/rtree.c index 54be2f6ced..e1b16ec0f5 100644 --- a/ext/rtree/rtree.c +++ b/ext/rtree/rtree.c @@ -1904,6 +1904,7 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ */ pIdxInfo->estimatedCost = 30.0; pIdxInfo->estimatedRows = 1; + pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE; return SQLITE_OK; } diff --git a/ext/rtree/rtree1.test b/ext/rtree/rtree1.test index a8ebf20625..bdaad542d2 100644 --- a/ext/rtree/rtree1.test +++ b/ext/rtree/rtree1.test @@ -476,11 +476,11 @@ foreach {tn sql_template testdata} { } 3 "UPDATE %CONF% t1 SET idx = 2 WHERE idx = 4" { - ROLLBACK 1 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6} - ABORT 1 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7} - IGNORE 1 0 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7} - FAIL 1 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7} - REPLACE 1 0 {1 1 2 3 4 2 4 5 6 7 3 3 4 5 6} + ROLLBACK 0 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6} + ABORT 0 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7} + IGNORE 0 0 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7} + FAIL 0 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7} + REPLACE 0 0 {1 1 2 3 4 2 4 5 6 7 3 3 4 5 6} } 3 "UPDATE %CONF% t1 SET idx = ((idx+1)%5)+1 WHERE idx > 2" { diff --git a/manifest b/manifest index 8df58b3b86..721b442bbb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C New\stest\scase\sfor\sreading\sand\swriting\sthe\ssame\srtree\sconcurrently. -D 2018-05-24T22:42:27.872 +C When\sdoing\sa\sone-pass\sUPDATE\sor\sDELETE\son\svirtual\stables,\sclose\sthe\scursor\nprior\sto\srunning\sVUpdate.\s\sThis\sallows\sone-pass\sto\swork\son\svirtual\stables\nthat\sdo\snot\sallow\sconcurrent\sreads\sand\swrites.\s\sEnhance\srtree\sto\stake\nadvantage\sof\sthis\snew\scapability. +D 2018-05-24T23:51:57.743 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da @@ -355,9 +355,9 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782 F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 -F ext/rtree/rtree.c 204ddbb7cfe0aab0136aea8c8b68c24f102d54aa38ccb88f6b4782ad5a5c61c9 +F ext/rtree/rtree.c cb6d4bd43c118354fe5b5213843da058259467ecdbac0c6f71ead0fd89acf4ec F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412 -F ext/rtree/rtree1.test 587889855b26fb8637417921b0709ca843cb6d36db94a882371fd8b7dcc3aa0b +F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349 F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2 F ext/rtree/rtree3.test 4ee5d7df86040efe3d8d84f141f2962a7745452200a7cba1db06f86d97050499 F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd73452c4b @@ -445,7 +445,7 @@ F src/ctime.c 849d4cebe008cfc6e4799b034a172b4eaf8856b100739632a852732ba66eee48 F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957 F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6 F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91 -F src/delete.c b0f90749e22d5e41a12dbf940f4811138cf97da54b46b737089b93eb64a2896f +F src/delete.c 4c8c7604277a2041647f96b78f4b9a47858e9217e4fb333d35e7b5ab32c5b57f F src/expr.c af4a81a385277510bfc56df87c25d76fc365f98c33bc8797c4a8d84b88e31013 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331 @@ -559,7 +559,7 @@ F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c F src/tokenize.c bbde32eac9eb1280f5292bcdfef66f5a57e43176cbf9347e0efab9f75e133f97 F src/treeview.c 2c5c4bc0a443401db5fd621542150452ddf5055d38edd4eef868bc2b6bfb0260 F src/trigger.c 4ace6d1d5ba9a89822deb287317f33c810440526eafe185c2d8a48c31df1e995 -F src/update.c 5be2f501ddc704fc04183bdb28b25eab930bb8553d973429a089ec94fa85cf2b +F src/update.c 46dc24c6158446aaab45caee09b6d99327cb479268b83ffeb5b701823da3b67b F src/upsert.c ae4a4823b45c4daf87e8aea8c0f582a8844763271f5ed54ee5956c4c612734f4 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157 @@ -1729,7 +1729,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 d4ce66610851c825cb712f985216b63e015c753fdd5521f929c67ad18bfd7664 -R 7c176c4ded679924551c349003268c49 +P 3ba08e53d54165f5541756ad13a4c2f0b18516cb612a256e056ed1ff76c1fa83 +R 52623d992549c096857f92f7f6ff2464 U drh -Z 02d192b4b4e1fc5e4499fb6cc57fb084 +Z 92fa856c89ee79b753ba76005690f976 diff --git a/manifest.uuid b/manifest.uuid index c94163f18e..5d8567b91b 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3ba08e53d54165f5541756ad13a4c2f0b18516cb612a256e056ed1ff76c1fa83 \ No newline at end of file +b816023ce07d01024d5769e16db924374a49bf909edd12dc1344a0a1ef693db5 \ No newline at end of file diff --git a/src/delete.c b/src/delete.c index 8efe89ded4..b682658e51 100644 --- a/src/delete.c +++ b/src/delete.c @@ -553,13 +553,16 @@ void sqlite3DeleteFrom( if( IsVirtual(pTab) ){ const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); sqlite3VtabMakeWritable(pParse, pTab); - sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB); - sqlite3VdbeChangeP5(v, OE_Abort); assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE ); sqlite3MayAbort(pParse); - if( eOnePass==ONEPASS_SINGLE && sqlite3IsToplevel(pParse) ){ - pParse->isMultiWrite = 0; + if( eOnePass==ONEPASS_SINGLE ){ + sqlite3VdbeAddOp1(v, OP_Close, iTabCur); + if( sqlite3IsToplevel(pParse) ){ + pParse->isMultiWrite = 0; + } } + sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB); + sqlite3VdbeChangeP5(v, OE_Abort); }else #endif { diff --git a/src/update.c b/src/update.c index 913fc2dd7a..9860943c0e 100644 --- a/src/update.c +++ b/src/update.c @@ -845,7 +845,7 @@ static void updateVirtualTable( int regRowid; /* Register for ephem table rowid */ int iCsr = pSrc->a[0].iCursor; /* Cursor used for virtual table scan */ int aDummy[2]; /* Unused arg for sqlite3WhereOkOnePass() */ - int bOnePass; /* True to use onepass strategy */ + int eOnePass; /* True to use onepass strategy */ int addr; /* Address of OP_OpenEphemeral */ /* Allocate nArg registers in which to gather the arguments for VUpdate. Then @@ -890,12 +890,16 @@ static void updateVirtualTable( sqlite3VdbeAddOp2(v, OP_SCopy, regArg+2+iPk, regArg+1); } - bOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy); + eOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy); - if( bOnePass ){ + /* There is no ONEPASS_MULTI on virtual tables */ + assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE ); + + if( eOnePass ){ /* If using the onepass strategy, no-op out the OP_OpenEphemeral coded ** above. */ sqlite3VdbeChangeToNoop(v, addr); + sqlite3VdbeAddOp1(v, OP_Close, iCsr); }else{ /* Create a record from the argument register contents and insert it into ** the ephemeral table. */ @@ -911,7 +915,7 @@ static void updateVirtualTable( } - if( bOnePass==0 ){ + if( eOnePass==ONEPASS_OFF ){ /* End the virtual table scan */ sqlite3WhereEnd(pWInfo); @@ -931,7 +935,7 @@ static void updateVirtualTable( /* End of the ephemeral table scan. Or, if using the onepass strategy, ** jump to here if the scan visited zero rows. */ - if( bOnePass==0 ){ + if( eOnePass==ONEPASS_OFF ){ sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v); sqlite3VdbeJumpHere(v, addr); sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);