Remove the vdbeRecordCompareLargeHeader function. Fix some other details.

FossilOrigin-Name: 3861e853105cb8da344c7eebd2e455622b26395e
This commit is contained in:
dan
2014-03-01 19:44:56 +00:00
parent 597515d70c
commit 3833e934d3
8 changed files with 142 additions and 141 deletions
+115 -111
View File
@@ -3123,24 +3123,16 @@ void sqlite3VdbeRecordUnpack(
p->nField = u;
}
#if SQLITE_DEBUG
/*
** 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 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 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.
** This function compares two index or table record keys in the same way
** as the sqlite3VdbeRecordCompare() routine. Unlike VdbeRecordCompare(),
** this function deserializes and compares values using the
** sqlite3VdbeSerialGet() and sqlite3MemCompare() functions. It is used
** in assert() statements to ensure that the optimized code in
** sqlite3VdbeRecordCompare() returns results with these two primitives.
*/
static int vdbeRecordComparePrev(
static int vdbeRecordCompareDebug(
int nKey1, const void *pKey1, /* Left key */
UnpackedRecord *pPKey2 /* Right key */
){
@@ -3220,10 +3212,17 @@ static int vdbeRecordComparePrev(
** value. */
return pPKey2->default_rc;
}
#endif
/*
** Both *pMem1 and *pMem2 contain string values. Compare the two values
** using the collation sequence pColl. As usual, return a negative , zero
** or positive value if *pMem1 is less than, equal to or greater than
** *pMem2, respectively. Similar in spirit to "rc = (*pMem1) - (*pMem2);".
*/
static int vdbeCompareMemString(
const Mem *pMem1,
const Mem *pMem2,
const Mem *pMem1,
const Mem *pMem2,
const CollSeq *pColl
){
if( pMem1->enc==pColl->enc ){
@@ -3344,8 +3343,17 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
}
/*
** The first argument passed to this function is a serial-type that
** corresponds to an integer - all values between 1 and 9 inclusive
** except 7. The second points to a buffer containing an integer value
** serialized according to serial_type. This function deserializes
** and returns the value.
*/
static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
assert( CORRUPT_DB || (serial_type>=1 && serial_type<=9 && serial_type!=7) );
switch( serial_type ){
case 0:
case 1:
return (char)aKey[0];
case 2:
@@ -3354,13 +3362,11 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
return ((char)aKey[0] << 16) | (aKey[1] << 8) | aKey[2];
case 4:
return ((char)aKey[0]<<24) | (aKey[1]<<16) | (aKey[2]<<8)| aKey[3];
case 5: {
i64 msw = ((char)aKey[0]<<24)|(aKey[1]<<16)|(aKey[2]<<8)|aKey[3];
u32 lsw = (aKey[4] << 8) | aKey[5];
return (i64)( msw << 16 | (u64)lsw );
}
case 6: {
i64 msw = ((char)aKey[0]<<24)|(aKey[1]<<16)|(aKey[2]<<8)|aKey[3];
u32 lsw = ((unsigned)aKey[4]<<24)|(aKey[5]<<16)|(aKey[6]<<8)|aKey[7];
@@ -3371,36 +3377,51 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
return (serial_type - 8);
}
static int vdbeRecordCompare(
int nKey1, const void *pKey1, /* Left key */
int szHdr1, /* Size of record header in bytes */
u32 idx1, /* Offset of first type in header */
UnpackedRecord *const pPKey2 /* Right key */
/*
** 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 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.
**
** If argument bSkip is non-zero, it is assumed that the caller has already
** determined that the first fields of the keys are equal.
**
** Key1 and Key2 do not have to contain the same number of fields. If all
** fields that appear in both keys are equal, then pPKey2->default_rc is
** returned.
*/
int sqlite3VdbeRecordCompare(
int nKey1, const void *pKey1, /* Left key */
UnpackedRecord *const pPKey2, /* Right key */
int bSkip /* If true, skip the first field */
){
u32 d1 = szHdr1; /* Offset into aKey[] of next data element */
int i = 0;
int rc = 0;
Mem *pRhs = pPKey2->aMem;
u32 d1; /* Offset into aKey[] of next data element */
int i; /* Index of next field to compare */
int szHdr1; /* Size of record header in bytes */
u32 idx1; /* Offset of first type in header */
int rc = 0; /* Return value */
Mem *pRhs = pPKey2->aMem; /* Next field of pPKey2 to compare */
KeyInfo *pKeyInfo = pPKey2->pKeyInfo;
const unsigned char *aKey1 = (const unsigned char *)pKey1;
Mem mem1;
#ifdef SQLITE_DEBUG
int expected = vdbeRecordComparePrev(nKey1, pKey1, pPKey2);
static int nCall = 0;
nCall++;
#endif
/* If idx==0, then the caller has already determined that the first two
** elements in the keys are equal. Fix the various stack variables so
/* If bSkip is true, then the caller has already determined that the first
** two elements in the keys are equal. Fix the various stack variables so
** that this routine begins comparing at the second field. */
if( idx1==0 ){
if( bSkip ){
u32 s1;
assert( sqlite3VarintLen(szHdr1)==1 );
idx1 = 1 + getVarint32(&aKey1[1], s1);
d1 += sqlite3VdbeSerialTypeLen(s1);
szHdr1 = aKey1[0];
d1 = szHdr1 + sqlite3VdbeSerialTypeLen(s1);
i = 1;
pRhs++;
}else{
idx1 = getVarint32(aKey1, szHdr1);
d1 = szHdr1;
i = 0;
}
VVA_ONLY( mem1.zMalloc = 0; ) /* Only needed by assert() statements */
@@ -3511,18 +3532,14 @@ static int vdbeRecordCompare(
}
if( rc!=0 ){
assert( mem1.zMalloc==0 ); /* See comment below */
if( pKeyInfo->aSortOrder[i] ){
rc = -rc;
#if 0
assert( (rc>0 && (rc^(int)0x80000000)<0)
|| (rc<0 && (rc^(int)0x80000000)>0) );
assert( sizeof(int)==4 );
rc ^= (int)0x80000000; /* similar in spirit to: "rc = -rc;" */
assert( rc!=0 );
#endif
}
assert( (rc<0 && expected<0) || (rc>0 && expected>0) || CORRUPT_DB );
assert( CORRUPT_DB
|| (rc<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
|| (rc>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
);
assert( mem1.zMalloc==0 ); /* See comment below */
return rc;
}
@@ -3534,31 +3551,38 @@ static int vdbeRecordCompare(
/* No memory allocation is ever used on mem1. Prove this using
** the following assert(). If the assert() fails, it indicates a
** memory leak and a need to call sqlite3VdbeMemRelease(&mem1).
*/
** memory leak and a need to call sqlite3VdbeMemRelease(&mem1). */
assert( mem1.zMalloc==0 );
/* rc==0 here means that one or both of the keys ran out of fields and
** all the fields up to that point were equal. Return the the default_rc
** value. */
assert( pPKey2->default_rc==expected );
assert( CORRUPT_DB
|| pPKey2->default_rc==vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)
);
return pPKey2->default_rc;
}
/*
** This function is an optimized version of sqlite3VdbeRecordCompare()
** that (a) the first field of pPKey2 is an integer, and (b) the
** size-of-header varint at the start of (pKey1/nKey1) fits in a single
** byte (i.e. is less than 128).
*/
static int vdbeRecordCompareInt(
int nKey1, const void *pKey1, /* Left key */
int szHdr,
u32 idx1,
UnpackedRecord *pPKey2 /* Right key */
UnpackedRecord *pPKey2, /* Right key */
int bSkip /* Ignored */
){
const u8 *aKey = &((const u8*)pKey1)[szHdr];
const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1];
int serial_type = ((const u8*)pKey1)[1];
int res;
i64 v = pPKey2->aMem[0].u.i;
i64 lhs;
switch( serial_type ){
assert( bSkip==0 );
switch( serial_type ){
case 1:
lhs = (char)(aKey[0]);
break;
@@ -3571,25 +3595,21 @@ static int vdbeRecordCompareInt(
case 4:
lhs = (int)(((u32)aKey[0]<<24) | (aKey[1]<<16) | (aKey[2]<<8)| aKey[3]);
break;
case 5: {
i64 msw = ((char)aKey[0]<<24)|(aKey[1]<<16)|(aKey[2]<<8)|aKey[3];
u32 lsw = (aKey[4] << 8) | aKey[5];
lhs = (i64)( msw << 16 | (u64)lsw );
break;
}
case 6: {
i64 msw = ((char)aKey[0]<<24)|(aKey[1]<<16)|(aKey[2]<<8)|aKey[3];
u32 lsw = ((unsigned)aKey[4]<<24)|(aKey[5]<<16)|(aKey[6]<<8)|aKey[7];
lhs = (i64)( msw << 32 | (u64)lsw );
break;
}
case 8:
lhs = 0;
break;
case 9:
lhs = 1;
break;
@@ -3601,10 +3621,10 @@ static int vdbeRecordCompareInt(
** (as gcc is clever enough to combine the two like cases). Other
** compilers might be similar. */
case 0: case 7:
return vdbeRecordCompare(nKey1, pKey1, szHdr, 1, pPKey2);
return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0);
default:
return vdbeRecordCompare(nKey1, pKey1, szHdr, 1, pPKey2);
return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0);
}
if( v>lhs ){
@@ -3614,31 +3634,37 @@ static int vdbeRecordCompareInt(
}else if( pPKey2->nField>1 ){
/* The first fields of the two keys are equal. Compare the trailing
** fields. */
res = vdbeRecordCompare(nKey1, pKey1, szHdr, 0, pPKey2);
res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1);
}else{
/* The first fields of the two keys are equal and there are no trailing
** fields. Return pPKey2->default_rc in this case. */
res = pPKey2->default_rc;
}
assert( (res==0 && vdbeRecordComparePrev(nKey1, pKey1, pPKey2)==0)
|| (res<0 && vdbeRecordComparePrev(nKey1, pKey1, pPKey2)<0)
|| (res>0 && vdbeRecordComparePrev(nKey1, pKey1, pPKey2)>0)
assert( (res==0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)==0)
|| (res<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
|| (res>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
|| CORRUPT_DB
);
return res;
}
/*
** This function is an optimized version of sqlite3VdbeRecordCompare()
** that (a) the first field of pPKey2 is a string, that (b) the first field
** uses the collation sequence BINARY and (c) that the size-of-header varint
** at the start of (pKey1/nKey1) fits in a single byte.
*/
static int vdbeRecordCompareString(
int nKey1, const void *pKey1, /* Left key */
int szHdr,
u32 idx1,
UnpackedRecord *pPKey2 /* Right key */
UnpackedRecord *pPKey2, /* Right key */
int bSkip
){
const u8 *aKey1 = (const u8*)pKey1;
int serial_type;
int res;
assert( bSkip==0 );
getVarint32(&aKey1[1], serial_type);
if( serial_type<12 ){
@@ -3648,18 +3674,18 @@ static int vdbeRecordCompareString(
}else{
int nCmp;
int nStr;
aKey1 = &aKey1[szHdr];
int szHdr = aKey1[0];
nStr = (serial_type-12) / 2;
if( (szHdr + nStr) > nKey1 ) return 0; /* Corruption */
nCmp = MIN( pPKey2->aMem[0].n, nStr );
res = memcmp(aKey1, pPKey2->aMem[0].z, nCmp);
res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp);
if( res==0 ){
res = nStr - pPKey2->aMem[0].n;
if( res==0 ){
if( pPKey2->nField>1 ){
res = vdbeRecordCompare(nKey1, pKey1, szHdr, 0, pPKey2);
res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1);
}else{
res = pPKey2->default_rc;
}
@@ -3675,30 +3701,26 @@ static int vdbeRecordCompareString(
}
}
assert( (res==0 && sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2)==0)
|| (res<0 && sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2)<0)
|| (res>0 && sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2)>0)
assert( (res==0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)==0)
|| (res<0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)<0)
|| (res>0 && vdbeRecordCompareDebug(nKey1, pKey1, pPKey2)>0)
|| CORRUPT_DB
);
return res;
}
int vdbeRecordCompareLargeHeader(
int nKey1, const void *pKey1, /* Left key */
int dummy1, u32 dummy2, /* Unused arguments */
UnpackedRecord *pPKey2 /* Right key */
){
int szHdr;
u32 idx1;
idx1 = getVarint32(((u8*)pKey1), szHdr);
return vdbeRecordCompare(nKey1, pKey1, szHdr, idx1, pPKey2);
}
/*
** Return a pointer to an sqlite3VdbeRecordCompare() compatible function
** suitable for comparing serialized records to the unpacked record passed
** as the only argument.
*/
RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){
if( (p->pKeyInfo->nField + p->pKeyInfo->nXField) > 10 ){
return vdbeRecordCompareLargeHeader;
}else{
/* As the varints that make up a record header are all 5 bytes in size
** or less, if the binary keys being compared have 25 or fewer fields
** then it is guaranteed that the varint at the start of every record
** (the record-header size in bytes) fits in a single byte. If this
** is not the case, then sqlite3VdbeRecordCompare() must be used. */
if( (p->pKeyInfo->nField + p->pKeyInfo->nXField)<=25 ){
int flags = p->aMem[0].flags;
if( p->pKeyInfo->aSortOrder[0] ){
p->r1 = 1;
@@ -3717,25 +3739,7 @@ RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){
}
}
return vdbeRecordCompare;
}
RecordCompare sqlite3VdbeFindSorterCompare(KeyInfo *pKeyInfo){
if( (pKeyInfo->nField + pKeyInfo->nXField) > 10 ){
return vdbeRecordCompareLargeHeader;
}
return vdbeRecordCompare;
}
int sqlite3VdbeRecordCompare(
int nKey1, const void *pKey1, /* Left key */
UnpackedRecord *pPKey2 /* Right key */
){
int szHdr;
u32 idx1;
idx1 = getVarint32(((u8*)pKey1), szHdr);
return vdbeRecordCompare(nKey1, pKey1, szHdr, idx1, pPKey2);
return sqlite3VdbeRecordCompare;
}
/*
@@ -3850,7 +3854,7 @@ int sqlite3VdbeIdxKeyCompare(
if( rc ){
return rc;
}
*res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
*res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked, 0);
sqlite3VdbeMemRelease(&m);
return SQLITE_OK;
}