-C Update\ssome\stest\scases\sthat\sdeal\swith\scorrupt\sdatabases.
-D 2014-02-28T18:39:51.462
+C Remove\sthe\svdbeRecordCompareLargeHeader\sfunction.\sFix\ssome\sother\sdetails.
+D 2014-03-01T19:44:56.574
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
-F src/btree.c 77f175987c80ebec063f8653cb7d300776411413
+F src/btree.c d288e668614449571ec269535dc4aaf216a23db2
F src/btree.h 9e0f97c01b972f779eb7655cfb4f8727fd6dc26f
F src/btreeInt.h 0be66063468a520e4d66b80c7a1dc26d04ee6ea4
F src/build.c 00ce613bc2256e525c9195cb10d0df7bcc48d1f0
F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
-F src/sqliteInt.h 843e23d43ee2ab9369e68eb778815ba02835da59
+F src/sqliteInt.h b06500d391d4b7bf4c69fc110e37dd45719b760c
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
F src/vdbe.c ab910206dd8c9c5c1455f82953934bdbfe0bcc2a
-F src/vdbe.h 6833579fc0fbdc1c933e34519064841abda5b9b3
+F src/vdbe.h c6dc01f85cf3bdcc992d244aeff952c033fd5ad0
F src/vdbeInt.h 5286af9067cabdb8ba57b87c0c988a931be6c6c8
F src/vdbeapi.c 5bc41aaea448a7fc250902c418f1795859be3820
-F src/vdbeaux.c aad5345869c110f45074e2c1ca230e623b1ba182
+F src/vdbeaux.c da0979ce81ecdf3d018be9ee1e8998110181fb12
F src/vdbeblob.c d939997de046b8fcc607cfee4248f3d33dbcca50
F src/vdbemem.c 93fc3f13ebe6809ebaac8d0a17c812ec053ba233
-F src/vdbesort.c 72290f12428973c2c6b9d4f95ad0a7c8181e1280
+F src/vdbesort.c 46801acb342e5e4c07ba1777fe58880c143abb59
F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767
F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
-F src/where.c 6042e1a377cf7dc72c10493269ed75e276275cd8
+F src/where.c 36ef94b653a10944b39e34938ee4c758f3f42879
F src/whereInt.h 921f935af8b684ffb49705610bda7284db1db138
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
-P 284bde0ee20261737446eb8f5b6b36ad9bc3f355
-R 75b55639e7bdd048d8263d0acfa3cf8a
+P 3a09f5605ac7c6e503eb10acfdc607010414d917
+R b23b5e438c1d698174ad52d7cfba370e
U dan
-Z d116a418c5c97c83b8ebfe7a3e655c3c
+Z 35d9cecacf0cc917a2c2ed9a75b36eab
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 */
){
** 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 ){
}
+/*
+** 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:
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];
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 */
}
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;
}
/* 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;
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;
** (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 ){
}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 ){
}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;
}
}
}
- 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;
}
}
- 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;
}
/*
if( rc ){
return rc;
}
- *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
+ *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked, 0);
sqlite3VdbeMemRelease(&m);
return SQLITE_OK;
}