-C More\sspeed\simprovements.\s(CVS\s1381)
-D 2004-05-14T19:08:18
+C Cache\srecord\sheaders\sin\sthe\sOP_Column\sopcode.\s(CVS\s1382)
+D 2004-05-14T21:12:23
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
F src/attach.c c315c58cb16fd6e913b3bfa6412aedecb4567fa5
F src/auth.c 5c2f0bea4729c98c2be3b69d6b466fc51448fe79
-F src/btree.c c263f1f26b28e0ac929b9807bccf50877335c1b8
+F src/btree.c 731695f701be37c20146b0aaaf415135f01b6deb
F src/btree.h 6f51ad0ffebfba71295fcacdbe86007512200050
F src/btree_rb.c 9d7973e266ee6f9c61ce592f68742ce9cd5b10e5
F src/build.c e93f443a20eab57ffb77ff6244b1e09a1f7d9390
F src/utf.c fc799748d43fe1982d157b871e3e420a19c85d4f
F src/util.c f9511ffba78e6cf71a28774c2820d7750b5bacdf
F src/vacuum.c c134702e023db8778e6be59ac0ea7b02315b5476
-F src/vdbe.c fff79c08b3063d8d6f7b600fc6896c255c72238c
+F src/vdbe.c 90018d7938d36daec5caf3fb4c3833bcd803b061
F src/vdbe.h 94457ca73bae972dc61bca33a4dccc2e6e14e2f8
-F src/vdbeInt.h 03f4c3642482570a697a42a9bbb12908c6535bbe
-F src/vdbeaux.c 6cf897c49c1fde153d8b9e4c168714207f07cce3
+F src/vdbeInt.h 6740a3b80d437e9a6b3710aead703690fc0d1ddc
+F src/vdbeaux.c 38f924db0aa31c13d556bd65ad129d6f5d8c0a27
F src/where.c 6957bbd333cc7ffa7b3878adbe67a095319daa54
F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
F test/attach.test cb9b884344e6cfa5e165965d5b1adea679a24c83
F test/join2.test c97e4c5aa65dea462145529e58212a709b4722b8
F test/lastinsert.test 31382f88b9b0270333ac9e4a17f2c2f4732da718
F test/laststmtchanges.test cabd11bdfbaf73a4486c50b58297d9c2038ccc18
-F test/limit.test e28ce938ddacefdff860d082be45e1e5e2801441
+F test/limit.test 94c5dca1e81b7503ce90262ec5a2dc6c4e38d313
F test/lock.test 226ef831dad60ad4d200dc83e25479ba952aac7e
F test/main.test 6a851b5992c4881a725a3d9647e629199df8de9d
F test/malloc.test 2cfcffb7c858640e01e6520ee1cd54ca57d98e80
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P d4e0933dc72b66157164610e0b03f339bc535fb9
-R 9330d9bd11be003784ef684f1b9c1f25
+P cf75cac9b6bd43e60c6e25042b194ec5c60e5671
+R 1c44996f87c60027ab5d6785ca9e8bee
U drh
-Z 185a62bf4f1e1cc9ef6d8083626f74a6
+Z d44c78218fc520c849f4d72442c0d411
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.138 2004/05/14 19:08:18 drh Exp $
+** $Id: btree.c,v 1.139 2004/05/14 21:12:23 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
}
}
+/*
+** Make sure the BtCursor.info field of the given cursor is valid.
+*/
+static void getCellInfo(BtCursor *pCur){
+ MemPage *pPage = pCur->pPage;
+ if( !pCur->infoValid ){
+ parseCell(pPage, pPage->aCell[pCur->idx], &pCur->info);
+ pCur->infoValid = 1;
+ }else{
+#ifndef NDEBUG
+ CellInfo info;
+ parseCell(pPage, pPage->aCell[pCur->idx], &info);
+ assert( memcmp(&info, &pCur->info, sizeof(info))==0 );
+#endif
+ }
+}
+
/*
** Set *pSize to the size of the buffer needed to hold the value of
** the key for the current entry. If the cursor is not pointing
** itself, not the number of bytes in the key.
*/
int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){
- MemPage *pPage;
- unsigned char *cell;
-
if( !pCur->isValid ){
*pSize = 0;
}else{
- pPage = pCur->pPage;
- pageIntegrity(pPage);
- assert( pPage!=0 );
- assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
- cell = pPage->aCell[pCur->idx];
- cell += 2; /* Skip the offset to the next cell */
- if( !pPage->leaf ){
- cell += 4; /* Skip the child pointer */
- }
- if( pPage->hasData ){
- while( (0x80&*(cell++))!=0 ){} /* Skip the data size number */
- }
- getVarint(cell, pSize);
+ getCellInfo(pCur);
+ *pSize = pCur->info.nKey;
}
return SQLITE_OK;
}
** the database is empty) then *pSize is set to 0.
*/
int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){
- MemPage *pPage;
- unsigned char *cell;
-
if( !pCur->isValid ){
/* Not pointing at a valid entry - set *pSize to 0. */
*pSize = 0;
}else{
- pPage = pCur->pPage;
- assert( pPage!=0 );
- assert( pPage->isInit );
- pageIntegrity(pPage);
- if( !pPage->hasData ){
- *pSize = 0;
- }else{
- assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
- cell = pPage->aCell[pCur->idx];
- cell += 2; /* Skip the offset to the next cell */
- if( !pPage->leaf ){
- cell += 4; /* Skip the child pointer */
- }
- getVarint32(cell, pSize);
- }
+ getCellInfo(pCur);
+ *pSize = pCur->info.nData;
}
return SQLITE_OK;
}
pageIntegrity(pPage);
assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
aPayload = pPage->aCell[pCur->idx];
- if( !pCur->infoValid ){
- parseCell(pPage, aPayload, &pCur->info);
- pCur->infoValid = 1;
- }else{
-#ifndef NDEBUG
- CellInfo info;
- parseCell(pPage, aPayload, &info);
- assert( memcmp(&info, &pCur->info, sizeof(info))==0 );
-#endif
- }
+ getCellInfo(pCur);
aPayload += pCur->info.nHeader;
if( pPage->intKey ){
nKey = 0;
pageIntegrity(pPage);
assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
aPayload = pPage->aCell[pCur->idx];
- if( !pCur->infoValid ){
- parseCell(pPage, aPayload, &pCur->info);
- pCur->infoValid = 1;
- }else{
-#ifndef NDEBUG
- CellInfo info;
- parseCell(pPage, aPayload, &info);
- assert( memcmp(&info, &pCur->info, sizeof(info))==0 );
-#endif
- }
+ getCellInfo(pCur);
aPayload += pCur->info.nHeader;
if( pPage->intKey ){
nKey = 0;
** 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.291 2004/05/14 15:27:29 drh Exp $
+** $Id: vdbe.c,v 1.292 2004/05/14 21:12:23 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
break;
}
-/* Opcode: Column3 P1 P2 *
-**
-** This opcode (not yet in use) is a replacement for the current OP_Column3
-** that supports the SQLite3 manifest typing feature.
+/* Opcode: Column P1 P2 *
**
** Interpret the data that cursor P1 points to as a structure built using
** the MakeRecord instruction. (See the MakeRecord opcode for additional
char *zData;
int freeZdata = 0; /* zData requires sqliteFree() */
- u64 nFields; /* number of fields in the record */
- u64 *aTypes; /* An array of serial types (size nFields) */
+ u64 nField; /* number of fields in the record */
int len; /* The length of the serialized data for the column */
int offset;
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 ){
sqlite3VdbeCursorMoveto(pC);
zRec = 0;
pCrsr = pC->pCursor;
if( pC->nullRow ){
payloadSize = 0;
+ }else if( pC->cacheValid ){
+ payloadSize = pC->payloadSize;
}else if( pC->keyAsData ){
i64 payloadSize64;
sqlite3BtreeKeySize(pCrsr, &payloadSize64);
}else if( pC->pseudoTable ){
payloadSize = pC->nData;
zRec = pC->pData;
+ pC->cacheValid = 0;
assert( payloadSize==0 || zRec!=0 );
}else{
payloadSize = 0;
break;
}
- /* Read the number of fields for the record.
- ** FIX ME: The Cursor object should cache this data and the array of
- ** field types for subsequent OP_Column instructions.
+ /* Read and parse the table header. Store the results of the parse
+ ** into the record header cache fields of the cursor.
*/
- if( zRec ){
- zData = zRec;
- }else{
- /* We can assume that 9 bytes (maximum length of a varint) fits
- ** on the main page in all cases.
- */
- if( pC->keyAsData ){
- zData = (char *)sqlite3BtreeKeyFetch(pCrsr, 9>payloadSize?payloadSize:9);
+ if( !pC->cacheValid ){
+ pC->payloadSize = payloadSize;
+ if( zRec ){
+ zData = zRec;
}else{
- zData = (char *)sqlite3BtreeDataFetch(pCrsr, 9>payloadSize?payloadSize:9);
- }
- assert( zData );
- }
- offset = sqlite3GetVarint(zData, &nFields);
-
- if( !zRec ){
- /* If the record is stored in a table, see if enough of it is on
- ** the main page to use sqlite3BtreeDataFetch() to get the data
- ** containing the nFields serial types (varints). This will almost
- ** always work, but if it doesn't sqliteMalloc() space and use
- ** sqlite3BtreeData().
- **
- ** Estimate the maximum space required by the nFields varints by
- ** assuming the maximum space for each is the length required to store:
- **
- ** (<record length> * 2) + 13
- **
- ** This is the serial-type for a text object as long as the record
- ** itself. In all cases the length required to store this is three
- ** bytes or less.
- */
- int max_space = sqlite3VarintLen((((u64)payloadSize)<<1)+13)*nFields;
- max_space += offset;
- if( max_space>payloadSize ){
- max_space = payloadSize;
+ /* We can assume that 9 bytes (maximum length of a varint) fits
+ ** on the main page in all cases.
+ */
+ int n = 9;
+ if( payloadSize<9 ) n = payloadSize;
+ if( pC->keyAsData ){
+ zData = (char *)sqlite3BtreeKeyFetch(pCrsr, n);
+ }else{
+ zData = (char *)sqlite3BtreeDataFetch(pCrsr, n);
+ }
+ assert( zData );
}
-
- if( pC->keyAsData ){
- zData = (char *)sqlite3BtreeKeyFetch(pCrsr, max_space);
- }else{
- zData = (char *)sqlite3BtreeDataFetch(pCrsr, max_space);
+ offset = sqlite3GetVarint(zData, &nField);
+ if( nField>pC->nField ){
+ sqliteFree(pC->aType);
+ pC->aType = sqliteMallocRaw( nField*sizeof(pC->aType[0]) );
+ if( pC->aType==0 ){
+ goto no_mem;
+ }
}
- if( !zData ){
- /* This code will run very infrequently (e.g. tables with several
- ** hundred columns).
+ pC->nField = nField;
+
+ if( !zRec ){
+ /* If the record is stored in a table, see if enough of it is on
+ ** the main page to use sqlite3BtreeDataFetch() to get the data
+ ** containing the nField serial types (varints). This will almost
+ ** always work, but if it doesn't sqliteMalloc() space and use
+ ** sqlite3BtreeData().
+ **
+ ** Estimate the maximum space required by the nField varints by
+ ** assuming the maximum space for each is the length required to store:
+ **
+ ** (<record length> * 2) + 13
+ **
+ ** This is the serial-type for a text object as long as the record
+ ** itself. In all cases the length required to store this is three
+ ** bytes or less.
*/
- zData = (char *)sqliteMallocRaw(offset+max_space);
- if( !zData ){
- rc = SQLITE_NOMEM;
- goto abort_due_to_error;
+ int max_space = sqlite3VarintLen((((u64)payloadSize)<<1)+13)*nField;
+ max_space += offset;
+ if( max_space>payloadSize ){
+ max_space = payloadSize;
}
+
if( pC->keyAsData ){
- rc = sqlite3BtreeKey(pCrsr, 0, max_space, zData);
+ zData = (char *)sqlite3BtreeKeyFetch(pCrsr, max_space);
}else{
- rc = sqlite3BtreeData(pCrsr, 0, max_space, zData);
+ zData = (char *)sqlite3BtreeDataFetch(pCrsr, max_space);
}
- if( rc!=SQLITE_OK ){
- sqliteFree(zData);
- goto abort_due_to_error;
+ if( !zData ){
+ /* This code will run very infrequently (e.g. tables with several
+ ** hundred columns).
+ */
+ zData = (char *)sqliteMallocRaw(max_space);
+ if( !zData ){
+ goto no_mem;
+ }
+ if( pC->keyAsData ){
+ rc = sqlite3BtreeKey(pCrsr, 0, max_space, zData);
+ }else{
+ rc = sqlite3BtreeData(pCrsr, 0, max_space, zData);
+ }
+ if( rc!=SQLITE_OK ){
+ sqliteFree(zData);
+ goto abort_due_to_error;
+ }
+ freeZdata = 1;
}
- freeZdata = 1;
}
- }
- /* Dynamically allocate space for the aTypes array. and read all
- ** the serial types for the record. At the end of this block variable
- ** offset is set to the offset to the start of Data0 in the record.
- */
- aTypes = (u64 *)sqliteMallocRaw(sizeof(u64)*nFields);
- if( !aTypes ){
+ /* Read all the serial types for the record. At the end of this block
+ ** variable offset is set to the offset to the start of Data0 in the record.
+ */
+ for(nn=0; nn<nField; nn++){
+ offset += sqlite3GetVarint(&zData[offset], &pC->aType[nn]);
+ }
if( freeZdata ){
- sqliteFree(zData);
freeZdata = 0;
+ sqliteFree(zData);
}
- rc = SQLITE_NOMEM;
- goto abort_due_to_error;
- }
- for(nn=0; nn<nFields; nn++){
- offset += sqlite3GetVarint(&zData[offset], &aTypes[nn]);
- }
-
- if( freeZdata ){
- freeZdata = 0;
- sqliteFree(zData);
+ pC->nHeader = offset;
+ pC->cacheValid = 1;
}
+ /* Compute the offset from the beginning of the record to the beginning
+ ** of the data. And get the length of the data.
+ */
+ offset = pC->nHeader;
for(nn=0; nn<p2; nn++){
- offset += sqlite3VdbeSerialTypeLen(aTypes[nn]);
+ offset += sqlite3VdbeSerialTypeLen(pC->aType[nn]);
}
- len = sqlite3VdbeSerialTypeLen(aTypes[p2]);
+ len = sqlite3VdbeSerialTypeLen(pC->aType[p2]);
if( !zRec ){
/* If the record is stored in a table, see if enough of it
}else{
zData = (char *)sqlite3BtreeDataFetch(pCrsr, offset+len);
}
- if( !zData && len>0 ){
+ if( !zData ){
zData = (char *)sqliteMallocRaw(len);
if( !zData ){
- sqliteFree(aTypes);
- rc = SQLITE_NOMEM;
- goto abort_due_to_error;
+ goto no_mem;
}
if( pC->keyAsData ){
rc = sqlite3BtreeKey(pCrsr, offset, len, zData);
rc = sqlite3BtreeData(pCrsr, offset, len, zData);
}
if( rc!=SQLITE_OK ){
- sqliteFree( aTypes );
sqliteFree( zData );
goto abort_due_to_error;
}
}
/* Deserialize the value directly into the top of the stack */
- sqlite3VdbeSerialGet(&zData[offset], aTypes[p2], pTos);
+ sqlite3VdbeSerialGet(&zData[offset], pC->aType[p2], pTos);
- sqliteFree(aTypes);
if( freeZdata ){
sqliteFree(zData);
}
pC->recnoIsValid = 0;
}
pC->deferredMoveto = 0;
+ pC->cacheValid = 0;
pC->incrKey = 0;
sqlite3_search_count++;
oc = pOp->opcode;
rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
alreadyExists = rx==SQLITE_OK && res==0;
pC->deferredMoveto = 0;
+ pC->cacheValid = 0;
}
if( pOp->opcode==OP_Found ){
if( alreadyExists ) pc = pOp->p2 - 1;
/* Search for an entry in P1 where all but the last four bytes match K.
** If there is no such entry, jump immediately to P2.
*/
- assert( p->aCsr[i].deferredMoveto==0 );
+ assert( pCx->deferredMoveto==0 );
+ pCx->cacheValid = 0;
rc = sqlite3BtreeMoveto(pCrsr, zKey, len, &res);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
if( res<0 ){
*/
case OP_NotExists: {
int i = pOp->p1;
+ Cursor *pC;
BtCursor *pCrsr;
assert( pTos>=p->aStack );
assert( i>=0 && i<p->nCursor );
- if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
+ if( (pCrsr = (pC = &p->aCsr[i])->pCursor)!=0 ){
int res, rx;
u64 iKey;
assert( pTos->flags & MEM_Int );
assert( p->aCsr[i].intKey );
iKey = intToKey(pTos->i);
rx = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res);
- p->aCsr[i].lastRecno = pTos->i;
- p->aCsr[i].recnoIsValid = res==0;
- p->aCsr[i].nullRow = 0;
+ pC->lastRecno = pTos->i;
+ pC->recnoIsValid = res==0;
+ pC->nullRow = 0;
+ pC->cacheValid = 0;
if( rx!=SQLITE_OK || res!=0 ){
pc = pOp->p2 - 1;
- p->aCsr[i].recnoIsValid = 0;
+ pC->recnoIsValid = 0;
}
}
Release(pTos);
}
pC->recnoIsValid = 0;
pC->deferredMoveto = 0;
+ pC->cacheValid = 0;
}
pTos++;
pTos->i = v;
}
pC->recnoIsValid = 0;
pC->deferredMoveto = 0;
+ pC->cacheValid = 0;
}
popStack(&pTos, 2);
break;
sqlite3VdbeCursorMoveto(pC);
rc = sqlite3BtreeDelete(pC->pCursor);
pC->nextRowidValid = 0;
+ pC->cacheValid = 0;
}
if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++;
if( pOp->p2 & OPFLAG_CSCHANGE ) db->csChange++;
rc = sqlite3BtreeLast(pCrsr, &res);
pC->nullRow = res;
pC->deferredMoveto = 0;
+ pC->cacheValid = 0;
if( res && pOp->p2>0 ){
pc = pOp->p2 - 1;
}
rc = sqlite3BtreeFirst(pCrsr, &res);
pC->atFirst = res==0;
pC->deferredMoveto = 0;
+ pC->cacheValid = 0;
}else{
res = 1;
}
rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(pCrsr, &res) :
sqlite3BtreePrevious(pCrsr, &res);
pC->nullRow = res;
+ pC->cacheValid = 0;
}
if( res==0 ){
pc = pOp->p2 - 1;
*/
case OP_IdxPut: {
int i = pOp->p1;
+ Cursor *pC;
BtCursor *pCrsr;
assert( pTos>=p->aStack );
assert( i>=0 && i<p->nCursor );
assert( pTos->flags & MEM_Str );
- if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
+ if( (pCrsr = (pC = &p->aCsr[i])->pCursor)!=0 ){
int nKey = pTos->n;
const char *zKey = pTos->z;
if( pOp->p2 ){
int c;
sqlite3BtreeKeySize(pCrsr, &n);
if( n==nKey &&
- sqlite3VdbeIdxKeyCompare(&p->aCsr[i], len, zKey, 0, &c)==SQLITE_OK
+ sqlite3VdbeIdxKeyCompare(pC, len, zKey, 0, &c)==SQLITE_OK
&& c==0
){
rc = SQLITE_CONSTRAINT;
}
}
}
- assert( p->aCsr[i].intKey==0 );
+ assert( pC->intKey==0 );
rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0);
- assert( p->aCsr[i].deferredMoveto==0 );
+ assert( pC->deferredMoveto==0 );
+ pC->cacheValid = 0;
}
Release(pTos);
pTos--;
*/
case OP_IdxDelete: {
int i = pOp->p1;
+ Cursor *pC;
BtCursor *pCrsr;
assert( pTos>=p->aStack );
assert( pTos->flags & MEM_Str );
assert( i>=0 && i<p->nCursor );
- if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
+ if( (pCrsr = (pC = &p->aCsr[i])->pCursor)!=0 ){
int rx, res;
rx = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, &res);
if( rx==SQLITE_OK && res==0 ){
rc = sqlite3BtreeDelete(pCrsr);
}
- assert( p->aCsr[i].deferredMoveto==0 );
+ assert( pC->deferredMoveto==0 );
+ pC->cacheValid = 0;
}
Release(pTos);
pTos--;