Additional changes toward fixing ticket #3292. (CVS 5562)
FossilOrigin-Name: 0b92cbf5255020d4fde382f81590ff0488936667
This commit is contained in:
parent
ec1fc80ca3
commit
e63d999189
26
manifest
26
manifest
@ -1,5 +1,5 @@
|
||||
C A\spartial\sfix\sfor\sticket\s#3292.\s\sThis\sfixes\sthe\soriginal\sproblem\sbut\sthere\nare\sother\ssimilar\sproblems\slurking\sin\sthe\scode\sstill.\s(CVS\s5561)
|
||||
D 2008-08-13T14:07:40
|
||||
C Additional\schanges\stoward\sfixing\sticket\s#3292.\s(CVS\s5562)
|
||||
D 2008-08-13T19:11:48
|
||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||
F Makefile.in 2713ea64947be3b35f35d9a3158bb8299c90b019
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@ -96,8 +96,8 @@ F src/attach.c a85c14612e7e3410e0c3d2e0241832fa9688bd14
|
||||
F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
|
||||
F src/bitvec.c 95c86bd18d8fedf0533f5af196192546e10a7e7d
|
||||
F src/btmutex.c 709cad2cdca0afd013f0f612363810e53f59ec53
|
||||
F src/btree.c 2ae1092eee58d2d89e5d2f59f711f805dec59bbc
|
||||
F src/btree.h 03256ed7ee42b5ecacbe887070b0f8249e7d069d
|
||||
F src/btree.c c38431aed9dcdf62916c9009d6f9971e588189fe
|
||||
F src/btree.h 6371c5e599fab391a150c96afbc10062b276d107
|
||||
F src/btreeInt.h ab18c7b4980314e9e4b402e5dcde09f3c2545576
|
||||
F src/build.c 931ed94fd3bbd67b6ac9d5ac6a45dc01e9f01726
|
||||
F src/callback.c c9f75a4c403f166af3761df47d78a806587d63af
|
||||
@ -146,14 +146,14 @@ F src/select.c 390d1bdde0c24f0225e369896da8e60ef2aeffbe
|
||||
F src/shell.c d83b578a8ccdd3e0e7fef4388a0887ce9f810967
|
||||
F src/sqlite.h.in 54e51c22e2294c5989156b0aec87aa44168ac1f0
|
||||
F src/sqlite3ext.h 1e3887c9bd3ae66cb599e922824b04cd0d0f2c3e
|
||||
F src/sqliteInt.h df48efd8c4cb7b833bd7299a41c59c6651be0072
|
||||
F src/sqliteInt.h 7c68cacc760e8038ba6221c4d9ee3a7f0580e181
|
||||
F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
|
||||
F src/status.c 8caa772cd9310bc297280f7cf0ede4d69ed5b801
|
||||
F src/table.c 22744786199c9195720c15a7a42cb97b2e2728d8
|
||||
F src/tclsqlite.c ec46084184f033ba396a9ee7b5514b695083d0f3
|
||||
F src/test1.c 0ae2203b03dec8ecf8ad731038df47ba27bfe68c
|
||||
F src/test2.c 7a634c1e044be3ea5845e65155fdd1cab13936cb
|
||||
F src/test3.c e00795839be38f0345a4845170426fb17d828bf9
|
||||
F src/test3.c e85b7ce5c28c3ce7fbdbf7f98e1467b19786c62b
|
||||
F src/test4.c 41056378671e7b00e6305fa9ac6fa27e6f96f406
|
||||
F src/test5.c 162a1cea2105a2c460a3f39fa6919617b562a288
|
||||
F src/test6.c 0a0304a69cfa4962a429d084c6d451ff9e4fb572
|
||||
@ -183,11 +183,11 @@ F src/update.c 79b77a3cc8ed5f8903a7f37055fcedd69388dcae
|
||||
F src/utf.c c63e6f69082f85c19ab88d62dedaf91d71ac1a50
|
||||
F src/util.c afe659ccc05d1f8af9e8631dabfec3ee3a7144af
|
||||
F src/vacuum.c ef342828002debc97514617af3424aea8ef8522c
|
||||
F src/vdbe.c cda10a8e6ac05c783d6cd8a1d4852754fa73cf3b
|
||||
F src/vdbe.h ccca49ce3db3486ae27f9baec68a77ccc29c43a9
|
||||
F src/vdbeInt.h 6f04c2bf65a0d5c2bb8318b226278a35d1f7a8f5
|
||||
F src/vdbe.c e2dd0c78c5579e23db49ed8265f0b44d7b22c51d
|
||||
F src/vdbe.h 17bcc2b41082f9b99718b3757cbf97145a72023a
|
||||
F src/vdbeInt.h b48c74d86a9fb62b707a3186ccca76bb32f1c6be
|
||||
F src/vdbeapi.c f21971516880fd3a10821b2cdd0e64a5a63952c9
|
||||
F src/vdbeaux.c 7b25fbbbdbd548b71c0a44d2f90fd3d0b06e70b8
|
||||
F src/vdbeaux.c 3e2e1f36c25eae32bdd605456c8be99f73e71eaf
|
||||
F src/vdbeblob.c f93110888ddc246215e9ba1f831d3d375bfd8355
|
||||
F src/vdbefifo.c 20fda2a7c4c0bcee1b90eb7e545fefcdbf2e1de7
|
||||
F src/vdbemem.c c37b2a266a49eaf0c0f5080157f9f1a908fdaac3
|
||||
@ -618,7 +618,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
|
||||
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
P d6aacc5dc7c06f97fb5faa3d85a8f2d8ab0dd554
|
||||
R 9b480ed8f28854c07567551a082c6f07
|
||||
P 055f173ab1b6fb657bf817faa3a37335d8fa60d5
|
||||
R 3660b918f4cbadc772ff6c9bb7d03fb8
|
||||
U drh
|
||||
Z d0f90d7840e7d910b5f941e8ef52ae1d
|
||||
Z ef96eabf3e6f46a636feb3cbdfe8a28b
|
||||
|
@ -1 +1 @@
|
||||
055f173ab1b6fb657bf817faa3a37335d8fa60d5
|
||||
0b92cbf5255020d4fde382f81590ff0488936667
|
95
src/btree.c
95
src/btree.c
@ -9,7 +9,7 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** $Id: btree.c,v 1.496 2008/08/13 14:07:40 drh Exp $
|
||||
** $Id: btree.c,v 1.497 2008/08/13 19:11:48 drh Exp $
|
||||
**
|
||||
** This file implements a external (disk-based) database using BTrees.
|
||||
** See the header comment on "btreeInt.h" for additional information.
|
||||
@ -375,7 +375,7 @@ int sqlite3BtreeRestoreCursorPosition(BtCursor *pCur){
|
||||
return pCur->skip;
|
||||
}
|
||||
pCur->eState = CURSOR_INVALID;
|
||||
rc = sqlite3BtreeMoveto(pCur, pCur->pKey, 0, pCur->nKey, 0, &pCur->skip);
|
||||
rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skip);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_free(pCur->pKey);
|
||||
pCur->pKey = 0;
|
||||
@ -3648,12 +3648,11 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
|
||||
}
|
||||
|
||||
/* Move the cursor so that it points to an entry near the key
|
||||
** specified by pKey/nKey/pUnKey. Return a success code.
|
||||
** specified by pIdxKey or intKey. Return a success code.
|
||||
**
|
||||
** 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.
|
||||
** For INTKEY tables, the intKey parameter is used. pIdxKey
|
||||
** must be NULL. For index tables, pIdxKey is used and intKey
|
||||
** is ignored.
|
||||
**
|
||||
** 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
|
||||
@ -3675,16 +3674,14 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
|
||||
** is larger than pKey.
|
||||
**
|
||||
*/
|
||||
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 sqlite3BtreeMovetoUnpacked(
|
||||
BtCursor *pCur, /* The cursor to be moved */
|
||||
UnpackedRecord *pIdxKey, /* Unpacked index key */
|
||||
i64 intKey, /* The table key */
|
||||
int biasRight, /* If true, bias the search to the high end */
|
||||
int *pRes /* Write search results here */
|
||||
){
|
||||
int rc;
|
||||
char aSpace[200];
|
||||
|
||||
assert( cursorHoldsMutex(pCur) );
|
||||
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
|
||||
@ -3692,11 +3689,11 @@ int sqlite3BtreeMoveto(
|
||||
/* If the cursor is already positioned at the point we are trying
|
||||
** to move to, then just return without doing any work */
|
||||
if( pCur->eState==CURSOR_VALID && pCur->validNKey && pCur->pPage->intKey ){
|
||||
if( pCur->info.nKey==nKey ){
|
||||
if( pCur->info.nKey==intKey ){
|
||||
*pRes = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
if( pCur->atLast && pCur->info.nKey<nKey ){
|
||||
if( pCur->atLast && pCur->info.nKey<intKey ){
|
||||
*pRes = -1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@ -3714,24 +3711,7 @@ int sqlite3BtreeMoveto(
|
||||
assert( pCur->pPage->nCell==0 );
|
||||
return SQLITE_OK;
|
||||
}
|
||||
if( pCur->pPage->intKey ){
|
||||
/* 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( 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 );
|
||||
}
|
||||
assert( pCur->pPage->intKey || pIdxKey );
|
||||
for(;;){
|
||||
int lwr, upr;
|
||||
Pgno chldPg;
|
||||
@ -3739,7 +3719,7 @@ int sqlite3BtreeMoveto(
|
||||
int c = -1; /* pRes return if table is empty must be -1 */
|
||||
lwr = 0;
|
||||
upr = pPage->nCell-1;
|
||||
if( !pPage->intKey && pUnKey==0 ){
|
||||
if( !pPage->intKey && pIdxKey==0 ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto moveto_finish;
|
||||
}
|
||||
@ -3761,12 +3741,12 @@ int sqlite3BtreeMoveto(
|
||||
pCell += getVarint32(pCell, dummy);
|
||||
}
|
||||
getVarint(pCell, (u64*)&nCellKey);
|
||||
if( nCellKey==nKey ){
|
||||
if( nCellKey==intKey ){
|
||||
c = 0;
|
||||
}else if( nCellKey<nKey ){
|
||||
}else if( nCellKey<intKey ){
|
||||
c = -1;
|
||||
}else{
|
||||
assert( nCellKey>nKey );
|
||||
assert( nCellKey>intKey );
|
||||
c = +1;
|
||||
}
|
||||
}else{
|
||||
@ -3774,7 +3754,7 @@ int sqlite3BtreeMoveto(
|
||||
pCellKey = (void *)fetchPayload(pCur, &available, 0);
|
||||
nCellKey = pCur->info.nKey;
|
||||
if( available>=nCellKey ){
|
||||
c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, 0, pUnKey);
|
||||
c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pIdxKey);
|
||||
}else{
|
||||
pCellKey = sqlite3Malloc( nCellKey );
|
||||
if( pCellKey==0 ){
|
||||
@ -3782,7 +3762,7 @@ int sqlite3BtreeMoveto(
|
||||
goto moveto_finish;
|
||||
}
|
||||
rc = sqlite3BtreeKey(pCur, 0, nCellKey, (void *)pCellKey);
|
||||
c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, 0, pUnKey);
|
||||
c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pIdxKey);
|
||||
sqlite3_free(pCellKey);
|
||||
if( rc ) goto moveto_finish;
|
||||
}
|
||||
@ -3832,10 +3812,35 @@ int sqlite3BtreeMoveto(
|
||||
if( rc ) goto moveto_finish;
|
||||
}
|
||||
moveto_finish:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** In this version of BtreeMoveto, pKey is a packed index record
|
||||
** such as is generated by the OP_MakeRecord opcode. Unpack the
|
||||
** record and then call BtreeMovetoUnpacked() to do the work.
|
||||
*/
|
||||
int sqlite3BtreeMoveto(
|
||||
BtCursor *pCur, /* Cursor open on the btree to be searched */
|
||||
const void *pKey, /* Packed key if the btree is an index */
|
||||
i64 nKey, /* Integer key for tables. Size of pKey for indices */
|
||||
int bias, /* Bias search to the high end */
|
||||
int *pRes /* Write search results here */
|
||||
){
|
||||
int rc; /* Status code */
|
||||
UnpackedRecord *pIdxKey; /* Unpacked index key */
|
||||
char aSpace[200]; /* Temp space for pIdxKey - to avoid a malloc */
|
||||
|
||||
if( pKey ){
|
||||
/* If we created our own unpacked key at the top of this
|
||||
** procedure, then destroy that key before returning. */
|
||||
sqlite3VdbeDeleteUnpackedRecord(pUnKey);
|
||||
pIdxKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, nKey, pKey,
|
||||
aSpace, sizeof(aSpace));
|
||||
if( pIdxKey==0 ) return SQLITE_NOMEM;
|
||||
}else{
|
||||
pIdxKey = 0;
|
||||
}
|
||||
rc = sqlite3BtreeMovetoUnpacked(pCur, pIdxKey, nKey, bias, pRes);
|
||||
if( pKey ){
|
||||
sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@ -5836,7 +5841,7 @@ int sqlite3BtreeInsert(
|
||||
clearCursorPosition(pCur);
|
||||
if(
|
||||
SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) ||
|
||||
SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, 0, nKey, appendBias, &loc))
|
||||
SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc))
|
||||
){
|
||||
return rc;
|
||||
}
|
||||
|
12
src/btree.h
12
src/btree.h
@ -13,7 +13,7 @@
|
||||
** subsystem. See comments in the source code for a detailed description
|
||||
** of what each interface routine does.
|
||||
**
|
||||
** @(#) $Id: btree.h,v 1.102 2008/07/11 21:02:54 drh Exp $
|
||||
** @(#) $Id: btree.h,v 1.103 2008/08/13 19:11:48 drh Exp $
|
||||
*/
|
||||
#ifndef _BTREE_H_
|
||||
#define _BTREE_H_
|
||||
@ -122,8 +122,6 @@ int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue);
|
||||
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 */
|
||||
@ -137,11 +135,17 @@ int sqlite3BtreeCloseCursor(BtCursor*);
|
||||
int sqlite3BtreeMoveto(
|
||||
BtCursor*,
|
||||
const void *pKey,
|
||||
struct UnpackedRecord *pUnKey,
|
||||
i64 nKey,
|
||||
int bias,
|
||||
int *pRes
|
||||
);
|
||||
int sqlite3BtreeMovetoUnpacked(
|
||||
BtCursor*,
|
||||
UnpackedRecord *pUnKey,
|
||||
i64 intKey,
|
||||
int bias,
|
||||
int *pRes
|
||||
);
|
||||
int sqlite3BtreeCursorHasMoved(BtCursor*, int*);
|
||||
int sqlite3BtreeDelete(BtCursor*);
|
||||
int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey,
|
||||
|
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.754 2008/08/13 14:07:40 drh Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.755 2008/08/13 19:11:48 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITEINT_H_
|
||||
#define _SQLITEINT_H_
|
||||
@ -470,6 +470,7 @@ typedef struct Token Token;
|
||||
typedef struct TriggerStack TriggerStack;
|
||||
typedef struct TriggerStep TriggerStep;
|
||||
typedef struct Trigger Trigger;
|
||||
typedef struct UnpackedRecord UnpackedRecord;
|
||||
typedef struct WhereInfo WhereInfo;
|
||||
typedef struct WhereLevel WhereLevel;
|
||||
|
||||
@ -1037,21 +1038,45 @@ struct FKey {
|
||||
** An instance of the following structure is passed as the first
|
||||
** argument to sqlite3VdbeKeyCompare and is used to control the
|
||||
** comparison of the two index keys.
|
||||
**
|
||||
** If the KeyInfo.incrKey value is true and the comparison would
|
||||
** otherwise be equal, then return a result as if the second key
|
||||
** were larger.
|
||||
*/
|
||||
struct KeyInfo {
|
||||
sqlite3 *db; /* The database connection */
|
||||
u8 enc; /* Text encoding - one of the TEXT_Utf* values */
|
||||
u8 incrKey; /* Increase 2nd key by epsilon before comparison */
|
||||
u8 ckPrefixOnly; /* Records are equal if shorter is a prefix of longer */
|
||||
int nField; /* Number of entries in aColl[] */
|
||||
u16 nField; /* Number of entries in aColl[] */
|
||||
u8 *aSortOrder; /* If defined an aSortOrder[i] is true, sort DESC */
|
||||
CollSeq *aColl[1]; /* Collating sequence for each term of the key */
|
||||
};
|
||||
|
||||
/*
|
||||
** 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[] */
|
||||
u16 flags; /* Boolean settings. UNPACKED_... below */
|
||||
Mem *aMem; /* Values */
|
||||
};
|
||||
|
||||
/*
|
||||
** Allowed values of UnpackedRecord.flags
|
||||
*/
|
||||
#define UNPACKED_NEED_FREE 0x0001 /* Memory is from sqlite3Malloc() */
|
||||
#define UNPACKED_NEED_DESTROY 0x0002 /* apMem[]s should all be destroyed */
|
||||
#define UNPACKED_IGNORE_ROWID 0x0004 /* Ignore trailing rowid on key1 */
|
||||
#define UNPACKED_INCRKEY 0x0008 /* Make this key an epsilon larger */
|
||||
#define UNPACKED_PREFIX_MATCH 0x0010 /* A prefix match is considered OK */
|
||||
|
||||
/*
|
||||
** Each SQL index is represented in memory by an
|
||||
** instance of the following structure.
|
||||
|
@ -13,7 +13,7 @@
|
||||
** is not included in the SQLite library. It is used for automated
|
||||
** testing of the SQLite library.
|
||||
**
|
||||
** $Id: test3.c,v 1.100 2008/07/12 14:52:20 drh Exp $
|
||||
** $Id: test3.c,v 1.101 2008/08/13 19:11:48 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "btreeInt.h"
|
||||
@ -697,9 +697,9 @@ static int btree_move_to(
|
||||
sqlite3BtreeLeave(pCur->pBtree);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
rc = sqlite3BtreeMoveto(pCur, 0, 0, iKey, 0, &res);
|
||||
rc = sqlite3BtreeMovetoUnpacked(pCur, 0, iKey, 0, &res);
|
||||
}else{
|
||||
rc = sqlite3BtreeMoveto(pCur, argv[2], 0, strlen(argv[2]), 0, &res);
|
||||
rc = sqlite3BtreeMoveto(pCur, argv[2], strlen(argv[2]), 0, &res);
|
||||
}
|
||||
sqlite3BtreeLeave(pCur->pBtree);
|
||||
if( rc ){
|
||||
|
93
src/vdbe.c
93
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.774 2008/08/13 14:07:40 drh Exp $
|
||||
** $Id: vdbe.c,v 1.775 2008/08/13 19:11:48 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@ -555,6 +555,8 @@ int sqlite3VdbeExec(
|
||||
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
int nProgressOps = 0; /* Opcodes executed since progress callback. */
|
||||
#endif
|
||||
char zTempSpace[200]; /* Space to hold a transient UnpackedRecord */
|
||||
|
||||
|
||||
assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */
|
||||
assert( db->magic==SQLITE_MAGIC_BUSY );
|
||||
@ -2705,11 +2707,9 @@ case OP_OpenWrite: {
|
||||
rc = sqlite3BtreeCursor(pX, p2, wrFlag, pOp->p4.p, pCur->pCursor);
|
||||
if( pOp->p4type==P4_KEYINFO ){
|
||||
pCur->pKeyInfo = pOp->p4.pKeyInfo;
|
||||
pCur->pIncrKey = &pCur->pKeyInfo->incrKey;
|
||||
pCur->pKeyInfo->enc = ENC(p->db);
|
||||
}else{
|
||||
pCur->pKeyInfo = 0;
|
||||
pCur->pIncrKey = &pCur->bogusIncrKey;
|
||||
}
|
||||
switch( rc ){
|
||||
case SQLITE_BUSY: {
|
||||
@ -2809,13 +2809,11 @@ case OP_OpenEphemeral: {
|
||||
(KeyInfo*)pOp->p4.z, pCx->pCursor);
|
||||
pCx->pKeyInfo = pOp->p4.pKeyInfo;
|
||||
pCx->pKeyInfo->enc = ENC(p->db);
|
||||
pCx->pIncrKey = &pCx->pKeyInfo->incrKey;
|
||||
}
|
||||
pCx->isTable = 0;
|
||||
}else{
|
||||
rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, pCx->pCursor);
|
||||
pCx->isTable = 1;
|
||||
pCx->pIncrKey = &pCx->bogusIncrKey;
|
||||
}
|
||||
}
|
||||
pCx->isIndex = !pCx->isTable;
|
||||
@ -2851,7 +2849,6 @@ case OP_OpenPseudo: {
|
||||
pCx->nullRow = 1;
|
||||
pCx->pseudoTable = 1;
|
||||
pCx->ephemPseudoTable = pOp->p2;
|
||||
pCx->pIncrKey = &pCx->bogusIncrKey;
|
||||
pCx->isTable = 1;
|
||||
pCx->isIndex = 0;
|
||||
break;
|
||||
@ -2943,7 +2940,6 @@ case OP_MoveGt: { /* jump, in3 */
|
||||
int res, oc;
|
||||
oc = pOp->opcode;
|
||||
pC->nullRow = 0;
|
||||
*pC->pIncrKey = oc==OP_MoveGt || oc==OP_MoveLe;
|
||||
if( pC->isTable ){
|
||||
i64 iKey = sqlite3VdbeIntValue(pIn3);
|
||||
if( pOp->p2==0 ){
|
||||
@ -2953,7 +2949,7 @@ case OP_MoveGt: { /* jump, in3 */
|
||||
pC->deferredMoveto = 1;
|
||||
break;
|
||||
}
|
||||
rc = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)iKey, 0, &res);
|
||||
rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)iKey, 0, &res);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
@ -2966,10 +2962,13 @@ case OP_MoveGt: { /* jump, in3 */
|
||||
assert( nField>0 );
|
||||
r.pKeyInfo = pC->pKeyInfo;
|
||||
r.nField = nField;
|
||||
r.needFree = 0;
|
||||
r.needDestroy = 0;
|
||||
if( oc==OP_MoveGt || oc==OP_MoveLe ){
|
||||
r.flags = UNPACKED_INCRKEY;
|
||||
}else{
|
||||
r.flags = 0;
|
||||
}
|
||||
r.aMem = &p->aMem[pOp->p3];
|
||||
rc = sqlite3BtreeMoveto(pC->pCursor, 0, &r, 0, 0, &res);
|
||||
rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, &r, 0, 0, &res);
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
@ -2977,7 +2976,6 @@ case OP_MoveGt: { /* jump, in3 */
|
||||
}
|
||||
pC->deferredMoveto = 0;
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
*pC->pIncrKey = 0;
|
||||
#ifdef SQLITE_TEST
|
||||
sqlite3_search_count++;
|
||||
#endif
|
||||
@ -3055,13 +3053,20 @@ case OP_Found: { /* jump, in3 */
|
||||
assert( p->apCsr[i]!=0 );
|
||||
if( (pC = p->apCsr[i])->pCursor!=0 ){
|
||||
int res;
|
||||
UnpackedRecord *pIdxKey;
|
||||
|
||||
assert( pC->isTable==0 );
|
||||
assert( pIn3->flags & MEM_Blob );
|
||||
if( pOp->opcode==OP_Found ){
|
||||
pC->pKeyInfo->ckPrefixOnly = 1;
|
||||
pIdxKey = sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z,
|
||||
zTempSpace, sizeof(zTempSpace));
|
||||
if( pIdxKey==0 ){
|
||||
goto no_mem;
|
||||
}
|
||||
rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, 0, pIn3->n, 0, &res);
|
||||
pC->pKeyInfo->ckPrefixOnly = 0;
|
||||
if( pOp->opcode==OP_Found ){
|
||||
pIdxKey->flags |= UNPACKED_PREFIX_MATCH;
|
||||
}
|
||||
rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res);
|
||||
sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
|
||||
if( rc!=SQLITE_OK ){
|
||||
break;
|
||||
}
|
||||
@ -3081,7 +3086,7 @@ case OP_Found: { /* jump, in3 */
|
||||
**
|
||||
** The P3 register contains an integer record number. Call this
|
||||
** record number R. The P4 register contains an index key created
|
||||
** using MakeIdxRec. Call it K.
|
||||
** using MakeRecord. Call it K.
|
||||
**
|
||||
** P1 is an index. So it has no data and its key consists of a
|
||||
** record generated by OP_MakeRecord where the last field is the
|
||||
@ -3117,45 +3122,39 @@ case OP_IsUnique: { /* jump, in3 */
|
||||
pCrsr = pCx->pCursor;
|
||||
if( pCrsr!=0 ){
|
||||
int res;
|
||||
i64 v; /* The record number on the P1 entry that matches K */
|
||||
char *zKey; /* The value of K */
|
||||
int nKey; /* Number of bytes in K */
|
||||
int len; /* Number of bytes in K without the rowid at the end */
|
||||
int szRowid; /* Size of the rowid column at the end of zKey */
|
||||
i64 v; /* The record number that matches K */
|
||||
UnpackedRecord *pIdxKey; /* Unpacked version of P4 */
|
||||
|
||||
/* Make sure K is a string and make zKey point to K
|
||||
*/
|
||||
assert( pK->flags & MEM_Blob );
|
||||
zKey = pK->z;
|
||||
nKey = pK->n;
|
||||
pIdxKey = sqlite3VdbeRecordUnpack(pCx->pKeyInfo, pK->n, pK->z,
|
||||
zTempSpace, sizeof(zTempSpace));
|
||||
if( pIdxKey==0 ){
|
||||
goto no_mem;
|
||||
}
|
||||
pIdxKey->flags |= UNPACKED_IGNORE_ROWID;
|
||||
|
||||
/* sqlite3VdbeIdxRowidLen() only returns other than SQLITE_OK when the
|
||||
** record passed as an argument corrupt. Since the record in this case
|
||||
** has just been created by an OP_MakeRecord instruction, and not loaded
|
||||
** from the database file, it is not possible for it to be corrupt.
|
||||
** Therefore, assert(rc==SQLITE_OK).
|
||||
*/
|
||||
rc = sqlite3VdbeIdxRowidLen((u8*)zKey, nKey, &szRowid);
|
||||
assert(rc==SQLITE_OK);
|
||||
len = nKey-szRowid;
|
||||
|
||||
/* Search for an entry in P1 where all but the last four bytes match K.
|
||||
/* Search for an entry in P1 where all but the last rowid match K
|
||||
** If there is no such entry, jump immediately to P2.
|
||||
*/
|
||||
assert( pCx->deferredMoveto==0 );
|
||||
pCx->cacheStatus = CACHE_STALE;
|
||||
rc = sqlite3BtreeMoveto(pCrsr, zKey, 0, len, 0, &res);
|
||||
rc = sqlite3BtreeMovetoUnpacked(pCrsr, pIdxKey, 0, 0, &res);
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
if( res<0 ){
|
||||
rc = sqlite3BtreeNext(pCrsr, &res);
|
||||
if( res ){
|
||||
pc = pOp->p2 - 1;
|
||||
sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
|
||||
break;
|
||||
}
|
||||
}
|
||||
rc = sqlite3VdbeIdxKeyCompare(pCx, 0, len, (u8*)zKey, &res);
|
||||
rc = sqlite3VdbeIdxKeyCompare(pCx, pIdxKey, &res);
|
||||
sqlite3VdbeDeleteUnpackedRecord(pIdxKey);
|
||||
if( rc!=SQLITE_OK ) goto abort_due_to_error;
|
||||
if( res>0 ){
|
||||
pc = pOp->p2 - 1;
|
||||
@ -3212,7 +3211,7 @@ case OP_NotExists: { /* jump, in3 */
|
||||
assert( pIn3->flags & MEM_Int );
|
||||
assert( p->apCsr[i]->isTable );
|
||||
iKey = intToKey(pIn3->u.i);
|
||||
rc = sqlite3BtreeMoveto(pCrsr, 0, 0, iKey, 0,&res);
|
||||
rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0,&res);
|
||||
pC->lastRowid = pIn3->u.i;
|
||||
pC->rowidIsValid = res==0;
|
||||
pC->nullRow = 0;
|
||||
@ -3389,7 +3388,7 @@ case OP_NewRowid: { /* out2-prerelease */
|
||||
}
|
||||
if( v==0 ) continue;
|
||||
x = intToKey(v);
|
||||
rx = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)x, 0, &res);
|
||||
rx = sqlite3BtreeMovetoUnpacked(pC->pCursor, 0, (u64)x, 0, &res);
|
||||
cnt++;
|
||||
}while( cnt<100 && rx==SQLITE_OK && res==0 );
|
||||
db->priorNewRowid = v;
|
||||
@ -3885,10 +3884,9 @@ case OP_IdxDelete: {
|
||||
UnpackedRecord r;
|
||||
r.pKeyInfo = pC->pKeyInfo;
|
||||
r.nField = pOp->p3;
|
||||
r.needFree = 0;
|
||||
r.needDestroy = 0;
|
||||
r.flags = 0;
|
||||
r.aMem = &p->aMem[pOp->p2];
|
||||
rc = sqlite3BtreeMoveto(pCrsr, 0, &r, 0, 0, &res);
|
||||
rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
|
||||
if( rc==SQLITE_OK && res==0 ){
|
||||
rc = sqlite3BtreeDelete(pCrsr);
|
||||
}
|
||||
@ -3971,12 +3969,13 @@ case OP_IdxGE: { /* jump, in3 */
|
||||
assert( pOp->p4type==P4_INT32 );
|
||||
r.pKeyInfo = pC->pKeyInfo;
|
||||
r.nField = pOp->p4.i;
|
||||
r.needFree = 0;
|
||||
r.needDestroy = 0;
|
||||
if( pOp->p5 ){
|
||||
r.flags = UNPACKED_INCRKEY | UNPACKED_IGNORE_ROWID;
|
||||
}else{
|
||||
r.flags = UNPACKED_IGNORE_ROWID;
|
||||
}
|
||||
r.aMem = &p->aMem[pOp->p3];
|
||||
*pC->pIncrKey = pOp->p5;
|
||||
rc = sqlite3VdbeIdxKeyCompare(pC, &r, 0, 0, &res);
|
||||
*pC->pIncrKey = 0;
|
||||
rc = sqlite3VdbeIdxKeyCompare(pC, &r, &res);
|
||||
if( pOp->opcode==OP_IdxLT ){
|
||||
res = -res;
|
||||
}else{
|
||||
|
@ -15,7 +15,7 @@
|
||||
** 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.136 2008/08/13 14:07:41 drh Exp $
|
||||
** $Id: vdbe.h,v 1.137 2008/08/13 19:11:48 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITE_VDBE_H_
|
||||
#define _SQLITE_VDBE_H_
|
||||
@ -34,7 +34,6 @@ typedef struct Vdbe Vdbe;
|
||||
*/
|
||||
typedef struct VdbeFunc VdbeFunc;
|
||||
typedef struct Mem Mem;
|
||||
typedef struct UnpackedRecord UnpackedRecord;
|
||||
|
||||
/*
|
||||
** A single instruction of the virtual machine has an opcode
|
||||
@ -190,7 +189,7 @@ int sqlite3VdbeReleaseMemory(int);
|
||||
#endif
|
||||
UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,void*,int);
|
||||
void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*);
|
||||
int sqlite3VdbeRecordCompare(int,const void*,int,UnpackedRecord*);
|
||||
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
@ -15,7 +15,7 @@
|
||||
** 6000 lines long) it was split up into several smaller files and
|
||||
** this header information was factored out.
|
||||
**
|
||||
** $Id: vdbeInt.h,v 1.153 2008/08/02 03:50:39 drh Exp $
|
||||
** $Id: vdbeInt.h,v 1.154 2008/08/13 19:11:48 drh Exp $
|
||||
*/
|
||||
#ifndef _VDBEINT_H_
|
||||
#define _VDBEINT_H_
|
||||
@ -71,13 +71,11 @@ struct Cursor {
|
||||
Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */
|
||||
Bool isTable; /* True if a table requiring integer keys */
|
||||
Bool isIndex; /* True if an index containing keys only - no data */
|
||||
u8 bogusIncrKey; /* Something for pIncrKey to point to if pKeyInfo==0 */
|
||||
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
|
||||
Btree *pBt; /* Separate file holding temporary table */
|
||||
int nData; /* Number of bytes in pData */
|
||||
char *pData; /* Data for a NEW or OLD pseudo-table */
|
||||
i64 iKey; /* Key for the NEW or OLD pseudo-table row */
|
||||
u8 *pIncrKey; /* Pointer to pKeyInfo->incrKey */
|
||||
KeyInfo *pKeyInfo; /* Info about index keys needed by index cursors */
|
||||
int nField; /* Number of fields in the header */
|
||||
i64 seqCount; /* Sequence counter */
|
||||
@ -341,28 +339,6 @@ struct Vdbe {
|
||||
#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
|
||||
*/
|
||||
@ -387,10 +363,9 @@ int sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
|
||||
void sqlite3VdbeDeleteAuxData(VdbeFunc*, int);
|
||||
|
||||
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
|
||||
int sqlite3VdbeIdxKeyCompare(Cursor*,UnpackedRecord *,int,const unsigned char*,int*);
|
||||
int sqlite3VdbeIdxKeyCompare(Cursor*,UnpackedRecord*,int*);
|
||||
int sqlite3VdbeIdxRowid(BtCursor *, i64 *);
|
||||
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
|
||||
int sqlite3VdbeIdxRowidLen(const u8*, int, int*);
|
||||
int sqlite3VdbeExec(Vdbe*);
|
||||
int sqlite3VdbeList(Vdbe*);
|
||||
int sqlite3VdbeHalt(Vdbe*);
|
||||
|
102
src/vdbeaux.c
102
src/vdbeaux.c
@ -14,7 +14,7 @@
|
||||
** to version 2.8.7, all this code was combined into the vdbe.c source file.
|
||||
** But that file was getting too big so this subroutines were split out.
|
||||
**
|
||||
** $Id: vdbeaux.c,v 1.406 2008/08/13 14:07:41 drh Exp $
|
||||
** $Id: vdbeaux.c,v 1.407 2008/08/13 19:11:48 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@ -1850,9 +1850,8 @@ int sqlite3VdbeCursorMoveto(Cursor *p){
|
||||
extern int sqlite3_search_count;
|
||||
#endif
|
||||
assert( p->isTable );
|
||||
rc = sqlite3BtreeMoveto(p->pCursor, 0, 0, p->movetoTarget, 0, &res);
|
||||
rc = sqlite3BtreeMovetoUnpacked(p->pCursor, 0, p->movetoTarget, 0, &res);
|
||||
if( rc ) return rc;
|
||||
*p->pIncrKey = 0;
|
||||
p->lastRowid = keyToInt(p->movetoTarget);
|
||||
p->rowidIsValid = res==0;
|
||||
if( res<0 ){
|
||||
@ -2215,14 +2214,13 @@ UnpackedRecord *sqlite3VdbeRecordUnpack(
|
||||
if( nByte>szSpace ){
|
||||
p = sqlite3DbMallocRaw(pKeyInfo->db, nByte);
|
||||
if( p==0 ) return 0;
|
||||
p->needFree = 1;
|
||||
p->flags = UNPACKED_NEED_FREE | UNPACKED_NEED_DESTROY;
|
||||
}else{
|
||||
p = pSpace;
|
||||
p->needFree = 0;
|
||||
p->flags = UNPACKED_NEED_DESTROY;
|
||||
}
|
||||
p->pKeyInfo = pKeyInfo;
|
||||
p->nField = pKeyInfo->nField + 1;
|
||||
p->needDestroy = 1;
|
||||
p->aMem = pMem = &((Mem*)p)[1];
|
||||
idx = getVarint32(aKey, szHdr);
|
||||
d = szHdr;
|
||||
@ -2249,7 +2247,7 @@ UnpackedRecord *sqlite3VdbeRecordUnpack(
|
||||
*/
|
||||
void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
|
||||
if( p ){
|
||||
if( p->needDestroy ){
|
||||
if( p->flags & UNPACKED_NEED_DESTROY ){
|
||||
int i;
|
||||
Mem *pMem;
|
||||
for(i=0, pMem=p->aMem; i<p->nField; i++, pMem++){
|
||||
@ -2258,7 +2256,7 @@ void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
|
||||
}
|
||||
}
|
||||
}
|
||||
if( p->needFree ){
|
||||
if( p->flags & UNPACKED_NEED_FREE ){
|
||||
sqlite3DbFree(p->pKeyInfo->db, p);
|
||||
}
|
||||
}
|
||||
@ -2267,38 +2265,31 @@ void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){
|
||||
/*
|
||||
** This function compares the two table rows or index records
|
||||
** specified by {nKey1, pKey1} and pPKey2. It returns a negative, zero
|
||||
** or positive integer if {nKey1, pKey1} is less than, equal to or
|
||||
** greater than pPKey2. The {nKey1, pKey1} key must be a blob
|
||||
** or positive integer if key1 is less than, equal to or
|
||||
** greater than key2. The {nKey1, pKey1} key must be a blob
|
||||
** created by th OP_MakeRecord opcode of the VDBE. The pPKey2
|
||||
** key must be a parsed key such as obtained from
|
||||
** sqlite3VdbeParseRecord.
|
||||
**
|
||||
** Key1 and Key2 do not have to contain the same number of fields.
|
||||
** The key with fewer fields is usually considered lessor than the
|
||||
** longer. However if pPKey2->pKeyInfo->incrKey is set and
|
||||
** the common prefixes are equal, then key1 is less than key2.
|
||||
** Or if pPKey2->pKeyInfo->ckPrefixOnly flag is set and the
|
||||
** prefixes are equal, then the keys are considered to be equal and
|
||||
** The key with fewer fields is usually compares less than the
|
||||
** longer key. However if the UNPACKED_INCRKEY flags in pPKey2 is set
|
||||
** and the common prefixes are equal, then key1 is less than key2.
|
||||
** Or if the UNPACKED_MATCH_PREFIX flag is set and the prefixes are
|
||||
** equal, then the keys are considered to be equal and
|
||||
** the parts beyond the common prefix are ignored.
|
||||
**
|
||||
** The last nHdrIgnore1 bytes of the header of pKey1 are ignored,
|
||||
** as if they do not exist. Usually nHdrIgnore1 is 0 which means
|
||||
** that we look at the entire key. But sometimes nHdrIgnore1 is 1.
|
||||
** When nHdrIgnore1 is 1, the keys are index records and so the last
|
||||
** column is a rowid. The type code is always one byte in length.
|
||||
** Hence, setting nHdrIgnore1 to 1 means that the final rowid at the
|
||||
** end of the record should be treated as if it does not exist.
|
||||
**
|
||||
** Historical note: In earlier versions of this routine both Key1
|
||||
** and Key2 were blobs obtained from OP_MakeRecord. But we found
|
||||
** that in typical use the same Key2 would be submitted multiple times
|
||||
** in a row. So an optimization was added to parse the Key2 key
|
||||
** separately and submit the parsed version. In this way, we avoid
|
||||
** parsing the same Key2 multiple times.
|
||||
** If the UNPACKED_IGNORE_ROWID flag is set, then the last byte of
|
||||
** the header of pKey1 is ignored. It is assumed that pKey1 is
|
||||
** an index key, and thus ends with a rowid value. The last byte
|
||||
** of the header will therefore be the serial type of the rowid:
|
||||
** one of 1, 2, 3, 4, 5, 6, 8, or 9 - the integer serial types.
|
||||
** The serial type of the final rowid will always be a single byte.
|
||||
** By ignoring this last byte of the header, we force the comparison
|
||||
** to ignore the rowid at the end of key1.
|
||||
*/
|
||||
int sqlite3VdbeRecordCompare(
|
||||
int nKey1, const void *pKey1, /* Left key */
|
||||
int nHdrIgnore1, /* Omit this much from end of key1 header */
|
||||
UnpackedRecord *pPKey2 /* Right key */
|
||||
){
|
||||
u32 d1; /* Offset into aKey[] of next data element */
|
||||
@ -2319,7 +2310,9 @@ int sqlite3VdbeRecordCompare(
|
||||
|
||||
idx1 = getVarint32(aKey1, szHdr1);
|
||||
d1 = szHdr1;
|
||||
szHdr1 -= nHdrIgnore1;
|
||||
if( pPKey2->flags & UNPACKED_IGNORE_ROWID ){
|
||||
szHdr1--;
|
||||
}
|
||||
nField = pKeyInfo->nField;
|
||||
while( idx1<szHdr1 && i<pPKey2->nField ){
|
||||
u32 serial_type1;
|
||||
@ -2345,16 +2338,16 @@ int sqlite3VdbeRecordCompare(
|
||||
|
||||
if( rc==0 ){
|
||||
/* rc==0 here means that one of the keys ran out of fields and
|
||||
** all the fields up to that point were equal. If the incrKey
|
||||
** flag is true, then break the tie by treating the second key
|
||||
** as larger. If ckPrefixOnly is true, then keys with common prefixes
|
||||
** all the fields up to that point were equal. If the UNPACKED_INCRKEY
|
||||
** flag is set, then break the tie by treating key2 as larger.
|
||||
** If the UPACKED_PREFIX_MATCH flag is set, then keys with common prefixes
|
||||
** are considered to be equal. Otherwise, the longer key is the
|
||||
** larger. As it happens, the pPKey2 will always be the longer
|
||||
** if there is a difference.
|
||||
*/
|
||||
if( pKeyInfo->incrKey ){
|
||||
if( pPKey2->flags & UNPACKED_INCRKEY ){
|
||||
rc = -1;
|
||||
}else if( pKeyInfo->ckPrefixOnly ){
|
||||
}else if( pPKey2->flags & UNPACKED_PREFIX_MATCH ){
|
||||
/* Leave rc==0 */
|
||||
}else if( idx1<szHdr1 ){
|
||||
rc = 1;
|
||||
@ -2366,25 +2359,6 @@ int sqlite3VdbeRecordCompare(
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** The argument is an index entry composed using the OP_MakeRecord opcode.
|
||||
** The last entry in this record should be an integer (specifically
|
||||
** an integer rowid). This routine returns the number of bytes in
|
||||
** that integer.
|
||||
*/
|
||||
int sqlite3VdbeIdxRowidLen(const u8 *aKey, int nKey, int *pRowidLen){
|
||||
u32 szHdr; /* Size of the header */
|
||||
u32 typeRowid; /* Serial type of the rowid */
|
||||
|
||||
(void)getVarint32(aKey, szHdr);
|
||||
if( szHdr>nKey ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
(void)getVarint32(&aKey[szHdr-1], typeRowid);
|
||||
*pRowidLen = sqlite3VdbeSerialTypeLen(typeRowid);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@ -2437,15 +2411,12 @@ int sqlite3VdbeIdxRowid(BtCursor *pCur, i64 *rowid){
|
||||
int sqlite3VdbeIdxKeyCompare(
|
||||
Cursor *pC, /* The cursor to compare against */
|
||||
UnpackedRecord *pUnpacked, /* Unpacked version of pKey and nKey */
|
||||
int nKey, const u8 *pKey, /* The key to compare */
|
||||
int *res /* Write the comparison result here */
|
||||
){
|
||||
i64 nCellKey = 0;
|
||||
int rc;
|
||||
BtCursor *pCur = pC->pCursor;
|
||||
Mem m;
|
||||
UnpackedRecord *pRec;
|
||||
char zSpace[200];
|
||||
|
||||
sqlite3BtreeKeySize(pCur, &nCellKey);
|
||||
if( nCellKey<=0 ){
|
||||
@ -2459,19 +2430,8 @@ int sqlite3VdbeIdxKeyCompare(
|
||||
if( rc ){
|
||||
return rc;
|
||||
}
|
||||
if( !pUnpacked ){
|
||||
pRec = sqlite3VdbeRecordUnpack(pC->pKeyInfo, nKey, pKey,
|
||||
zSpace, sizeof(zSpace));
|
||||
}else{
|
||||
pRec = pUnpacked;
|
||||
}
|
||||
if( pRec==0 ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
*res = sqlite3VdbeRecordCompare(m.n, m.z, 1, pRec);
|
||||
if( !pUnpacked ){
|
||||
sqlite3VdbeDeleteUnpackedRecord(pRec);
|
||||
}
|
||||
assert( pUnpacked->flags & UNPACKED_IGNORE_ROWID );
|
||||
*res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
|
||||
sqlite3VdbeMemRelease(&m);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user