]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Speed up in the handling of VDBE cursors. (CVS 1578)
authordrh <drh@noemail.net>
Sat, 12 Jun 2004 20:12:51 +0000 (20:12 +0000)
committerdrh <drh@noemail.net>
Sat, 12 Jun 2004 20:12:51 +0000 (20:12 +0000)
FossilOrigin-Name: e42316f5708de6f639b7b54e08d4be73b45367e9

manifest
manifest.uuid
src/vdbe.c
src/vdbeInt.h
src/vdbeaux.c

index 42030e5a2009345a50bd34706e17c227c60a31a4..eda87be02c7f5cef833ca5e91300acd4451b0d91 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Improve\sthe\sspeed\sof\sOP_Column\sthrough\sbetter\scaching.\s(CVS\s1577)
-D 2004-06-12T18:12:16
+C Speed\sup\sin\sthe\shandling\sof\sVDBE\scursors.\s(CVS\s1578)
+D 2004-06-12T20:12:51
 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -71,11 +71,11 @@ F src/update.c 168b6d523087ca4545b74ec9f3102b1f3c6b1e38
 F src/utf.c e16737b3fc4201bf7ce9bd8ced5250596aa31b76
 F src/util.c 90375fa253137562d536ccdd40b297f0fd7413fc
 F src/vacuum.c b921eb778842592e1fb48a9d4cef7e861103878f
-F src/vdbe.c 9f941bbdf0bcbc18fbdfceecbc2322e82084e094
+F src/vdbe.c c71e47262d3d3539a20a489a03b9cde15ef3acb7
 F src/vdbe.h 46f74444a213129bc4b5ce40124dd8ed613b0cde
-F src/vdbeInt.h 1cc767a63eefd1d1114e190336588c6d4f70a6a0
+F src/vdbeInt.h ffc7b8ed911c5bf804796a768fdb6f0568010fa2
 F src/vdbeapi.c ee350b552fc4c1c695b760f914f69e9c5556e829
-F src/vdbeaux.c 1d0dbaf73c89bd1cc27abad19ee0aa26ab5d03f4
+F src/vdbeaux.c ff7c66b704dc2c35805657f2cb10ad1b00c8ecd2
 F src/vdbemem.c 34f59988831ea032b7f526c2c73175f9f4c0f3ad
 F src/where.c dda77afaa593cd54e5955ec433076de18faf62f6
 F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
@@ -223,7 +223,7 @@ F www/support.tcl 1801397edd271cc39a2aadd54e701184b5181248
 F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075
 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P 99a7bd83ac38e14bb936a834634313cf98279a62
-R 1e1692dcb3026c03937468eb4d723051
+P f687977a28eda5ce0aa1cba2fdfb0152443032bc
+R 088c58f79c616faca7f8012c3563c5db
 U drh
