]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
When a cursor points at the last entry of an intkey btree after an insert, leave...
authordanielk1977 <danielk1977@noemail.net>
Sat, 2 May 2009 10:03:09 +0000 (10:03 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Sat, 2 May 2009 10:03:09 +0000 (10:03 +0000)
FossilOrigin-Name: 9950c0a79c82eb7d8495b0b1a8fe117d566e2387

manifest
manifest.uuid
src/btree.c

index 22d417b81cb7730b8a7b6fafb036f2172a0318dc..744628383e1ad30a2bbc27ef76c6e7ab8abd1a61 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Do\snot\sreset\sthe\scursor\sbefore\sseeking\sit\sin\ssqlite3BtreeInsert().\sThis\sspeeds\sup\sINSERT\soperations\sthat\suse\sauto-generated\srowid\svalues.\s(CVS\s6591)
-D 2009-05-02T07:36:50
+C When\sa\scursor\spoints\sat\sthe\slast\sentry\sof\san\sintkey\sbtree\safter\san\sinsert,\sleave\sit\sthere\s(instead\sof\smoving\sit\sto\sthe\stree\sroot\snode).\sThis\sspeeds\sup\sstatements\sof\sthe\sform\s"INSERT\sINTO\s...\sSELECT\s..."\sthat\suse\sauto-generated\srowids.\s(CVS\s6592)
+D 2009-05-02T10:03:09
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in 583e87706abc3026960ed759aff6371faf84c211
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -106,7 +106,7 @@ F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
 F src/backup.c 0082d0e5a63f04e88faee0dff0a7d63d3e92a78d
 F src/bitvec.c ef370407e03440b0852d05024fb016b14a471d3d
 F src/btmutex.c 9b899c0d8df3bd68f527b0afe03088321b696d3c
-F src/btree.c 1201cba9e4ccd029a2b88431d14e315c086af6ba
+F src/btree.c 64ad8841aefce2ba0cb3b138e5fe8669ce5fa6db
 F src/btree.h 99fcc7e8c4a1e35afe271bcb38de1a698dfc904e
 F src/btreeInt.h df64030d632f8c8ac217ed52e8b6b3eacacb33a5
 F src/build.c a079f965feea2d0b469b293e09cd0ac41be1272f
@@ -727,7 +727,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
-P 7d2b80c7addc2d03d49647da9c6df9113f01349d
-R be37f24bb5752583479cd908d65ba960
+P 20c4acc291def33980f584f882c76e85ee1c8238
+R 473bd4e478192dc26a9afe58e69a17f0
 U danielk1977
-Z 771348bde250b0527ce1a0ce0c034f60
+Z 5fda7c8bdbaa8fda519ae98860016fe1
index 81dae04fdc912d796a13b18e1ed40c2de759546e..e59e11086a37d8c926faa2c302795b916f32b935 100644 (file)
@@ -1 +1 @@
-20c4acc291def33980f584f882c76e85ee1c8238
\ No newline at end of file
+9950c0a79c82eb7d8495b0b1a8fe117d566e2387
\ No newline at end of file
index 7241ac7b58e3ca958815c7efdae6574e9502b987..2692539a5086a634d72a92ba89aecbb57a739e89 100644 (file)
@@ -9,7 +9,7 @@
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** $Id: btree.c,v 1.604 2009/05/02 07:36:50 danielk1977 Exp $
+** $Id: btree.c,v 1.605 2009/05/02 10:03:09 danielk1977 Exp $
 **
 ** This file implements a external (disk-based) database using BTrees.
 ** See the header comment on "btreeInt.h" for additional information.
@@ -3921,6 +3921,22 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
  
   assert( cursorHoldsMutex(pCur) );
   assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
+
+  /* If the cursor already points to the last entry, this is a no-op. */
+  if( CURSOR_VALID==pCur->eState && pCur->atLast ){
+#ifdef SQLITE_DEBUG
+    /* This block serves to assert() that the cursor really does point 
+    ** to the last entry in the b-tree. */
+    int ii;
+    for(ii=0; ii<pCur->iPage; ii++){
+      assert( pCur->aiIdx[ii]==pCur->apPage[ii]->nCell );
+    }
+    assert( pCur->aiIdx[pCur->iPage]==pCur->apPage[pCur->iPage]->nCell-1 );
+    assert( pCur->apPage[pCur->iPage]->leaf );
+#endif
+    return SQLITE_OK;
+  }
+
   rc = moveToRoot(pCur);
   if( rc==SQLITE_OK ){
     if( CURSOR_INVALID==pCur->eState ){
@@ -6210,17 +6226,42 @@ int sqlite3BtreeInsert(
     assert( pPage->leaf );
   }
   rc = insertCell(pPage, idx, newCell, szNew, 0, 0);
-  if( rc==SQLITE_OK ){
+  assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 );
+
+  /* If no error has occured, call balance() to deal with any overflow and
+  ** move the cursor to point at the root of the table (since balance may
+  ** have rearranged the table in such a way as to invalidate BtCursor.apPage[]
+  ** or BtCursor.aiIdx[]).
+  **
+  ** Except, if all of the following are true, do nothing:
+  **
+  **   * Inserting the new cell did not cause overflow,
+  **
+  **   * Before inserting the new cell the cursor was pointing at the 
+  **     largest key in an intkey B-Tree, and
+  **
+  **   * The key value associated with the new cell is now the largest 
+  **     in the B-Tree.
+  **
+  ** In this case the cursor can be safely left pointing at the (new) 
+  ** largest key value in the B-Tree. Doing so speeds up inserting a set
+  ** of entries with increasing integer key values via a single cursor
+  ** (comes up with "INSERT INTO ... SELECT ..." statements), as 
+  ** the next insert operation is not required to seek the cursor.
+  */
+  if( rc==SQLITE_OK 
+   && (pPage->nOverflow || !pCur->atLast || loc>=0 || !pCur->apPage[0]->intKey)
+  ){
     rc = balance(pCur, 1);
+    if( rc==SQLITE_OK ){
+      moveToRoot(pCur);
+    }
   }
-
+  
   /* Must make sure nOverflow is reset to zero even if the balance()
   ** fails.  Internal data structure corruption will result otherwise. */
   pCur->apPage[pCur->iPage]->nOverflow = 0;
 
-  if( rc==SQLITE_OK ){
-    moveToRoot(pCur);
-  }
 end_insert:
   return rc;
 }