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:
16
manifest
16
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
|
||||
|
||||
@@ -1 +1 @@
|
||||
f687977a28eda5ce0aa1cba2fdfb0152443032bc
|
||||
e42316f5708de6f639b7b54e08d4be73b45367e9
|
||||
80
src/vdbe.c
80
src/vdbe.c
@@ -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,25 +271,28 @@ 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]);
|
||||
}
|
||||
p->apCsr[iCur] = pCx = sqliteMalloc( sizeof(Cursor) );
|
||||
return pCx;
|
||||
}
|
||||
|
||||
/*
|
||||
** Apply any conversion required by the supplied column affinity to
|
||||
@@ -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;
|
||||
|
||||
@@ -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*);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user