-C Test\sstring\svalues\spassed\sto\sbind_text()\sand\sresult_text()\sfor\sa\snul-terminator.\s(CVS\s4915)
-D 2008-03-25T16:16:29
+C Modify\sthe\s{quote:\sIdxDelete}\sopcode\sso\sthat\sit\stakes\san\sarray\sof\sregisters\srather\r\nthan\sa\srecord\sformed\susing\s{quote:\sMakeRecord.}\s\sThis\savoids\sa\sneedless\spacking\r\nand\sunpacking\sof\sthe\srecord\sto\sbe\sdeleted.\s(CVS\s4916)
+D 2008-03-25T17:23:33
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
F Makefile.in cf434ce8ca902e69126ae0f94fc9f7dc7428a5fa
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
F src/bitvec.c 49817d442e51e4123585f3cf3c2afc293a3c91e2
F src/btmutex.c 483ced3c52205b04b97df69161fadbf87f4f1ea2
-F src/btree.c 366f5f66ebb3dfdc8513242d4aecbfb402dcc0a9
-F src/btree.h e02869e1e7753ad5b3c7cb7852e952c95c2e609a
+F src/btree.c 6e60d634d236232efbb289b800dd76e72a5ecf9d
+F src/btree.h c66cb17c6fffa84a88926dbef173bab4ae692fd4
F src/btreeInt.h d232be68a7ab2a24376dc6332a869e717551b0bd
-F src/build.c d0715b3454b140cb405412e3029ec7c0fb434efd
+F src/build.c 4e6321d112f0ed1070c579677573e4eb76cda1fd
F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
F src/date.c e41ce4513fb0e359dc678d6bddb4ace135fe365d
-F src/delete.c 526b783b71b9885b201d74720d44a386b971dc01
+F src/delete.c 3dc7d7cc46c8675219a7776b7c67b626bba530df
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
F src/expr.c 7e56d2a24af8137f4bebbfa1d7dd1dcf70107c88
F src/fault.c c28478c7190daef16be09d261c5461638b4d686c
F src/pager.c 22241b59c80ca083a96816df434adb8c097afcd4
F src/pager.h b1e2258f03878c14b06a95bfa362e8c5c9638170
F src/parse.y b0ee84d94218046ea88c2a6561005710d127ca7d
-F src/pragma.c f64eed914518c28d1863356163dea1e6f58e28f2
+F src/pragma.c 99cec6d99d0241436494aab15b05da97b0e70683
F src/prepare.c 185fb47f1fb3e45a345d523eb391d673f5eb367c
F src/printf.c 05d2b44d7b5b80c8a4a09108ddad9c20e254370d
F src/random.c 2b2db2de4ab491f5a14d3480466f8f4b5a5db74a
-F src/select.c c06849a0d0ad408fbdd8180439176e94aae43e56
+F src/select.c 831714d4f09f4b9f4be43d2399eff12dcf281c86
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
F src/shell.c 22297fffa6f00a6c6d44020fa13b1184a1bb372d
F src/sqlite.h.in 61d8d1cefcbf0803c03c2179be138a78bfd1d335
F src/sqlite3ext.h faacd0e6a81aabee0861c6d7883c9172e74ef5b3
-F src/sqliteInt.h 07b472437b2d7297c300f8b7cea5205984fa64d1
+F src/sqliteInt.h 50a9313829041721d34f20c8be4562c3197dcff9
F src/sqliteLimit.h eecbc288b410ae5565e71aaa4a439aae57bb0707
F src/table.c 2c48c575dd59b3a6c5c306bc55f51a9402cf429a
F src/tclsqlite.c 1367762764772a233643524c3585b4711a9adcda
F src/test1.c 342a2628310fa709074d979e695a28a3bb570834
F src/test2.c f0808cc643528b9620e4059ca9bda8346f526121
-F src/test3.c 31027a4a190d2f3c1e479ea2d750e696160bbf04
+F src/test3.c c715b5a8a6415d7b2c67f97c394eef488b6f7e63
F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071
F src/test5.c 3a6a5717a149d7ca2e6d14f5be72cf7555d54dc4
F src/test6.c 62281c0a9ac0265e579065942f7de4e080f8eb05
F src/utf.c 32b00d6e19010025e58f2ecb2f921d5e126771b4
F src/util.c dba9e04121eb17ec4643d6ca231ff859452cf0e2
F src/vacuum.c 3524411bfb58aac0d87eadd3e5b7cd532772af30
-F src/vdbe.c bdcbf54cf944a99b004e87a523736dd326fa34be
-F src/vdbe.h 0fef6798be121ed2b5a547a5cb85e0824ec3971f
-F src/vdbeInt.h 4bbec80d55d179ab8438ac9822416d9111638919
+F src/vdbe.c 0068703495a197e7b77dbdff604b42896722a1cc
+F src/vdbe.h ecca2e1c1ac1066f4e68ad38068a20ea32ea7063
+F src/vdbeInt.h 4d767f189a1d13ff8d4881de60aacc470e54f5b8
F src/vdbeapi.c b9e9d7a58690c1e1ae66de7232edccf4793ad817
-F src/vdbeaux.c c071014d81c1d4b2c381247c16a3e86182951e51
+F src/vdbeaux.c e45929a3b5e59e8f2d69b7d6164c9a636149e1df
F src/vdbeblob.c cc713c142c3d4952b380c98ee035f850830ddbdb
F src/vdbefifo.c a30c237b2a3577e1415fb6e288cbb6b8ed1e5736
F src/vdbemem.c d48a71d66a7afd564b6537ab7e7442f7729fa5af
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P fe1bc0f3b7cd87cd65f7d03b91095b59788a6f8d
-R 033bb4545035899c2c5396ecb143bb5f
-U danielk1977
-Z 09f5af34fae3a95557976f8d7d3936e3
+P 24c3ebc0c5c53c234516d16dce761d713fb29578
+R 66dfc33f9c0d1eba54064363b17cc27e
+U drh
+Z 040d5190ae2e9926a42f3065a9864529
-24c3ebc0c5c53c234516d16dce761d713fb29578
\ No newline at end of file
+ee381b43563e1b0637ee74389d076dff77deddf9
\ No newline at end of file
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.446 2008/03/25 14:24:57 danielk1977 Exp $
+** $Id: btree.c,v 1.447 2008/03/25 17:23:33 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
}
#endif
pCur->eState = CURSOR_INVALID;
- rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skip);
+ rc = sqlite3BtreeMoveto(pCur, pCur->pKey, 0, pCur->nKey, 0, &pCur->skip);
if( rc==SQLITE_OK ){
sqlite3_free(pCur->pKey);
pCur->pKey = 0;
return rc;
}
-/* Move the cursor so that it points to an entry near pKey/nKey.
-** Return a success code.
+/* Move the cursor so that it points to an entry near the key
+** specified by pKey/nKey/pUnKey. Return a success code.
**
-** For INTKEY tables, only the nKey parameter is used. pKey is
-** ignored. For other tables, nKey is the number of bytes of data
-** in pKey.
+** For INTKEY tables, only the nKey parameter is used. pKey
+** and pUnKey must be NULL. For index tables, either pUnKey
+** must point to a key that has already been unpacked, or else
+** pKey/nKey describes a blob containing the key.
**
** If an exact match is not found, then the cursor is always
** left pointing at a leaf page which would hold the entry if it
int sqlite3BtreeMoveto(
BtCursor *pCur, /* The cursor to be moved */
const void *pKey, /* The key content for indices. Not used by tables */
+ UnpackedRecord *pUnKey,/* Unpacked version of pKey */
i64 nKey, /* Size of pKey. Or the key for tables */
int biasRight, /* If true, bias the search to the high end */
int *pRes /* Search result flag */
){
int rc;
- VdbeParsedRecord *pPKey;
char aSpace[200];
assert( cursorHoldsMutex(pCur) );
return SQLITE_OK;
}
if( pCur->pPage->intKey ){
- pPKey = 0;
- }else{
- pPKey = sqlite3VdbeRecordParse(pCur->pKeyInfo, nKey, pKey,
+ /* We are given an SQL table to search. The key is the integer
+ ** rowid contained in nKey. pKey and pUnKey should both be NULL */
+ assert( pUnKey==0 );
+ assert( pKey==0 );
+ }else if( pUnKey==0 ){
+ /* We are to search an SQL index using a key encoded as a blob.
+ ** The blob is found at pKey and is nKey bytes in length. Unpack
+ ** this key so that we can use it. */
+ assert( pKey!=0 );
+ pUnKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, nKey, pKey,
aSpace, sizeof(aSpace));
- if( pPKey==0 ) return SQLITE_NOMEM;
+ if( pUnKey==0 ) return SQLITE_NOMEM;
+ }else{
+ /* We are to search an SQL index using a key that is already unpacked
+ ** and handed to us in pUnKey. */
+ assert( pKey==0 );
}
for(;;){
int lwr, upr;
int c = -1; /* pRes return if table is empty must be -1 */
lwr = 0;
upr = pPage->nCell-1;
- if( !pPage->intKey && pKey==0 ){
+ if( !pPage->intKey && pUnKey==0 ){
rc = SQLITE_CORRUPT_BKPT;
goto moveto_finish;
}
pCellKey = (void *)fetchPayload(pCur, &available, 0);
nCellKey = pCur->info.nKey;
if( available>=nCellKey ){
- c = sqlite3VdbeRecordCompareParsed(nCellKey, pCellKey, pPKey);
+ c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pUnKey);
}else{
pCellKey = sqlite3_malloc( nCellKey );
if( pCellKey==0 ){
goto moveto_finish;
}
rc = sqlite3BtreeKey(pCur, 0, nCellKey, (void *)pCellKey);
- c = sqlite3VdbeRecordCompareParsed(nCellKey, pCellKey, pPKey);
+ c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pUnKey);
sqlite3_free(pCellKey);
if( rc ) goto moveto_finish;
}
if( rc ) goto moveto_finish;
}
moveto_finish:
- sqlite3VdbeRecordUnparse(pPKey);
+ if( pKey ){
+ /* If we created our own unpacked key at the top of this
+ ** procedure, then destroy that key before returning. */
+ sqlite3VdbeDeleteUnpackedRecord(pUnKey);
+ }
return rc;
}
clearCursorPosition(pCur);
if(
SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) ||
- SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc))
+ SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, 0, nKey, appendBias, &loc))
){
return rc;
}
** subsystem. See comments in the source code for a detailed description
** of what each interface routine does.
**
-** @(#) $Id: btree.h,v 1.96 2008/03/25 09:47:35 danielk1977 Exp $
+** @(#) $Id: btree.h,v 1.97 2008/03/25 17:23:33 drh Exp $
*/
#ifndef _BTREE_H_
#define _BTREE_H_
int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
void sqlite3BtreeTripAllCursors(Btree*, int);
+struct UnpackedRecord; /* Forward declaration. Definition in vdbeaux.c. */
+
int sqlite3BtreeCursor(
Btree*, /* BTree containing table to open */
int iTable, /* Index of root page */
int sqlite3BtreeCursorSize();
int sqlite3BtreeCloseCursor(BtCursor*);
-int sqlite3BtreeMoveto(BtCursor*,const void *pKey,i64 nKey,int bias,int *pRes);
+int sqlite3BtreeMoveto(
+ BtCursor*,
+ const void *pKey,
+ struct UnpackedRecord *pUnKey,
+ i64 nKey,
+ int bias,
+ int *pRes
+);
int sqlite3BtreeDelete(BtCursor*);
int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey,
const void *pData, int nData,
** COMMIT
** ROLLBACK
**
-** $Id: build.c,v 1.476 2008/03/25 09:47:35 danielk1977 Exp $
+** $Id: build.c,v 1.477 2008/03/25 17:23:33 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
regRecord = sqlite3GetTempReg(pParse);
- regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord);
+ regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
if( pIndex->onError!=OE_None ){
int j1, j2;
int regRowid;
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
-** $Id: delete.c,v 1.163 2008/03/25 09:47:35 danielk1977 Exp $
+** $Id: delete.c,v 1.164 2008/03/25 17:23:33 drh Exp $
*/
#include "sqliteInt.h"
Index *pIdx;
int r1;
- r1 = sqlite3GetTempReg(pParse);
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue;
- sqlite3GenerateIndexKey(pParse, pIdx, iCur, r1);
- sqlite3VdbeAddOp2(pParse->pVdbe, OP_IdxDelete, iCur+i, r1);
+ r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, r1, 0);
+ sqlite3VdbeAddOp3(pParse->pVdbe, OP_IdxDelete, iCur+i, r1,pIdx->nColumn+1);
}
- sqlite3ReleaseTempReg(pParse, r1);
}
/*
-** Generate code that will assemble an index key and put it on the top
-** of the tack. The key with be for index pIdx which is an index on pTab.
+** Generate code that will assemble an index key and put it in register
+** regOut. The key with be for index pIdx which is an index on pTab.
** iCur is the index of a cursor open on the pTab table and pointing to
** the entry that needs indexing.
**
Parse *pParse, /* Parsing context */
Index *pIdx, /* The index for which to generate a key */
int iCur, /* Cursor number for the pIdx->pTable table */
- int regOut /* Write the new index key to this register */
+ int regOut, /* Write the new index key to this register */
+ int doMakeRec /* Run the OP_MakeRecord instruction if true */
){
Vdbe *v = pParse->pVdbe;
int j;
sqlite3ColumnDefault(v, pTab, idx);
}
}
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
- sqlite3IndexAffinityStr(v, pIdx);
+ if( doMakeRec ){
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
+ sqlite3IndexAffinityStr(v, pIdx);
+ }
sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
return regBase;
}
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
-** $Id: pragma.c,v 1.172 2008/03/20 11:04:21 danielk1977 Exp $
+** $Id: pragma.c,v 1.173 2008/03/25 17:23:33 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
{ OP_IfPos, 1, 0, 0}, /* 9 */
{ OP_Halt, 0, 0, 0},
};
- sqlite3GenerateIndexKey(pParse, pIdx, 1, 3);
+ sqlite3GenerateIndexKey(pParse, pIdx, 1, 3, 1);
jmp2 = sqlite3VdbeAddOp3(v, OP_Found, j+2, 0, 3);
addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr);
sqlite3VdbeChangeP4(v, addr+1, "rowid ", P4_STATIC);
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
-** $Id: select.c,v 1.418 2008/03/25 09:47:35 danielk1977 Exp $
+** $Id: select.c,v 1.419 2008/03/25 17:23:33 drh Exp $
*/
#include "sqliteInt.h"
** the temporary table iParm.
*/
case SRT_Except: {
- int r1;
- r1 = sqlite3GetTempReg(pParse);
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);
- sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC);
- sqlite3VdbeAddOp2(v, OP_IdxDelete, iParm, r1);
- sqlite3ReleaseTempReg(pParse, r1);
+ sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nColumn);
break;
}
#endif
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.679 2008/03/21 16:45:47 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.680 2008/03/25 17:23:33 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
int sqlite3IsRowid(const char*);
void sqlite3GenerateRowDelete(Parse*, Table*, int, int, int);
void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int*);
-int sqlite3GenerateIndexKey(Parse*, Index*, int, int);
+int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int);
void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int,
int*,int,int,int,int);
void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*,int,int,int,int);
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
-** $Id: test3.c,v 1.93 2008/03/25 09:47:35 danielk1977 Exp $
+** $Id: test3.c,v 1.94 2008/03/25 17:23:33 drh Exp $
*/
#include "sqliteInt.h"
#include "btreeInt.h"
sqlite3BtreeLeave(pCur->pBtree);
return TCL_ERROR;
}
- rc = sqlite3BtreeMoveto(pCur, 0, iKey, 0, &res);
+ rc = sqlite3BtreeMoveto(pCur, 0, 0, iKey, 0, &res);
}else{
- rc = sqlite3BtreeMoveto(pCur, argv[2], strlen(argv[2]), 0, &res);
+ rc = sqlite3BtreeMoveto(pCur, argv[2], 0, strlen(argv[2]), 0, &res);
}
sqlite3BtreeLeave(pCur->pBtree);
if( rc ){
** 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.717 2008/03/25 09:47:35 danielk1977 Exp $
+** $Id: vdbe.c,v 1.718 2008/03/25 17:23:33 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
pC->deferredMoveto = 1;
break;
}
- rc = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, 0, &res);
+ rc = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)iKey, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
}else{
assert( pIn3->flags & MEM_Blob );
ExpandBlob(pIn3);
- rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, pIn3->n, 0, &res);
+ rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, 0, pIn3->n, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
if( pOp->opcode==OP_Found ){
pC->pKeyInfo->prefixIsEqual = 1;
}
- rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, pIn3->n, 0, &res);
+ rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, 0, pIn3->n, 0, &res);
pC->pKeyInfo->prefixIsEqual = 0;
if( rc!=SQLITE_OK ){
break;
*/
assert( pCx->deferredMoveto==0 );
pCx->cacheStatus = CACHE_STALE;
- rc = sqlite3BtreeMoveto(pCrsr, zKey, len, 0, &res);
+ rc = sqlite3BtreeMoveto(pCrsr, zKey, 0, len, 0, &res);
if( rc!=SQLITE_OK ){
goto abort_due_to_error;
}
assert( pIn3->flags & MEM_Int );
assert( p->apCsr[i]->isTable );
iKey = intToKey(pIn3->u.i);
- rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, 0,&res);
+ rc = sqlite3BtreeMoveto(pCrsr, 0, 0, iKey, 0,&res);
pC->lastRowid = pIn3->u.i;
pC->rowidIsValid = res==0;
pC->nullRow = 0;
}
if( v==0 ) continue;
x = intToKey(v);
- rx = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)x, 0, &res);
+ rx = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)x, 0, &res);
cnt++;
}while( cnt<100 && rx==SQLITE_OK && res==0 );
db->priorNewRowid = v;
break;
}
-/* Opcode: IdxDelete P1 P2 * * *
+/* Opcode: IdxDeleteM P1 P2 P3 * *
**
-** The content of register P2 is an index key built using the
-** MakeIdxRec opcode. This opcode removes that entry from the
+** The content of P3 registers starting at register P2 form
+** an unpacked index key. This opcode removes that entry from the
** index opened by cursor P1.
*/
-case OP_IdxDelete: { /* in2 */
+case OP_IdxDelete: {
int i = pOp->p1;
Cursor *pC;
BtCursor *pCrsr;
- assert( pIn2->flags & MEM_Blob );
+ assert( pOp->p3>0 );
+ assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem );
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
int res;
- rc = sqlite3BtreeMoveto(pCrsr, pIn2->z, pIn2->n, 0, &res);
+ UnpackedRecord r;
+ r.pKeyInfo = pC->pKeyInfo;
+ r.nField = pOp->p3;
+ r.needFree = 0;
+ r.needDestroy = 0;
+ r.aMem = &p->aMem[pOp->p2];
+ rc = sqlite3BtreeMoveto(pCrsr, 0, &r, 0, 0, &res);
if( rc==SQLITE_OK && res==0 ){
rc = sqlite3BtreeDelete(pCrsr);
}
** or VDBE. The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
-** $Id: vdbe.h,v 1.127 2008/03/25 00:22:21 drh Exp $
+** $Id: vdbe.h,v 1.128 2008/03/25 17:23:34 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
*/
typedef struct VdbeFunc VdbeFunc;
typedef struct Mem Mem;
-typedef struct VdbeParsedRecord VdbeParsedRecord;
+typedef struct UnpackedRecord UnpackedRecord;
/*
** A single instruction of the virtual machine has an opcode
void sqlite3VdbeSetSql(Vdbe*, const char *z, int n);
void sqlite3VdbeSwap(Vdbe*,Vdbe*);
-VdbeParsedRecord *sqlite3VdbeRecordParse(KeyInfo*,int,const void*,void*,int);
-void sqlite3VdbeRecordUnparse(VdbeParsedRecord*);
-int sqlite3VdbeRecordCompareParsed(int,const void*,VdbeParsedRecord*);
+UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,void*,int);
+void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*);
+int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
#ifndef NDEBUG
#endif
};
+/*
+** An instance of the following structure holds information about a
+** single index record that has already been parsed out into individual
+** values.
+**
+** A record is an object that contains one or more fields of data.
+** Records are used to store the content of a table row and to store
+** the key of an index. A blob encoding of a record is created by
+** the OP_MakeRecord opcode of the VDBE and is disassemblied by the
+** OP_Column opcode.
+**
+** This structure holds a record that has already been disassembled
+** into its constitutent fields.
+*/
+struct UnpackedRecord {
+ KeyInfo *pKeyInfo; /* Collation and sort-order information */
+ u16 nField; /* Number of entries in apMem[] */
+ u8 needFree; /* True if memory obtained from sqlite3_malloc() */
+ u8 needDestroy; /* True if apMem[]s should be destroyed on close */
+ Mem *aMem; /* Values */
+};
+
/*
** The following are allowed values for Vdbe.magic
*/
extern int sqlite3_search_count;
#endif
assert( p->isTable );
- rc = sqlite3BtreeMoveto(p->pCursor, 0, p->movetoTarget, 0, &res);
+ rc = sqlite3BtreeMoveto(p->pCursor, 0, 0, p->movetoTarget, 0, &res);
if( rc ) return rc;
*p->pIncrKey = 0;
p->lastRowid = keyToInt(p->movetoTarget);
*/
#define GetVarint(A,B) ((B = *(A))<=0x7f ? 1 : sqlite3GetVarint32(A, &B))
-#if 0
-/*
-** This function compares the two table rows or index records specified by
-** {nKey1, pKey1} and {nKey2, pKey2}, returning a negative, zero
-** or positive integer if {nKey1, pKey1} is less than, equal to or
-** greater than {nKey2, pKey2}. Both Key1 and Key2 must be byte strings
-** composed by the OP_MakeRecord opcode of the VDBE.
-**
-** Key1 and Key2 do not have to contain the same number of fields.
-** But if the lengths differ, Key2 must be the shorter of the two.
-*/
-int sqlite3VdbeRecordCompare(
- void *userData,
- int nKey1, const void *pKey1,
- int nKey2, const void *pKey2
-){
- KeyInfo *pKeyInfo = (KeyInfo*)userData;
- u32 d1, d2; /* Offset into aKey[] of next data element */
- u32 idx1, idx2; /* Offset into aKey[] of next header element */
- u32 szHdr1, szHdr2; /* Number of bytes in header */
- int i = 0;
- int nField;
- int rc = 0;
- const unsigned char *aKey1 = (const unsigned char *)pKey1;
- const unsigned char *aKey2 = (const unsigned char *)pKey2;
-
- Mem mem1;
- Mem mem2;
- mem1.enc = pKeyInfo->enc;
- mem1.db = pKeyInfo->db;
- mem1.flags = 0;
- mem2.enc = pKeyInfo->enc;
- mem2.db = pKeyInfo->db;
- mem2.flags = 0;
-
- idx1 = GetVarint(aKey1, szHdr1);
- d1 = szHdr1;
- idx2 = GetVarint(aKey2, szHdr2);
- d2 = szHdr2;
- nField = pKeyInfo->nField;
- while( idx1<szHdr1 && idx2<szHdr2 ){
- u32 serial_type1;
- u32 serial_type2;
-
- /* Read the serial types for the next element in each key. */
- idx1 += GetVarint( aKey1+idx1, serial_type1 );
- if( d1>=nKey1 && sqlite3VdbeSerialTypeLen(serial_type1)>0 ) break;
- idx2 += GetVarint( aKey2+idx2, serial_type2 );
- if( d2>=nKey2 && sqlite3VdbeSerialTypeLen(serial_type2)>0 ) break;
-
- /* Extract the values to be compared.
- */
- d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1);
- d2 += sqlite3VdbeSerialGet(&aKey2[d2], serial_type2, &mem2);
-
- /* Do the comparison
- */
- rc = sqlite3MemCompare(&mem1, &mem2, i<nField ? pKeyInfo->aColl[i] : 0);
- if( mem1.flags&MEM_Dyn ) sqlite3VdbeMemRelease(&mem1);
- if( mem2.flags&MEM_Dyn ) sqlite3VdbeMemRelease(&mem2);
- if( rc!=0 ){
- break;
- }
- i++;
- }
-
- /* One of the keys ran out of fields, but all the fields up to that point
- ** were equal. If the incrKey flag is true, then the second key is
- ** treated as larger.
- */
- if( rc==0 ){
- if( pKeyInfo->incrKey ){
- rc = -1;
- }else if( !pKeyInfo->prefixIsEqual ){
- if( d1<nKey1 ){
- rc = 1;
- }else if( d2<nKey2 ){
- rc = -1; /* Only occurs on a corrupt database file */
- }
- }
- }else if( pKeyInfo->aSortOrder && i<pKeyInfo->nField
- && pKeyInfo->aSortOrder[i] ){
- rc = -rc;
- }
-
- return rc;
-}
-#endif
-
-/*
-** An instance of the following structure holds information about a
-** single index record that has already been parsed out into individual
-** values.
-**
-** A record is an object that contains one or more fields of data.
-** Records are used to store the content of a table row and to store
-** the key of an index. A blob encoding of a record is created by
-** the OP_MakeRecord opcode of the VDBE and is disassemblied by the
-** OP_Column opcode.
-**
-** This structure holds a record that has already been disassembled
-** into its constitutent fields.
-*/
-struct VdbeParsedRecord {
- KeyInfo *pKeyInfo; /* Collation and sort-order information */
- u16 nField; /* Number of entries in apMem[] */
- u8 needFree; /* True if memory obtained from sqlite3_malloc() */
- u8 needDestroy; /* True if apMem[]s should be destroyed on close */
- Mem *apMem[1]; /* Values */
-};
-
/*
** Given the nKey-byte encoding of a record in pKey[], parse the
-** record into a VdbeParsedRecord structure. Return a pointer to
+** record into a UnpackedRecord structure. Return a pointer to
** that structure.
**
** The calling function might provide szSpace bytes of memory
** not big enough, space is obtained from sqlite3_malloc().
**
** The returned structure should be closed by a call to
-** sqlite3VdbeRecordUnparse().
+** sqlite3VdbeDeleteUnpackedRecord().
*/
-VdbeParsedRecord *sqlite3VdbeRecordParse(
+UnpackedRecord *sqlite3VdbeRecordUnpack(
KeyInfo *pKeyInfo, /* Information about the record format */
int nKey, /* Size of the binary record */
const void *pKey, /* The binary record */
int szSpace /* Size of pSpace[] in bytes */
){
const unsigned char *aKey = (const unsigned char *)pKey;
- VdbeParsedRecord *p;
+ UnpackedRecord *p;
int nByte;
int i, idx, d;
u32 szHdr;
Mem *pMem;
- nByte = sizeof(*p) + sizeof(Mem*)*pKeyInfo->nField
- + sizeof(Mem)*(pKeyInfo->nField+1);
+ nByte = sizeof(*p) + sizeof(Mem)*(pKeyInfo->nField+1);
if( nByte>szSpace ){
p = sqlite3DbMallocRaw(pKeyInfo->db, nByte);
if( p==0 ) return 0;
p->pKeyInfo = pKeyInfo;
p->nField = pKeyInfo->nField + 1;
p->needDestroy = 1;
- pMem = (Mem*)&p->apMem[pKeyInfo->nField+1];
+ p->aMem = pMem = (Mem*)&p[1];
idx = GetVarint(aKey, szHdr);
d = szHdr;
i = 0;
pMem->db = pKeyInfo->db;
pMem->flags = 0;
d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem);
- p->apMem[i++] = pMem++;
+ pMem++;
+ i++;
}
p->nField = i;
return (void*)p;
}
/*
-** This routine destroys a VdbeParsedRecord object
+** This routine destroys a UnpackedRecord object
*/
-void sqlite3VdbeRecordUnparse(VdbeParsedRecord *p){
+void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
if( p ){
if( p->needDestroy ){
int i;
- for(i=0; i<p->nField; i++){
- if( p->apMem[i]->flags & MEM_Dyn ){
- sqlite3VdbeMemRelease(p->apMem[i]);
+ Mem *pMem;
+ for(i=0, pMem=p->aMem; i<p->nField; i++, pMem++){
+ if( pMem->flags & MEM_Dyn ){
+ sqlite3VdbeMemRelease(pMem);
}
}
}
** separately and submit the parsed version. In this way, we avoid
** parsing the same Key2 multiple times in a row.
*/
-int sqlite3VdbeRecordCompareParsed(
+int sqlite3VdbeRecordCompare(
int nKey1, const void *pKey1,
- VdbeParsedRecord *pPKey2
+ UnpackedRecord *pPKey2
){
u32 d1; /* Offset into aKey[] of next data element */
u32 idx1; /* Offset into aKey[] of next header element */
/* Do the comparison
*/
- rc = sqlite3MemCompare(&mem1, pPKey2->apMem[i],
+ rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i],
i<nField ? pKeyInfo->aColl[i] : 0);
if( mem1.flags&MEM_Dyn ) sqlite3VdbeMemRelease(&mem1);
if( rc!=0 ){
BtCursor *pCur = pC->pCursor;
int lenRowid;
Mem m;
- VdbeParsedRecord *pRec;
+ UnpackedRecord *pRec;
char zSpace[200];
sqlite3BtreeKeySize(pCur, &nCellKey);
return rc;
}
lenRowid = sqlite3VdbeIdxRowidLen((u8*)m.z);
- pRec = sqlite3VdbeRecordParse(pC->pKeyInfo, nKey, pKey,
+ pRec = sqlite3VdbeRecordUnpack(pC->pKeyInfo, nKey, pKey,
zSpace, sizeof(zSpace));
if( pRec==0 ){
return SQLITE_NOMEM;
}
- *res = sqlite3VdbeRecordCompareParsed(m.n-lenRowid, m.z, pRec);
- sqlite3VdbeRecordUnparse(pRec);
+ *res = sqlite3VdbeRecordCompare(m.n-lenRowid, m.z, pRec);
+ sqlite3VdbeDeleteUnpackedRecord(pRec);
sqlite3VdbeMemRelease(&m);
return SQLITE_OK;
}