Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -41,11 +41,11 @@ ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** 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.292 2004/05/14 21:12:23 drh Exp $ +** $Id: vdbe.c,v 1.293 2004/05/14 21:59:40 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include #include "vdbeInt.h" @@ -411,15 +411,17 @@ ** If a memory allocation error occurs, return 1. Return 0 if ** everything works. */ static int expandCursorArraySize(Vdbe *p, int mxCursor){ if( mxCursor>=p->nCursor ){ - Cursor *aCsr = sqliteRealloc( p->aCsr, (mxCursor+1)*sizeof(Cursor) ); - if( aCsr==0 ) return 1; - p->aCsr = aCsr; - memset(&p->aCsr[p->nCursor], 0, sizeof(Cursor)*(mxCursor+1-p->nCursor)); - p->nCursor = mxCursor+1; + 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; + } } return 0; } /* @@ -560,13 +562,10 @@ #endif #ifndef SQLITE_OMIT_PROGRESS_CALLBACK int nProgressOps = 0; /* Opcodes executed since progress callback. */ #endif - /* FIX ME. */ - expandCursorArraySize(p, 100); - if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE; assert( db->magic==SQLITE_MAGIC_BUSY ); assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY ); p->rc = SQLITE_OK; assert( p->explain==0 ); @@ -1919,11 +1918,11 @@ assert( &pTos[i]>=p->aStack ); assert( pTos[i].flags & MEM_Str ); zRec = pTos[i].z; payloadSize = pTos[i].n; pC->cacheValid = 0; - }else if( (pC = &p->aCsr[i])->pCursor!=0 ){ + }else if( (pC = p->apCsr[i])->pCursor!=0 ){ sqlite3VdbeCursorMoveto(pC); zRec = 0; pCrsr = pC->pCursor; if( pC->nullRow ){ payloadSize = 0; @@ -2621,13 +2620,12 @@ break; } } assert( i>=0 ); if( expandCursorArraySize(p, i) ) goto no_mem; - pCur = &p->aCsr[i]; + pCur = p->apCsr[i]; sqlite3VdbeCleanupCursor(pCur); - memset(pCur, 0, sizeof(Cursor)); pCur->nullRow = 1; if( pX==0 ) break; do{ /* When opening cursors, always supply the comparison function ** sqlite3VdbeKeyCompare(). If the table being opened is of type @@ -2689,11 +2687,11 @@ case OP_OpenTemp: { int i = pOp->p1; Cursor *pCx; assert( i>=0 ); if( expandCursorArraySize(p, i) ) goto no_mem; - pCx = &p->aCsr[i]; + pCx = p->apCsr[i]; sqlite3VdbeCleanupCursor(pCx); memset(pCx, 0, sizeof(*pCx)); pCx->nullRow = 1; rc = sqlite3BtreeFactory(db, 0, 1, TEMP_PAGES, &pCx->pBt); @@ -2734,11 +2732,11 @@ case OP_OpenPseudo: { int i = pOp->p1; Cursor *pCx; assert( i>=0 ); if( expandCursorArraySize(p, i) ) goto no_mem; - pCx = &p->aCsr[i]; + pCx = p->apCsr[i]; sqlite3VdbeCleanupCursor(pCx); memset(pCx, 0, sizeof(*pCx)); pCx->nullRow = 1; pCx->pseudoTable = 1; break; @@ -2750,11 +2748,11 @@ ** currently open, this instruction is a no-op. */ case OP_Close: { int i = pOp->p1; if( i>=0 && inCursor ){ - sqlite3VdbeCleanupCursor(&p->aCsr[i]); + sqlite3VdbeCleanupCursor(p->apCsr[i]); } break; } /* Opcode: MoveTo P1 P2 * @@ -2793,11 +2791,11 @@ int i = pOp->p1; Cursor *pC; assert( pTos>=p->aStack ); assert( i>=0 && inCursor ); - pC = &p->aCsr[i]; + pC = p->apCsr[i]; if( pC->pCursor!=0 ){ int res, oc; pC->nullRow = 0; if( pC->intKey ){ i64 iKey; @@ -2893,11 +2891,11 @@ int i = pOp->p1; int alreadyExists = 0; Cursor *pC; assert( pTos>=p->aStack ); assert( i>=0 && inCursor ); - if( (pC = &p->aCsr[i])->pCursor!=0 ){ + if( (pC = p->apCsr[i])->pCursor!=0 ){ int res, rx; assert( pC->intKey==0 ); Stringify(pTos); rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res); alreadyExists = rx==SQLITE_OK && res==0; @@ -2948,11 +2946,11 @@ assert( pNos>=p->aStack ); Integerify(pTos); R = pTos->i; pTos--; assert( i>=0 && i<=p->nCursor ); - pCx = &p->aCsr[i]; + pCx = p->apCsr[i]; pCrsr = pCx->pCursor; if( pCrsr!=0 ){ int res, rc; i64 v; /* The record number on the P1 entry that matches K */ char *zKey; /* The value of K */ @@ -3032,15 +3030,15 @@ int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; assert( pTos>=p->aStack ); assert( i>=0 && inCursor ); - if( (pCrsr = (pC = &p->aCsr[i])->pCursor)!=0 ){ + if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int res, rx; u64 iKey; assert( pTos->flags & MEM_Int ); - assert( p->aCsr[i].intKey ); + assert( p->apCsr[i]->intKey ); iKey = intToKey(pTos->i); rx = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res); pC->lastRecno = pTos->i; pC->recnoIsValid = res==0; pC->nullRow = 0; @@ -3065,11 +3063,11 @@ case OP_NewRecno: { int i = pOp->p1; i64 v = 0; Cursor *pC; assert( i>=0 && inCursor ); - if( (pC = &p->aCsr[i])->pCursor==0 ){ + if( (pC = p->apCsr[i])->pCursor==0 ){ /* The zero initialization above is all that is needed */ }else{ /* The next rowid or record number (different terms for the same ** thing) is obtained in a two-step algorithm. ** @@ -3193,11 +3191,11 @@ Mem *pNos = &pTos[-1]; int i = pOp->p1; Cursor *pC; assert( pNos>=p->aStack ); assert( i>=0 && inCursor ); - if( ((pC = &p->aCsr[i])->pCursor!=0 || pC->pseudoTable) ){ + if( ((pC = p->apCsr[i])->pCursor!=0 || pC->pseudoTable) ){ char *zKey; i64 nKey; i64 iKey; if( pOp->opcode==OP_PutStrKey ){ Stringify(pNos); @@ -3280,11 +3278,11 @@ */ case OP_Delete: { int i = pOp->p1; Cursor *pC; assert( i>=0 && inCursor ); - pC = &p->aCsr[i]; + pC = p->apCsr[i]; if( pC->pCursor!=0 ){ sqlite3VdbeCursorMoveto(pC); rc = sqlite3BtreeDelete(pC->pCursor); pC->nextRowidValid = 0; pC->cacheValid = 0; @@ -3313,11 +3311,11 @@ ** processing compound selects. */ case OP_KeyAsData: { int i = pOp->p1; assert( i>=0 && inCursor ); - p->aCsr[i].keyAsData = pOp->p2; + p->apCsr[i]->keyAsData = pOp->p2; break; } /* Opcode: RowData P1 * * ** @@ -3343,11 +3341,11 @@ Cursor *pC; int n; pTos++; assert( i>=0 && inCursor ); - pC = &p->aCsr[i]; + pC = p->apCsr[i]; if( pC->nullRow ){ pTos->flags = MEM_Null; }else if( pC->pCursor!=0 ){ BtCursor *pCrsr = pC->pCursor; sqlite3VdbeCursorMoveto(pC); @@ -3398,11 +3396,11 @@ int i = pOp->p1; Cursor *pC; i64 v; assert( i>=0 && inCursor ); - pC = &p->aCsr[i]; + pC = p->apCsr[i]; sqlite3VdbeCursorMoveto(pC); pTos++; if( pC->recnoIsValid ){ v = pC->lastRecno; }else if( pC->pseudoTable ){ @@ -3432,21 +3430,22 @@ ** This opcode may not be used on a pseudo-table. */ case OP_FullKey: { int i = pOp->p1; BtCursor *pCrsr; + Cursor *pC; - assert( p->aCsr[i].keyAsData ); - assert( !p->aCsr[i].pseudoTable ); + assert( p->apCsr[i]->keyAsData ); + assert( !p->apCsr[i]->pseudoTable ); assert( i>=0 && inCursor ); pTos++; - if( (pCrsr = p->aCsr[i].pCursor)!=0 ){ + if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ u64 amt; char *z; - sqlite3VdbeCursorMoveto(&p->aCsr[i]); - assert( p->aCsr[i].intKey==0 ); + sqlite3VdbeCursorMoveto(pC); + assert( pC->intKey==0 ); sqlite3BtreeKeySize(pCrsr, &amt); if( amt<=0 ){ rc = SQLITE_CORRUPT; goto abort_due_to_error; } @@ -3471,14 +3470,16 @@ ** that occur while the cursor is on the null row will always push ** a NULL onto the stack. */ case OP_NullRow: { int i = pOp->p1; + Cursor *pC; assert( i>=0 && inCursor ); - p->aCsr[i].nullRow = 1; - p->aCsr[i].recnoIsValid = 0; + pC = p->apCsr[i]; + pC->nullRow = 1; + pC->recnoIsValid = 0; break; } /* Opcode: Last P1 P2 * ** @@ -3492,11 +3493,11 @@ int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; assert( i>=0 && inCursor ); - pC = &p->aCsr[i]; + pC = p->apCsr[i]; if( (pCrsr = pC->pCursor)!=0 ){ int res; rc = sqlite3BtreeLast(pCrsr, &res); pC->nullRow = res; pC->deferredMoveto = 0; @@ -3523,11 +3524,11 @@ Cursor *pC; BtCursor *pCrsr; int res; assert( i>=0 && inCursor ); - pC = &p->aCsr[i]; + pC = p->apCsr[i]; if( (pCrsr = pC->pCursor)!=0 ){ rc = sqlite3BtreeFirst(pCrsr, &res); pC->atFirst = res==0; pC->deferredMoveto = 0; pC->cacheValid = 0; @@ -3562,11 +3563,11 @@ Cursor *pC; BtCursor *pCrsr; CHECK_FOR_INTERRUPT; assert( pOp->p1>=0 && pOp->p1nCursor ); - pC = &p->aCsr[pOp->p1]; + pC = p->apCsr[pOp->p1]; if( (pCrsr = pC->pCursor)!=0 ){ int res; if( pC->nullRow ){ res = 1; }else{ @@ -3603,11 +3604,11 @@ Cursor *pC; BtCursor *pCrsr; assert( pTos>=p->aStack ); assert( i>=0 && inCursor ); assert( pTos->flags & MEM_Str ); - if( (pCrsr = (pC = &p->aCsr[i])->pCursor)!=0 ){ + if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int nKey = pTos->n; const char *zKey = pTos->z; if( pOp->p2 ){ int res; int len; @@ -3660,11 +3661,11 @@ Cursor *pC; BtCursor *pCrsr; assert( pTos>=p->aStack ); assert( pTos->flags & MEM_Str ); assert( i>=0 && inCursor ); - if( (pCrsr = (pC = &p->aCsr[i])->pCursor)!=0 ){ + if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int rx, res; rx = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, &res); if( rx==SQLITE_OK && res==0 ){ rc = sqlite3BtreeDelete(pCrsr); } @@ -3685,18 +3686,19 @@ ** See also: Recno, MakeIdxKey. */ case OP_IdxRecno: { int i = pOp->p1; BtCursor *pCrsr; + Cursor *pC; assert( i>=0 && inCursor ); pTos++; - if( (pCrsr = p->aCsr[i].pCursor)!=0 ){ + if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ i64 rowid; - assert( p->aCsr[i].deferredMoveto==0 ); - assert( p->aCsr[i].intKey==0 ); + assert( pC->deferredMoveto==0 ); + assert( pC->intKey==0 ); rc = sqlite3VdbeIdxRowid(pCrsr, &rowid); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } pTos->flags = MEM_Int; @@ -3767,19 +3769,19 @@ case OP_IdxLT: case OP_IdxGT: case OP_IdxGE: { int i= pOp->p1; BtCursor *pCrsr; + Cursor *pC; assert( i>=0 && inCursor ); assert( pTos>=p->aStack ); - if( (pCrsr = p->aCsr[i].pCursor)!=0 ){ + if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int res, rc; - Cursor *pC = &p->aCsr[i]; Stringify(pTos); - assert( p->aCsr[i].deferredMoveto==0 ); + assert( pC->deferredMoveto==0 ); if( pOp->p3 ){ pC->incrKey = 1; } rc = sqlite3VdbeIdxKeyCompare(pC, pTos->n, pTos->z, 0, &res); pC->incrKey = 0; Index: src/vdbeInt.h ================================================================== --- src/vdbeInt.h +++ src/vdbeInt.h @@ -263,12 +263,12 @@ int *aLabel; /* Space to hold the labels */ Mem *aStack; /* The operand stack, except string values */ Mem *pTos; /* Top entry in the operand stack */ char **zArgv; /* Text values used by the callback */ char **azColName; /* Becomes the 4th parameter to callbacks */ - int nCursor; /* Number of slots in aCsr[] */ - Cursor *aCsr; /* One element of this array for each open cursor */ + int nCursor; /* Number of slots in apCsr[] */ + Cursor **apCsr; /* One element of this array for each open cursor */ Sorter *pSort; /* A linked list of objects to be sorted */ FILE *pFile; /* At most one open file handler */ int nField; /* Number of file fields */ char **azField; /* Data for each file field */ int nVar; /* Number of entries in azVariable[] */ Index: src/vdbeaux.c ================================================================== --- src/vdbeaux.c +++ src/vdbeaux.c @@ -734,23 +734,25 @@ if( pCx->pBt ){ sqlite3BtreeClose(pCx->pBt); } sqliteFree(pCx->pData); sqliteFree(pCx->aType); - memset(pCx, 0, sizeof(Cursor)); + memset(pCx, 0, sizeof(*pCx)); } /* ** Close all cursors */ static void closeAllCursors(Vdbe *p){ int i; for(i=0; inCursor; i++){ - sqlite3VdbeCleanupCursor(&p->aCsr[i]); + Cursor *pC = p->apCsr[i]; + sqlite3VdbeCleanupCursor(pC); + sqliteFree(pC); } - sqliteFree(p->aCsr); - p->aCsr = 0; + sqliteFree(p->apCsr); + p->apCsr = 0; p->nCursor = 0; } /* ** Clean up the VM after execution.