From: drh Date: Mon, 18 Apr 2016 16:06:03 +0000 (+0000) Subject: Fix the sqlite3BtreeDelete() routine so that it preserves the correct X-Git-Tag: version-3.12.2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=37c66558cefd2fe6fd1460273bf632b3952d4306;p=thirdparty%2Fsqlite.git Fix the sqlite3BtreeDelete() routine so that it preserves the correct key even when the row being deleted is not on a leaf page. Fix for ticket [a306e56ff68b8fa56] FossilOrigin-Name: 368e86c760477f2e646f71f6135b69d40eeb82e7 --- diff --git a/manifest b/manifest index 239e5c27e5..348b5c25e3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Increase\sthe\sversion\snumber\sto\s3.12.2. -D 2016-04-18T15:59:16.905 +C Fix\sthe\ssqlite3BtreeDelete()\sroutine\sso\sthat\sit\spreserves\sthe\scorrect\nkey\seven\swhen\sthe\srow\sbeing\sdeleted\sis\snot\son\sa\sleaf\spage.\nFix\sfor\sticket\s[a306e56ff68b8fa56] +D 2016-04-18T16:06:03.711 F Makefile.in f53429fb2f313c099283659d0df6f20f932c861f F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc b00bcf0ec7001857aea81ee39fae45d20f5f4e59 @@ -297,7 +297,7 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c f60f0aa55d25d853ffde53d0b0370a7bb7ee41ce F src/bitvec.c 3ee4c8b2c94ed3a7377256e18199e6ff5cf33f63 F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 -F src/btree.c 577fb5674e2f0aa0a38246afc19e1885a0b8c9b0 +F src/btree.c c833d5ac4469a761435c211956315d000b246fdd F src/btree.h a5008b9afe56e8e54ade6c436a910f112defcca9 F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 F src/build.c 16bbcb166a06b4909a4c645273c474645dbdce66 @@ -593,7 +593,7 @@ F test/default.test 0cb49b1c315a0d81c81d775e407f66906a2a604d F test/delete.test e1bcdf8926234e27aac24b346ad83d3329ec8b6f F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab -F test/delete4.test 3ac0b8d23689ba764c2e8b78c1b56b8f1b942fa2 +F test/delete4.test 738044ee892ee0c84e0848e36ba92c55f907d52b F test/descidx1.test 6d03b44c8538fe0eb4924e19fba10cdd8f3c9240 F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2 @@ -1459,7 +1459,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ab9d279f40f81e5a95de10f70324960cf091c368 -R 98297537d8f146517a1f23e21a9df1a6 +P 9c37e9ce07b42bdbaa0cecfdd2bc8181b1eded47 +Q +ca2ef8a86cf806cbbcc64db03251b1df5b2c5501 +R 4710e941720805c2cc7e949e21895ad6 U drh -Z c9af401b6ea9af28f45209d059fd0667 +Z e361cdd0aa73a2909e88537a2c8c4051 diff --git a/manifest.uuid b/manifest.uuid index 882c458269..e879e4e2f6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9c37e9ce07b42bdbaa0cecfdd2bc8181b1eded47 \ No newline at end of file +368e86c760477f2e646f71f6135b69d40eeb82e7 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index bf99597095..496e09b690 100644 --- a/src/btree.c +++ b/src/btree.c @@ -8140,6 +8140,28 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ pPage = pCur->apPage[iCellDepth]; pCell = findCell(pPage, iCellIdx); + /* If the bPreserve flag is set to true, then the cursor position must + ** be preserved following this delete operation. If the current delete + ** will cause a b-tree rebalance, then this is done by saving the cursor + ** key and leaving the cursor in CURSOR_REQUIRESEEK state before + ** returning. + ** + ** Or, if the current delete will not cause a rebalance, then the cursor + ** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately + ** before or after the deleted entry. In this case set bSkipnext to true. */ + if( bPreserve ){ + if( !pPage->leaf + || (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3) + ){ + /* A b-tree rebalance will be required after deleting this entry. + ** Save the cursor key. */ + rc = saveCursorKey(pCur); + if( rc ) return rc; + }else{ + bSkipnext = 1; + } + } + /* If the page containing the entry to delete is not a leaf page, move ** the cursor to the largest entry in the tree that is smaller than ** the entry being deleted. This cell will replace the cell being deleted @@ -8166,28 +8188,6 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){ invalidateIncrblobCursors(p, pCur->info.nKey, 0); } - /* If the bPreserve flag is set to true, then the cursor position must - ** be preserved following this delete operation. If the current delete - ** will cause a b-tree rebalance, then this is done by saving the cursor - ** key and leaving the cursor in CURSOR_REQUIRESEEK state before - ** returning. - ** - ** Or, if the current delete will not cause a rebalance, then the cursor - ** will be left in CURSOR_SKIPNEXT state pointing to the entry immediately - ** before or after the deleted entry. In this case set bSkipnext to true. */ - if( bPreserve ){ - if( !pPage->leaf - || (pPage->nFree+cellSizePtr(pPage,pCell)+2)>(int)(pBt->usableSize*2/3) - ){ - /* A b-tree rebalance will be required after deleting this entry. - ** Save the cursor key. */ - rc = saveCursorKey(pCur); - if( rc ) return rc; - }else{ - bSkipnext = 1; - } - } - /* Make the page containing the entry to be deleted writable. Then free any ** overflow pages associated with the entry and finally remove the cell ** itself from within the page. */ diff --git a/test/delete4.test b/test/delete4.test index f3598a9496..7622b7525e 100644 --- a/test/delete4.test +++ b/test/delete4.test @@ -139,7 +139,26 @@ do_execsql_test 4.12 { PRAGMA integrity_check; } {ok} - - +# 2016-04-09 +# Ticket https://sqlite.org/src/info/a306e56ff68b8fa5 +# Failure to completely delete when reverse_unordered_selects is +# engaged. +# +db close +forcedelete test.db +sqlite3 db test.db +do_execsql_test 5.0 { + PRAGMA page_size=1024; + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); + CREATE INDEX x1 ON t1(b, c); + INSERT INTO t1(a,b,c) VALUES(1, 1, zeroblob(80)); + INSERT INTO t1(a,b,c) SELECT a+1, 1, c FROM t1; + INSERT INTO t1(a,b,c) SELECT a+2, 1, c FROM t1; + INSERT INTO t1(a,b,c) SELECT a+10, 2, c FROM t1 WHERE b=1; + INSERT INTO t1(a,b,c) SELECT a+20, 3, c FROM t1 WHERE b=1; + PRAGMA reverse_unordered_selects = ON; + DELETE FROM t1 WHERE b=2; + SELECT a FROM t1 WHERE b=2; +} {} finish_test