-Z 511db11f04adc59072cae9559d18a6b6
+Z 661048d261d615dd2ffa1c2c62f56278
index 3a7b8c7357cd720aa6eb60c70f5e7312023300e1..8db71c8278cc139f5b078475d02caa1ab3d308a0 100644 (file)
@@ -1 +1 @@
-f687977a28eda5ce0aa1cba2fdfb0152443032bc
\ No newline at end of file
+e42316f5708de6f639b7b54e08d4be73b45367e9
\ No newline at end of file
index 4c1faef212cd99ee76145fe55291584a77d67da0..9057e0de4ec44fbe20a6e45e7f5624cb36b1782a 100644 (file)
@@ -43,7 +43,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.369 2004/06/12 18:12:16 drh Exp $
+** $Id: vdbe.c,v 1.370 2004/06/12 20:12:51 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -271,24 +271,27 @@ static Sorter *Merge(Sorter *pLeft, Sorter *pRight, KeyInfo *pKeyInfo){
 }
 
 /*
-** Make sure there is space in the Vdbe structure to hold at least
-** mxCursor cursors.  If there is not currently enough space, then
-** allocate more.
-**
-** If a memory allocation error occurs, return 1.  Return 0 if
-** everything works.
-*/
-static int expandCursorArraySize(Vdbe *p, int mxCursor){
-  if( mxCursor>=p->nCursor ){
-    p->apCsr = sqliteRealloc( p->apCsr, (mxCursor+1)*sizeof(Cursor*) );
-    if( p->apCsr==0 ) return 1;
-    while( p->nCursor<=mxCursor ){
-      Cursor *pC;
-      p->apCsr[p->nCursor++] = pC = sqliteMalloc( sizeof(Cursor) );
-      if( pC==0 ) return 1;
+** Allocate cursor number iCur.  Return a pointer to it.  Return NULL
+** if we run out of memory.
+*/
+static Cursor *allocateCursor(Vdbe *p, int iCur){
+  Cursor *pCx;
+  if( iCur>=p->nCursor ){
+    int i;
+    p->apCsr = sqliteRealloc( p->apCsr, (iCur+1)*sizeof(Cursor*) );
+    if( p->apCsr==0 ){
+      p->nCursor = 0;
+      return 0;
     }
+    for(i=p->nCursor; i<iCur; i++){
+      p->apCsr[i] = 0;
+    }
+    p->nCursor = iCur+1;
+  }else if( p->apCsr[iCur] ){
+    sqlite3VdbeFreeCursor(p->apCsr[iCur]);
   }
-  return 0;
+  p->apCsr[iCur] = pCx = sqliteMalloc( sizeof(Cursor) );
+  return pCx;
 }
 
 /*
@@ -1867,6 +1870,7 @@ case OP_NotNull: {
 */
 case OP_SetNumColumns: {
   assert( (pOp->p1)<p->nCursor );
+  assert( p->apCsr[pOp->p1]!=0 );
   p->apCsr[pOp->p1]->nField = pOp->p2;
   break;
 }
@@ -1931,6 +1935,7 @@ case OP_Column: {
   ** records on the stack, the next entry down on the stack is an integer
   ** which is the number of records.
   */
+  assert( p1<0 || p->apCsr[p1]!=0 );
   if( p1<0 ){
     /* Take the record off of the stack */
     Mem *pRec = &pTos[p1];
@@ -2572,9 +2577,8 @@ case OP_OpenWrite: {
     }
   }
   assert( i>=0 );
-  if( expandCursorArraySize(p, i) ) goto no_mem;
-  pCur = p->apCsr[i];
-  sqlite3VdbeCleanupCursor(pCur);
+  pCur = allocateCursor(p, i);
+  if( pCur==0 ) goto no_mem;
   pCur->nullRow = 1;
   if( pX==0 ) break;
   /* We always provide a key comparison function.  If the table being
@@ -2635,10 +2639,8 @@ case OP_OpenTemp: {
   int i = pOp->p1;
   Cursor *pCx;
   assert( i>=0 );
-  if( expandCursorArraySize(p, i) ) goto no_mem;
-  pCx = p->apCsr[i];
-  sqlite3VdbeCleanupCursor(pCx);
-  memset(pCx, 0, sizeof(*pCx));
+  pCx = allocateCursor(p, i);
+  if( pCx==0 ) goto no_mem;
   pCx->nullRow = 1;
   rc = sqlite3BtreeFactory(db, 0, 1, TEMP_PAGES, &pCx->pBt);
 
@@ -2686,10 +2688,8 @@ case OP_OpenPseudo: {
   int i = pOp->p1;
   Cursor *pCx;
   assert( i>=0 );
-  if( expandCursorArraySize(p, i) ) goto no_mem;
-  pCx = p->apCsr[i];
-  sqlite3VdbeCleanupCursor(pCx);
-  memset(pCx, 0, sizeof(*pCx));
+  pCx = allocateCursor(p, i);
+  if( pCx==0 ) goto no_mem;
   pCx->nullRow = 1;
   pCx->pseudoTable = 1;
   pCx->pIncrKey = &pCx->bogusIncrKey;
@@ -2704,7 +2704,8 @@ case OP_OpenPseudo: {
 case OP_Close: {
   int i = pOp->p1;
   if( i>=0 && i<p->nCursor ){
-    sqlite3VdbeCleanupCursor(p->apCsr[i]);
+    sqlite3VdbeFreeCursor(p->apCsr[i]);
+    p->apCsr[i] = 0;
   }
   break;
 }
@@ -2759,6 +2760,7 @@ case OP_MoveGt: {
   assert( pTos>=p->aStack );
   assert( i>=0 && i<p->nCursor );
   pC = p->apCsr[i];
+  assert( pC!=0 );
   if( pC->pCursor!=0 ){
     int res, oc;
     oc = pOp->opcode;
@@ -2858,6 +2860,7 @@ case OP_Found: {
   Cursor *pC;
   assert( pTos>=p->aStack );
   assert( i>=0 && i<p->nCursor );
+  assert( p->apCsr[i]!=0 );
   if( (pC = p->apCsr[i])->pCursor!=0 ){
     int res, rx;
     assert( pC->intKey==0 );
@@ -2915,6 +2918,7 @@ case OP_IsUnique: {
   pTos--;
   assert( i>=0 && i<=p->nCursor );
   pCx = p->apCsr[i];
+  assert( pCx!=0 );
   pCrsr = pCx->pCursor;
   if( pCrsr!=0 ){
     int res, rc;
@@ -2998,6 +3002,7 @@ case OP_NotExists: {
   BtCursor *pCrsr;
   assert( pTos>=p->aStack );
   assert( i>=0 && i<p->nCursor );
+  assert( p->apCsr[i]!=0 );
   if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
     int res, rx;
     u64 iKey;
@@ -3031,6 +3036,7 @@ case OP_NewRecno: {
   i64 v = 0;
   Cursor *pC;
   assert( i>=0 && i<p->nCursor );
+  assert( p->apCsr[i]!=0 );
   if( (pC = p->apCsr[i])->pCursor==0 ){
     /* The zero initialization above is all that is needed */
   }else{
@@ -3159,6 +3165,7 @@ case OP_PutStrKey: {
   Cursor *pC;
   assert( pNos>=p->aStack );
   assert( i>=0 && i<p->nCursor );
+  assert( p->apCsr[i]!=0 );
   if( ((pC = p->apCsr[i])->pCursor!=0 || pC->pseudoTable) ){
     char *zKey;
     i64 nKey; 
@@ -3249,6 +3256,7 @@ case OP_Delete: {
   Cursor *pC;
   assert( i>=0 && i<p->nCursor );
   pC = p->apCsr[i];
+  assert( pC!=0 );
   if( pC->pCursor!=0 ){
     sqlite3VdbeCursorMoveto(pC);
     rc = sqlite3BtreeDelete(pC->pCursor);
@@ -3283,6 +3291,7 @@ case OP_KeyAsData: {
   Cursor *pC;
   assert( i>=0 && i<p->nCursor );
   pC = p->apCsr[i];
+  assert( pC!=0 );
   pC->keyAsData = pOp->p2;
   break;
 }
@@ -3314,6 +3323,7 @@ case OP_RowData: {
   pTos++;
   assert( i>=0 && i<p->nCursor );
   pC = p->apCsr[i];
+  assert( pC!=0 );
   if( pC->nullRow ){
     pTos->flags = MEM_Null;
   }else if( pC->pCursor!=0 ){
@@ -3370,6 +3380,7 @@ case OP_Recno: {
 
   assert( i>=0 && i<p->nCursor );
   pC = p->apCsr[i];
+  assert( pC!=0 );
   sqlite3VdbeCursorMoveto(pC);
   pTos++;
   if( pC->recnoIsValid ){
@@ -3405,9 +3416,10 @@ case OP_FullKey: {
   BtCursor *pCrsr;
   Cursor *pC;
 
+  assert( i>=0 && i<p->nCursor );
+  assert( p->apCsr[i]!=0 );
   assert( p->apCsr[i]->keyAsData );
   assert( !p->apCsr[i]->pseudoTable );
-  assert( i>=0 && i<p->nCursor );
   pTos++;
   if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
     u64 amt;
@@ -3448,6 +3460,7 @@ case OP_NullRow: {
 
   assert( i>=0 && i<p->nCursor );
   pC = p->apCsr[i];
+  assert( pC!=0 );
   pC->nullRow = 1;
   pC->recnoIsValid = 0;
   break;
@@ -3468,6 +3481,7 @@ case OP_Last: {
 
   assert( i>=0 && i<p->nCursor );
   pC = p->apCsr[i];
+  assert( pC!=0 );
   if( (pCrsr = pC->pCursor)!=0 ){
     int res;
     rc = sqlite3BtreeLast(pCrsr, &res);
@@ -3499,6 +3513,7 @@ case OP_Rewind: {
 
   assert( i>=0 && i<p->nCursor );
   pC = p->apCsr[i];
+  assert( pC!=0 );
   if( (pCrsr = pC->pCursor)!=0 ){
     rc = sqlite3BtreeFirst(pCrsr, &res);
     pC->atFirst = res==0;
@@ -3538,6 +3553,7 @@ case OP_Next: {
   CHECK_FOR_INTERRUPT;
   assert( pOp->p1>=0 && pOp->p1<p->nCursor );
   pC = p->apCsr[pOp->p1];
+  assert( pC!=0 );
   if( (pCrsr = pC->pCursor)!=0 ){
     int res;
     if( pC->nullRow ){
@@ -3577,6 +3593,7 @@ case OP_IdxPut: {
   BtCursor *pCrsr;
   assert( pTos>=p->aStack );
   assert( i>=0 && i<p->nCursor );
+  assert( p->apCsr[i]!=0 );
   assert( pTos->flags & MEM_Blob );
   if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
     int nKey = pTos->n;
@@ -3629,6 +3646,7 @@ case OP_IdxDelete: {
   assert( pTos>=p->aStack );
   assert( pTos->flags & MEM_Blob );
   assert( i>=0 && i<p->nCursor );
+  assert( p->apCsr[i]!=0 );
   if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
     int rx, res;
     rx = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, &res);
@@ -3657,6 +3675,7 @@ case OP_IdxRecno: {
   Cursor *pC;
 
   assert( i>=0 && i<p->nCursor );
+  assert( p->apCsr[i]!=0 );
   pTos++;
   if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
     i64 rowid;
@@ -3763,6 +3782,7 @@ case OP_IdxGE: {
   Cursor *pC;
 
   assert( i>=0 && i<p->nCursor );
+  assert( p->apCsr[i]!=0 );
   assert( pTos>=p->aStack );
   if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
     int res, rc;
index 39f27c1f606a781883129d0de1007b69552971b9..cb4ac818d212c5e4b1de405bb92770dc484ea51f 100644 (file)
@@ -62,6 +62,7 @@ struct Cursor {
   BtCursor *pCursor;    /* The cursor structure of the backend */
   i64 lastRecno;        /* Last recno from a Next or NextIdx operation */
   i64 nextRowid;        /* Next rowid returned by OP_NewRowid */
+  Bool zeroed;          /* True if zeroed out and ready for reuse */
   Bool recnoIsValid;    /* True if lastRecno is valid */
   Bool keyAsData;       /* The OP_Column command works on key instead of data */
   Bool atFirst;         /* True if pointing to first entry */
@@ -352,7 +353,7 @@ struct Vdbe {
 /*
 ** Function prototypes
 */
-void sqlite3VdbeCleanupCursor(Cursor*);
+void sqlite3VdbeFreeCursor(Cursor*);
 void sqlite3VdbeSorterReset(Vdbe*);
 int sqlite3VdbeAggReset(sqlite *, Agg *, KeyInfo *);
 void sqlite3VdbeKeylistFree(Keylist*);
index fbf21483d823ecd32a7acdd23cbcedd512f6997e..7836f1330e3c2ccdaf466b19613aa9f01cddcafc 100644 (file)
@@ -826,7 +826,10 @@ void sqlite3VdbeKeylistFree(Keylist *p){
 ** Close a cursor and release all the resources that cursor happens
 ** to hold.
 */
-void sqlite3VdbeCleanupCursor(Cursor *pCx){
+void sqlite3VdbeFreeCursor(Cursor *pCx){
+  if( pCx==0 ){
+    return;
+  }
   if( pCx->pCursor ){
     sqlite3BtreeCloseCursor(pCx->pCursor);
   }
@@ -835,7 +838,7 @@ void sqlite3VdbeCleanupCursor(Cursor *pCx){
   }
   sqliteFree(pCx->pData);
   sqliteFree(pCx->aType);
-  memset(pCx, 0, sizeof(*pCx));
+  sqliteFree(pCx);
 }
 
 /*
@@ -844,9 +847,7 @@ void sqlite3VdbeCleanupCursor(Cursor *pCx){
 static void closeAllCursors(Vdbe *p){
   int i;
   for(i=0; i<p->nCursor; i++){
-    Cursor *pC = p->apCsr[i];
-    sqlite3VdbeCleanupCursor(pC);
-    sqliteFree(pC);
+    sqlite3VdbeFreeCursor(p->apCsr[i]);
   }
   sqliteFree(p->apCsr);
   p->apCsr = 0;