Merge the performance enhancements of trunk (and some obscure bug fixes)

into the sessions branch.

FossilOrigin-Name: 7f51ad97f0b24c57453d58faf25eee68861faa23
This commit is contained in:
drh
2014-03-04 14:34:14 +00:00
68 changed files with 3223 additions and 1426 deletions
+610 -57
View File
@@ -174,6 +174,9 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
#ifdef VDBE_PROFILE
pOp->cycles = 0;
pOp->cnt = 0;
#endif
#ifdef SQLITE_VDBE_COVERAGE
pOp->iSrcLine = 0;
#endif
return i;
}
@@ -536,7 +539,7 @@ VdbeOp *sqlite3VdbeTakeOpArray(Vdbe *p, int *pnOp, int *pnMaxArg){
** Add a whole list of operations to the operation stack. Return the
** address of the first operation added.
*/
int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp, int iLineno){
int addr;
assert( p->magic==VDBE_MAGIC_INIT );
if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p) ){
@@ -564,6 +567,11 @@ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
pOut->zComment = 0;
#endif
#ifdef SQLITE_VDBE_COVERAGE
pOut->iSrcLine = iLineno+i;
#else
(void)iLineno;
#endif
#ifdef SQLITE_DEBUG
if( p->db->flags & SQLITE_VdbeAddopTrace ){
sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]);
@@ -852,6 +860,15 @@ void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){
}
#endif /* NDEBUG */
#ifdef SQLITE_VDBE_COVERAGE
/*
** Set the value if the iSrcLine field for the previously coded instruction.
*/
void sqlite3VdbeSetLineNumber(Vdbe *v, int iLine){
sqlite3VdbeGetOp(v,-1)->iSrcLine = iLine;
}
#endif /* SQLITE_VDBE_COVERAGE */
/*
** Return the opcode for a given address. If the address is -1, then
** return the most recently inserted opcode.
@@ -1175,7 +1192,7 @@ void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
displayComment(pOp, zP4, zCom, sizeof(zCom));
#else
zCom[0] = 0
zCom[0] = 0;
#endif
/* NB: The sqlite3OpcodeName() function is implemented by code created
** by the mkopcodeh.awk and mkopcodec.awk scripts which extract the
@@ -1204,6 +1221,7 @@ static void releaseMemArray(Mem *p, int N){
}
for(pEnd=&p[N]; p<pEnd; p++){
assert( (&p[1])==pEnd || p[0].db==p[1].db );
assert( sqlite3VdbeCheckMemInvariants(p) );
/* This block is really an inlined version of sqlite3VdbeMemRelease()
** that takes advantage of the fact that the memory cell value is
@@ -1397,7 +1415,7 @@ int sqlite3VdbeList(
assert( p->db->mallocFailed );
return SQLITE_ERROR;
}
pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
pMem->flags = MEM_Str|MEM_Term;
zP4 = displayP4(pOp, pMem->z, 32);
if( zP4!=pMem->z ){
sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
@@ -1414,7 +1432,7 @@ int sqlite3VdbeList(
assert( p->db->mallocFailed );
return SQLITE_ERROR;
}
pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
pMem->flags = MEM_Str|MEM_Term;
pMem->n = 2;
sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */
pMem->memType = MEM_Str;
@@ -1426,7 +1444,7 @@ int sqlite3VdbeList(
assert( p->db->mallocFailed );
return SQLITE_ERROR;
}
pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
pMem->flags = MEM_Str|MEM_Term;
pMem->n = displayComment(pOp, zP4, pMem->z, 500);
pMem->memType = MEM_Str;
pMem->enc = SQLITE_UTF8;
@@ -2553,12 +2571,24 @@ int sqlite3VdbeReset(Vdbe *p){
fprintf(out, "%02x", p->aOp[i].opcode);
}
fprintf(out, "\n");
if( p->zSql ){
char c, pc = 0;
fprintf(out, "-- ");
for(i=0; (c = p->zSql[i])!=0; i++){
if( pc=='\n' ) fprintf(out, "-- ");
putc(c, out);
pc = c;
}
if( pc!='\n' ) fprintf(out, "\n");
}
for(i=0; i<p->nOp; i++){
fprintf(out, "%6d %10lld %8lld ",
char zHdr[100];
sqlite3_snprintf(sizeof(zHdr), zHdr, "%6u %12llu %8llu ",
p->aOp[i].cnt,
p->aOp[i].cycles,
p->aOp[i].cnt>0 ? p->aOp[i].cycles/p->aOp[i].cnt : 0
);
fprintf(out, "%s", zHdr);
sqlite3VdbePrintOp(out, i, &p->aOp[i]);
}
fclose(out);
@@ -2913,6 +2943,14 @@ u32 sqlite3VdbeSerialPut(u8 *buf, Mem *pMem, u32 serial_type){
return 0;
}
/* Input "x" is a sequence of unsigned characters that represent a
** big-endian integer. Return the equivalent native integer
*/
#define ONE_BYTE_INT(x) ((i8)(x)[0])
#define TWO_BYTE_INT(x) (256*(i8)((x)[0])|(x)[1])
#define THREE_BYTE_INT(x) (65536*(i8)((x)[0])|((x)[1]<<8)|(x)[2])
#define FOUR_BYTE_UINT(x) (((u32)(x)[0]<<24)|((x)[1]<<16)|((x)[2]<<8)|(x)[3])
/*
** Deserialize the data blob pointed to by buf as serial type serial_type
** and store the result in pMem. Return the number of bytes read.
@@ -2924,7 +2962,6 @@ u32 sqlite3VdbeSerialGet(
){
u64 x;
u32 y;
int i;
switch( serial_type ){
case 10: /* Reserved for future use */
case 11: /* Reserved for future use */
@@ -2933,33 +2970,28 @@ u32 sqlite3VdbeSerialGet(
break;
}
case 1: { /* 1-byte signed integer */
pMem->u.i = (signed char)buf[0];
pMem->u.i = ONE_BYTE_INT(buf);
pMem->flags = MEM_Int;
return 1;
}
case 2: { /* 2-byte signed integer */
i = 256*(signed char)buf[0] | buf[1];
pMem->u.i = (i64)i;
pMem->u.i = TWO_BYTE_INT(buf);
pMem->flags = MEM_Int;
return 2;
}
case 3: { /* 3-byte signed integer */
i = 65536*(signed char)buf[0] | (buf[1]<<8) | buf[2];
pMem->u.i = (i64)i;
pMem->u.i = THREE_BYTE_INT(buf);
pMem->flags = MEM_Int;
return 3;
}
case 4: { /* 4-byte signed integer */
y = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
y = FOUR_BYTE_UINT(buf);
pMem->u.i = (i64)*(int*)&y;
pMem->flags = MEM_Int;
return 4;
}
case 5: { /* 6-byte signed integer */
x = 256*(signed char)buf[0] + buf[1];
y = ((unsigned)buf[2]<<24) | (buf[3]<<16) | (buf[4]<<8) | buf[5];
x = (x<<32) | y;
pMem->u.i = *(i64*)&x;
pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf);
pMem->flags = MEM_Int;
return 6;
}
@@ -2977,8 +3009,8 @@ u32 sqlite3VdbeSerialGet(
swapMixedEndianFloat(t2);
assert( sizeof(r1)==sizeof(t2) && memcmp(&r1, &t2, sizeof(r1))==0 );
#endif
x = ((unsigned)buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
y = ((unsigned)buf[4]<<24) | (buf[5]<<16) | (buf[6]<<8) | buf[7];
x = FOUR_BYTE_UINT(buf);
y = FOUR_BYTE_UINT(buf+4);
x = (x<<32) | y;
if( serial_type==6 ){
pMem->u.i = *(i64*)&x;
@@ -3074,7 +3106,7 @@ void sqlite3VdbeRecordUnpack(
u32 szHdr;
Mem *pMem = p->aMem;
p->flags = 0;
p->default_rc = 0;
assert( EIGHT_BYTE_ALIGNMENT(pMem) );
idx = getVarint32(aKey, szHdr);
d = szHdr;
@@ -3096,26 +3128,18 @@ 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.
*/
int sqlite3VdbeRecordCompare(
static int vdbeRecordCompareDebug(
int nKey1, const void *pKey1, /* Left key */
UnpackedRecord *pPKey2 /* Right key */
const UnpackedRecord *pPKey2 /* Right key */
){
u32 d1; /* Offset into aKey[] of next data element */
u32 idx1; /* Offset into aKey[] of next header element */
@@ -3189,24 +3213,554 @@ int sqlite3VdbeRecordCompare(
assert( mem1.zMalloc==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 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.
** all the fields up to that point were equal. Return the the default_rc
** 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 CollSeq *pColl
){
if( pMem1->enc==pColl->enc ){
/* The strings are already in the correct encoding. Call the
** comparison function directly */
return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z);
}else{
int rc;
const void *v1, *v2;
int n1, n2;
Mem c1;
Mem c2;
memset(&c1, 0, sizeof(c1));
memset(&c2, 0, sizeof(c2));
sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
n1 = v1==0 ? 0 : c1.n;
v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
n2 = v2==0 ? 0 : c2.n;
rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
sqlite3VdbeMemRelease(&c1);
sqlite3VdbeMemRelease(&c2);
return rc;
}
}
/*
** Compare the values contained by the two memory cells, returning
** negative, zero or positive if pMem1 is less than, equal to, or greater
** than pMem2. Sorting order is NULL's first, followed by numbers (integers
** and reals) sorted numerically, followed by text ordered by the collating
** sequence pColl and finally blob's ordered by memcmp().
**
** Two NULL values are considered equal by this function.
*/
int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){
int rc;
int f1, f2;
int combined_flags;
f1 = pMem1->flags;
f2 = pMem2->flags;
combined_flags = f1|f2;
assert( (combined_flags & MEM_RowSet)==0 );
/* If one value is NULL, it is less than the other. If both values
** are NULL, return 0.
*/
assert( rc==0 );
if( pPKey2->flags & UNPACKED_INCRKEY ){
rc = -1;
}else if( pPKey2->flags & UNPACKED_PREFIX_MATCH ){
/* Leave rc==0 */
}else if( idx1<szHdr1 ){
rc = 1;
if( combined_flags&MEM_Null ){
return (f2&MEM_Null) - (f1&MEM_Null);
}
/* If one value is a number and the other is not, the number is less.
** If both are numbers, compare as reals if one is a real, or as integers
** if both values are integers.
*/
if( combined_flags&(MEM_Int|MEM_Real) ){
double r1, r2;
if( (f1 & f2 & MEM_Int)!=0 ){
if( pMem1->u.i < pMem2->u.i ) return -1;
if( pMem1->u.i > pMem2->u.i ) return 1;
return 0;
}
if( (f1&MEM_Real)!=0 ){
r1 = pMem1->r;
}else if( (f1&MEM_Int)!=0 ){
r1 = (double)pMem1->u.i;
}else{
return 1;
}
if( (f2&MEM_Real)!=0 ){
r2 = pMem2->r;
}else if( (f2&MEM_Int)!=0 ){
r2 = (double)pMem2->u.i;
}else{
return -1;
}
if( r1<r2 ) return -1;
if( r1>r2 ) return 1;
return 0;
}
/* If one value is a string and the other is a blob, the string is less.
** If both are strings, compare using the collating functions.
*/
if( combined_flags&MEM_Str ){
if( (f1 & MEM_Str)==0 ){
return 1;
}
if( (f2 & MEM_Str)==0 ){
return -1;
}
assert( pMem1->enc==pMem2->enc );
assert( pMem1->enc==SQLITE_UTF8 ||
pMem1->enc==SQLITE_UTF16LE || pMem1->enc==SQLITE_UTF16BE );
/* The collation sequence must be defined at this point, even if
** the user deletes the collation sequence after the vdbe program is
** compiled (this was not always the case).
*/
assert( !pColl || pColl->xCmp );
if( pColl ){
return vdbeCompareMemString(pMem1, pMem2, pColl);
}
/* If a NULL pointer was passed as the collate function, fall through
** to the blob case and use memcmp(). */
}
/* Both values must be blobs. Compare using memcmp(). */
rc = memcmp(pMem1->z, pMem2->z, (pMem1->n>pMem2->n)?pMem2->n:pMem1->n);
if( rc==0 ){
rc = pMem1->n - pMem2->n;
}
return rc;
}
/*
** 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){
u32 y;
assert( CORRUPT_DB || (serial_type>=1 && serial_type<=9 && serial_type!=7) );
switch( serial_type ){
case 0:
case 1:
return ONE_BYTE_INT(aKey);
case 2:
return TWO_BYTE_INT(aKey);
case 3:
return THREE_BYTE_INT(aKey);
case 4: {
y = FOUR_BYTE_UINT(aKey);
return (i64)*(int*)&y;
}
case 5: {
return FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey);
}
case 6: {
u64 x = FOUR_BYTE_UINT(aKey);
x = (x<<32) | FOUR_BYTE_UINT(aKey+4);
return (i64)*(i64*)&x;
}
}
return (serial_type - 8);
}
/*
** 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 */
const UnpackedRecord *pPKey2, /* Right key */
int bSkip /* If true, skip the first field */
){
u32 d1; /* Offset into aKey[] of next data element */
int i; /* Index of next field to compare */
u32 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;
/* 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( bSkip ){
u32 s1;
idx1 = 1 + getVarint32(&aKey1[1], 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 */
assert( pPKey2->pKeyInfo->nField+pPKey2->pKeyInfo->nXField>=pPKey2->nField
|| CORRUPT_DB );
assert( pPKey2->pKeyInfo->aSortOrder!=0 );
assert( pPKey2->pKeyInfo->nField>0 );
assert( idx1<=szHdr1 || CORRUPT_DB );
do{
u32 serial_type;
/* RHS is an integer */
if( pRhs->flags & MEM_Int ){
serial_type = aKey1[idx1];
if( serial_type>=12 ){
rc = +1;
}else if( serial_type==0 ){
rc = -1;
}else if( serial_type==7 ){
double rhs = (double)pRhs->u.i;
sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
if( mem1.r<rhs ){
rc = -1;
}else if( mem1.r>rhs ){
rc = +1;
}
}else{
i64 lhs = vdbeRecordDecodeInt(serial_type, &aKey1[d1]);
i64 rhs = pRhs->u.i;
if( lhs<rhs ){
rc = -1;
}else if( lhs>rhs ){
rc = +1;
}
}
}
/* RHS is real */
else if( pRhs->flags & MEM_Real ){
serial_type = aKey1[idx1];
if( serial_type>=12 ){
rc = +1;
}else if( serial_type==0 ){
rc = -1;
}else{
double rhs = pRhs->r;
double lhs;
sqlite3VdbeSerialGet(&aKey1[d1], serial_type, &mem1);
if( serial_type==7 ){
lhs = mem1.r;
}else{
lhs = (double)mem1.u.i;
}
if( lhs<rhs ){
rc = -1;
}else if( lhs>rhs ){
rc = +1;
}
}
}
/* RHS is a string */
else if( pRhs->flags & MEM_Str ){
getVarint32(&aKey1[idx1], serial_type);
if( serial_type<12 ){
rc = -1;
}else if( !(serial_type & 0x01) ){
rc = +1;
}else{
mem1.n = (serial_type - 12) / 2;
if( (d1+mem1.n) > (unsigned)nKey1 ){
rc = 1; /* Corruption */
}else if( pKeyInfo->aColl[i] ){
mem1.enc = pKeyInfo->enc;
mem1.db = pKeyInfo->db;
mem1.flags = MEM_Str;
mem1.z = (char*)&aKey1[d1];
rc = vdbeCompareMemString(&mem1, pRhs, pKeyInfo->aColl[i]);
}else{
int nCmp = MIN(mem1.n, pRhs->n);
rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
if( rc==0 ) rc = mem1.n - pRhs->n;
}
}
}
/* RHS is a blob */
else if( pRhs->flags & MEM_Blob ){
getVarint32(&aKey1[idx1], serial_type);
if( serial_type<12 || (serial_type & 0x01) ){
rc = -1;
}else{
int nStr = (serial_type - 12) / 2;
if( (d1+nStr) > (unsigned)nKey1 ){
rc = 1; /* Corruption */
}else{
int nCmp = MIN(nStr, pRhs->n);
rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
if( rc==0 ) rc = nStr - pRhs->n;
}
}
}
/* RHS is null */
else{
serial_type = aKey1[idx1];
rc = (serial_type!=0);
}
if( rc!=0 ){
if( pKeyInfo->aSortOrder[i] ){
rc = -rc;
}
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;
}
i++;
pRhs++;
d1 += sqlite3VdbeSerialTypeLen(serial_type);
idx1 += sqlite3VarintLen(serial_type);
}while( idx1<(unsigned)szHdr1 && i<pPKey2->nField && d1<=(unsigned)nKey1 );
/* 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). */
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( 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 */
const UnpackedRecord *pPKey2, /* Right key */
int bSkip /* Ignored */
){
const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F];
int serial_type = ((const u8*)pKey1)[1];
int res;
u32 y;
u64 x;
i64 v = pPKey2->aMem[0].u.i;
i64 lhs;
UNUSED_PARAMETER(bSkip);
assert( bSkip==0 );
switch( serial_type ){
case 1: { /* 1-byte signed integer */
lhs = ONE_BYTE_INT(aKey);
break;
}
case 2: { /* 2-byte signed integer */
lhs = TWO_BYTE_INT(aKey);
break;
}
case 3: { /* 3-byte signed integer */
lhs = THREE_BYTE_INT(aKey);
break;
}
case 4: { /* 4-byte signed integer */
y = FOUR_BYTE_UINT(aKey);
lhs = (i64)*(int*)&y;
break;
}
case 5: { /* 6-byte signed integer */
lhs = FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey);
break;
}
case 6: { /* 8-byte signed integer */
x = FOUR_BYTE_UINT(aKey);
x = (x<<32) | FOUR_BYTE_UINT(aKey+4);
lhs = *(i64*)&x;
break;
}
case 8:
lhs = 0;
break;
case 9:
lhs = 1;
break;
/* This case could be removed without changing the results of running
** this code. Including it causes gcc to generate a faster switch
** statement (since the range of switch targets now starts at zero and
** is contiguous) but does not cause any duplicate code to be generated
** (as gcc is clever enough to combine the two like cases). Other
** compilers might be similar. */
case 0: case 7:
return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0);
default:
return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 0);
}
if( v>lhs ){
res = pPKey2->r1;
}else if( v<lhs ){
res = pPKey2->r2;
}else if( pPKey2->nField>1 ){
/* The first fields of the two keys are equal. Compare the trailing
** fields. */
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 && 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 */
const UnpackedRecord *pPKey2, /* Right key */
int bSkip
){
const u8 *aKey1 = (const u8*)pKey1;
int serial_type;
int res;
UNUSED_PARAMETER(bSkip);
assert( bSkip==0 );
getVarint32(&aKey1[1], serial_type);
if( serial_type<12 ){
res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */
}else if( !(serial_type & 0x01) ){
res = pPKey2->r2; /* (pKey1/nKey1) is a blob */
}else{
int nCmp;
int nStr;
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[szHdr], pPKey2->aMem[0].z, nCmp);
if( res==0 ){
res = nStr - pPKey2->aMem[0].n;
if( res==0 ){
if( pPKey2->nField>1 ){
res = sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2, 1);
}else{
res = pPKey2->default_rc;
}
}else if( res>0 ){
res = pPKey2->r2;
}else{
res = pPKey2->r1;
}
}else if( res>0 ){
res = pPKey2->r2;
}else{
res = pPKey2->r1;
}
}
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;
}
/*
** 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){
/* varintRecordCompareInt() and varintRecordCompareString() both assume
** that the size-of-header varint that occurs at the start of each record
** fits in a single byte (i.e. is 127 or less). varintRecordCompareInt()
** also assumes that it is safe to overread a buffer by at least the
** maximum possible legal header size plus 8 bytes. Because there is
** guaranteed to be at least 74 (but not 136) bytes of padding following each
** buffer passed to varintRecordCompareInt() this makes it convenient to
** limit the size of the header to 64 bytes in cases where the first field
** is an integer.
**
** The easiest way to enforce this limit is to consider only records with
** 13 fields or less. If the first field is an integer, the maximum legal
** header size is (12*5 + 1 + 1) bytes. */
if( (p->pKeyInfo->nField + p->pKeyInfo->nXField)<=13 ){
int flags = p->aMem[0].flags;
if( p->pKeyInfo->aSortOrder[0] ){
p->r1 = 1;
p->r2 = -1;
}else{
p->r1 = -1;
p->r2 = 1;
}
if( (flags & MEM_Int) ){
return vdbeRecordCompareInt;
}
if( (flags & (MEM_Int|MEM_Real|MEM_Null|MEM_Blob))==0
&& p->pKeyInfo->aColl[0]==0
){
return vdbeRecordCompareString;
}
}
return sqlite3VdbeRecordCompare;
}
/*
** pCur points at an index entry created using the OP_MakeRecord opcode.
@@ -3297,9 +3851,9 @@ idx_rowid_corruption:
** of the keys prior to the final rowid, not the entire key.
*/
int sqlite3VdbeIdxKeyCompare(
VdbeCursor *pC, /* The cursor to compare against */
UnpackedRecord *pUnpacked, /* Unpacked version of key to compare against */
int *res /* Write the comparison result here */
VdbeCursor *pC, /* The cursor to compare against */
const UnpackedRecord *pUnpacked, /* Unpacked version of key */
int *res /* Write the comparison result here */
){
i64 nCellKey = 0;
int rc;
@@ -3309,7 +3863,7 @@ int sqlite3VdbeIdxKeyCompare(
assert( sqlite3BtreeCursorIsValid(pCur) );
VVA_ONLY(rc =) sqlite3BtreeKeySize(pCur, &nCellKey);
assert( rc==SQLITE_OK ); /* pCur is always valid so KeySize cannot fail */
/* nCellKey will always be between 0 and 0xffffffff because of the say
/* nCellKey will always be between 0 and 0xffffffff because of the way
** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
if( nCellKey<=0 || nCellKey>0x7fffffff ){
*res = 0;
@@ -3320,8 +3874,7 @@ int sqlite3VdbeIdxKeyCompare(
if( rc ){
return rc;
}
assert( pUnpacked->flags & UNPACKED_PREFIX_MATCH );
*res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
*res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked, 0);
sqlite3VdbeMemRelease(&m);
return SQLITE_OK;
}