1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-12 13:01:09 +03:00

Speed up in the handling of VDBE cursors. (CVS 1578)

FossilOrigin-Name: e42316f5708de6f639b7b54e08d4be73b45367e9
This commit is contained in:
drh
2004-06-12 20:12:51 +00:00
parent e61cffc203
commit 4774b13029
5 changed files with 66 additions and 44 deletions

View File

@@ -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

View File

@@ -1 +1 @@
f687977a28eda5ce0aa1cba2fdfb0152443032bc
e42316f5708de6f639b7b54e08d4be73b45367e9

View 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.
** Allocate cursor number iCur. Return a pointer to it. Return NULL
** if we run out of memory.
*/
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;
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;

View 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*);

View 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;