]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix the saveCursorPosition() routine in btree.c so that it works
authordrh <drh@noemail.net>
Wed, 25 Mar 2015 17:35:01 +0000 (17:35 +0000)
committerdrh <drh@noemail.net>
Wed, 25 Mar 2015 17:35:01 +0000 (17:35 +0000)
correctly for a eState=CURSOR_SKIPNEXT cursor.

FossilOrigin-Name: 37866b4d483296ab9b7fcb9f5486695d4c2b8ddd

manifest
manifest.uuid
src/btree.c
test/btree02.test [new file with mode: 0644]

index a0f706c6357eda1bdc97b17d88c0f2ce2dc0f18f..48427f05a39fbac0ce5c3a095c85838e1b3fa607 100644 (file)
--- 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
index d4bfb47acf64557d8523a5e963313de6187ac159..90856bf9ee9aa7451c2da8f3633561ff990204c2 100644 (file)
@@ -1 +1 @@
-1e96520ac1d12ca83f019a60482efa0a074f2f94
\ No newline at end of file
+37866b4d483296ab9b7fcb9f5486695d4c2b8ddd
\ No newline at end of file
index ac350ac92fe934caf194194ea3706c29acf8b450..dd10f6a09acff032da61a3c2c3d1519799bd8ca4 100644 (file)
@@ -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 (file)
index 0000000..de7c06d
--- /dev/null
@@ -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