From: drh Date: Wed, 25 Mar 2015 17:35:01 +0000 (+0000) Subject: Fix the saveCursorPosition() routine in btree.c so that it works X-Git-Tag: version-3.8.9~32 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d2f83139f3774c61f545095c813a28a859320b39;p=thirdparty%2Fsqlite.git Fix the saveCursorPosition() routine in btree.c so that it works correctly for a eState=CURSOR_SKIPNEXT cursor. FossilOrigin-Name: 37866b4d483296ab9b7fcb9f5486695d4c2b8ddd --- diff --git a/manifest b/manifest index a0f706c635..48427f05a3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Reactivate\san\solder\sassert()\s(adding\san\s"||\sCORRUPT_DB"\sterm)\sand\sadd\sa\nnew\sassert()\sin\sbtree.c. -D 2015-03-25T13:06:54.837 +C Fix\sthe\ssaveCursorPosition()\sroutine\sin\sbtree.c\sso\sthat\sit\sworks\ncorrectly\sfor\sa\seState=CURSOR_SKIPNEXT\scursor. +D 2015-03-25T17:35:01.825 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 88a3e6261286db378fdffa1124cad11b3c05f5bb F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -173,7 +173,7 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240 F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3 F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 -F src/btree.c 3634c2ee748bbbb2488cdca9dc8fc8c7bdc2f66f +F src/btree.c 933ab4ad883546193f5fd55f840299165adb8069 F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1 F src/btreeInt.h 2bfefc01875d8da066504c233ec259fcb3b2ef72 F src/build.c 0419bba592c22f6d00e6d57a2ca7136720d02c1a @@ -384,6 +384,7 @@ F test/boundary3.test 56ef82096b4329aca2be74fa1e2b0f762ea0eb45 F test/boundary4.tcl 0bb4b1a94f4fc5ae59b79b9a2b7a140c405e2983 F test/boundary4.test 89e02fa66397b8a325d5eb102b5806f961f8ec4b F test/btree01.test e08b3613540145b353f20c81cb18ead54ff12e0f +F test/btree02.test fe69453d474d8154d19b904157ff1db4812fed99 F test/btreefault.test c2bcb542685eea44621275cfedbd8a13f65201e3 F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0 F test/cache.test 13bc046b26210471ca6f2889aceb1ea52dc717de @@ -1246,7 +1247,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 42d1793d6516e285a8925bbfd96b3d3375603d15 -R 90535e28cf02760b75aa0324ce2f944c +P 1e96520ac1d12ca83f019a60482efa0a074f2f94 +R 0d2b32f8ac05ffe0443a79d106bd4efe U drh -Z 7ee968129b9c07925188972da6333faa +Z 2f58ba8b67469927a3c7d533210b0ef3 diff --git a/manifest.uuid b/manifest.uuid index d4bfb47acf..90856bf9ee 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1e96520ac1d12ca83f019a60482efa0a074f2f94 \ No newline at end of file +37866b4d483296ab9b7fcb9f5486695d4c2b8ddd \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index ac350ac92f..dd10f6a09a 100644 --- a/src/btree.c +++ b/src/btree.c @@ -600,10 +600,15 @@ static void btreeReleaseAllCursorPages(BtCursor *pCur){ static int saveCursorPosition(BtCursor *pCur){ int rc; - assert( CURSOR_VALID==pCur->eState ); + assert( CURSOR_VALID==pCur->eState || CURSOR_SKIPNEXT==pCur->eState ); assert( 0==pCur->pKey ); assert( cursorHoldsMutex(pCur) ); + if( pCur->eState==CURSOR_SKIPNEXT ){ + pCur->eState = CURSOR_VALID; + }else{ + pCur->skipNext = 0; + } rc = sqlite3BtreeKeySize(pCur, &pCur->nKey); assert( rc==SQLITE_OK ); /* KeySize() cannot fail */ @@ -674,7 +679,7 @@ static int SQLITE_NOINLINE saveCursorsOnList( ){ do{ if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){ - if( p->eState==CURSOR_VALID ){ + if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){ int rc = saveCursorPosition(p); if( SQLITE_OK!=rc ){ return rc; @@ -746,17 +751,19 @@ static int btreeMoveto( */ static int btreeRestoreCursorPosition(BtCursor *pCur){ int rc; + int skipNext; assert( cursorHoldsMutex(pCur) ); assert( pCur->eState>=CURSOR_REQUIRESEEK ); if( pCur->eState==CURSOR_FAULT ){ return pCur->skipNext; } pCur->eState = CURSOR_INVALID; - rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skipNext); + rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext); if( rc==SQLITE_OK ){ sqlite3_free(pCur->pKey); pCur->pKey = 0; assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID ); + pCur->skipNext |= skipNext; if( pCur->skipNext && pCur->eState==CURSOR_VALID ){ pCur->eState = CURSOR_SKIPNEXT; } @@ -808,7 +815,7 @@ int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow){ *pDifferentRow = 1; return rc; } - if( pCur->eState!=CURSOR_VALID || NEVER(pCur->skipNext!=0) ){ + if( pCur->eState!=CURSOR_VALID || pCur->skipNext!=0 ){ *pDifferentRow = 1; }else{ *pDifferentRow = 0; @@ -3625,7 +3632,7 @@ int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int writeOnly){ for(p=pBtree->pBt->pCursor; p; p=p->pNext){ int i; if( writeOnly && (p->curFlags & BTCF_WriteFlag)==0 ){ - if( p->eState==CURSOR_VALID ){ + if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){ rc = saveCursorPosition(p); if( rc!=SQLITE_OK ){ (void)sqlite3BtreeTripAllCursors(pBtree, rc, 0); diff --git a/test/btree02.test b/test/btree02.test new file mode 100644 index 0000000000..de7c06d442 --- /dev/null +++ b/test/btree02.test @@ -0,0 +1,52 @@ +# 2015-03-25 +# +# 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. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. +# +# The focus of this script is making multiple calls to saveCursorPosition() +# and restoreCursorPosition() when cursors have eState==CURSOR_SKIPNEXT +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +load_static_extension db eval +do_execsql_test btree02-100 { + CREATE TABLE t1(a TEXT, ax INTEGER, b INT, PRIMARY KEY(a,ax)) WITHOUT ROWID; + WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<10) + INSERT INTO t1(a,ax,b) SELECT printf('%02x',i), random(), i FROM c; + CREATE INDEX t1a ON t1(a); + CREATE TABLE t2(x,y); + CREATE TABLE t3(cnt); + WITH RECURSIVE c(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM c WHERE i<4) + INSERT INTO t3(cnt) SELECT i FROM c; + SELECT count(*) FROM t1; +} {10} +do_test btree02-110 { + db eval BEGIN + set i 0 + db eval {SELECT a, ax, b, cnt FROM t1 CROSS JOIN t3 WHERE b IS NOT NULL} { + db eval {INSERT INTO t2(x,y) VALUES($b,$cnt)} + # puts "a,b,cnt = ($a,$b,$cnt)" + incr i + if {$i%2==1} { + set bx [expr {$b+1000}] + # puts "INSERT ($a),$bx" + db eval {INSERT INTO t1(a,ax,b) VALUES(printf('(%s)',$a),random(),$bx)} + } else { + # puts "DELETE a=$a" + db eval {DELETE FROM t1 WHERE a=$a} + } + db eval {COMMIT; BEGIN} + } + db one {COMMIT; SELECT count(*) FROM t1;} +} {20} + +finish_test