Merge the latest changes from trunk.

FossilOrigin-Name: 3047a25f1c41e83f0b4772f7c36fbfec0f12dc7e
This commit is contained in:
drh
2014-03-28 18:35:39 +00:00
12 changed files with 131 additions and 67 deletions
+3
View File
@@ -4588,6 +4588,7 @@ int sqlite3BtreeMovetoUnpacked(
if( pIdxKey ){
xRecordCompare = sqlite3VdbeFindCompare(pIdxKey);
pIdxKey->isCorrupt = 0;
assert( pIdxKey->default_rc==1
|| pIdxKey->default_rc==0
|| pIdxKey->default_rc==-1
@@ -4711,6 +4712,7 @@ int sqlite3BtreeMovetoUnpacked(
c = xRecordCompare(nCell, pCellKey, pIdxKey, 0);
sqlite3_free(pCellKey);
}
assert( pIdxKey->isCorrupt==0 || c==0 );
if( c<0 ){
lwr = idx+1;
}else if( c>0 ){
@@ -4720,6 +4722,7 @@ int sqlite3BtreeMovetoUnpacked(
*pRes = 0;
rc = SQLITE_OK;
pCur->aiIdx[pCur->iPage] = (u16)idx;
if( pIdxKey->isCorrupt ) rc = SQLITE_CORRUPT;
goto moveto_finish;
}
if( lwr>upr ) break;
+1
View File
@@ -1627,6 +1627,7 @@ struct UnpackedRecord {
KeyInfo *pKeyInfo; /* Collation and sort-order information */
u16 nField; /* Number of entries in apMem[] */
i8 default_rc; /* Comparison result if keys are equal */
u8 isCorrupt; /* Corruption detected by xRecordCompare() */
Mem *aMem; /* Values */
int r1; /* Value to return if (lhs > rhs) */
int r2; /* Value to return if (rhs < lhs) */
+2 -2
View File
@@ -211,10 +211,10 @@ void sqlite3VdbeSetVarmask(Vdbe*, int);
#endif
void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
int sqlite3VdbeRecordCompare(int,const void*,const UnpackedRecord*,int);
int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*,int);
UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
typedef int (*RecordCompare)(int,const void*,const UnpackedRecord*,int);
typedef int (*RecordCompare)(int,const void*,UnpackedRecord*,int);
RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
#ifndef SQLITE_OMIT_TRIGGER
+1 -1
View File
@@ -392,7 +392,7 @@ u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
void sqlite3VdbeDeleteAuxData(Vdbe*, int, int);
int sqlite2BtreeKeyCompare(BtCursor *, const void *, int, int, int *);
int sqlite3VdbeIdxKeyCompare(VdbeCursor*,const UnpackedRecord*,int*);
int sqlite3VdbeIdxKeyCompare(VdbeCursor*,UnpackedRecord*,int*);
int sqlite3VdbeIdxRowid(sqlite3*, BtCursor *, i64 *);
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
int sqlite3VdbeExec(Vdbe*);
+19 -8
View File
@@ -3405,10 +3405,13 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
** 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.
**
** If database corruption is discovered, set pPKey2->isCorrupt to non-zero
** and return 0.
*/
int sqlite3VdbeRecordCompare(
int nKey1, const void *pKey1, /* Left key */
const UnpackedRecord *pPKey2, /* Right key */
UnpackedRecord *pPKey2, /* Right key */
int bSkip /* If true, skip the first field */
){
u32 d1; /* Offset into aKey[] of next data element */
@@ -3434,7 +3437,10 @@ int sqlite3VdbeRecordCompare(
}else{
idx1 = getVarint32(aKey1, szHdr1);
d1 = szHdr1;
if( d1>(unsigned)nKey1 ) return 1; /* Corruption */
if( d1>(unsigned)nKey1 ){
pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
return 0; /* Corruption */
}
i = 0;
}
@@ -3511,7 +3517,8 @@ int sqlite3VdbeRecordCompare(
testcase( (d1+mem1.n)==(unsigned)nKey1 );
testcase( (d1+mem1.n+1)==(unsigned)nKey1 );
if( (d1+mem1.n) > (unsigned)nKey1 ){
rc = 1; /* Corruption */
pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
return 0; /* Corruption */
}else if( pKeyInfo->aColl[i] ){
mem1.enc = pKeyInfo->enc;
mem1.db = pKeyInfo->db;
@@ -3537,7 +3544,8 @@ int sqlite3VdbeRecordCompare(
testcase( (d1+nStr)==(unsigned)nKey1 );
testcase( (d1+nStr+1)==(unsigned)nKey1 );
if( (d1+nStr) > (unsigned)nKey1 ){
rc = 1; /* Corruption */
pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
return 0; /* Corruption */
}else{
int nCmp = MIN(nStr, pRhs->n);
rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
@@ -3596,7 +3604,7 @@ int sqlite3VdbeRecordCompare(
*/
static int vdbeRecordCompareInt(
int nKey1, const void *pKey1, /* Left key */
const UnpackedRecord *pPKey2, /* Right key */
UnpackedRecord *pPKey2, /* Right key */
int bSkip /* Ignored */
){
const u8 *aKey = &((const u8*)pKey1)[*(const u8*)pKey1 & 0x3F];
@@ -3694,7 +3702,7 @@ static int vdbeRecordCompareInt(
*/
static int vdbeRecordCompareString(
int nKey1, const void *pKey1, /* Left key */
const UnpackedRecord *pPKey2, /* Right key */
UnpackedRecord *pPKey2, /* Right key */
int bSkip
){
const u8 *aKey1 = (const u8*)pKey1;
@@ -3715,7 +3723,10 @@ static int vdbeRecordCompareString(
int szHdr = aKey1[0];
nStr = (serial_type-12) / 2;
if( (szHdr + nStr) > nKey1 ) return 0; /* Corruption */
if( (szHdr + nStr) > nKey1 ){
pPKey2->isCorrupt = (u8)SQLITE_CORRUPT_BKPT;
return 0; /* Corruption */
}
nCmp = MIN( pPKey2->aMem[0].n, nStr );
res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp);
@@ -3880,7 +3891,7 @@ idx_rowid_corruption:
*/
int sqlite3VdbeIdxKeyCompare(
VdbeCursor *pC, /* The cursor to compare against */
const UnpackedRecord *pUnpacked, /* Unpacked version of key */
UnpackedRecord *pUnpacked, /* Unpacked version of key */
int *res /* Write the comparison result here */
){
i64 nCellKey = 0;
+35 -11
View File
@@ -4328,18 +4328,34 @@ static int whereLoopAddBtree(
)
){
pNew->iSortIdx = b ? iSortIdx : 0;
/* TUNING: The base cost of an index scan is N + log2(N).
** The log2(N) is for the initial seek to the beginning and the N
** is for the scan itself. */
pNew->rRun = sqlite3LogEstAdd(rSize, rLogSize);
if( m==0 ){
/* TUNING: Cost of a covering index scan is K*(N + log2(N)).
** + The extra factor K of between 1.1 and 3.0 that depends
** on the relative sizes of the table and the index. K
** is smaller for smaller indices, thus favoring them.
** The upper bound on K (3.0) matches the penalty factor
** on a full table scan that tries to encourage the use of
** indexed lookups over full scans.
*/
pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 1 +
(15*pProbe->szIdxRow)/pTab->szTabRow;
pNew->rRun += 1 + (15*pProbe->szIdxRow)/pTab->szTabRow;
}else{
/* TUNING: Cost of scanning a non-covering index is (N+1)*log2(N)
** which we will simplify to just N*log2(N) */
pNew->rRun = rSize + rLogSize;
/* TUNING: The cost of scanning a non-covering index is multiplied
** by log2(N) to account for the binary search of the main table
** that must happen for each row of the index.
** TODO: Should there be a multiplier here, analogous to the 3x
** multiplier for a fulltable scan or covering index scan, to
** further discourage the use of an index scan? Or is the log2(N)
** term sufficient discouragement?
** TODO: What if some or all of the WHERE clause terms can be
** computed without reference to the original table. Then the
** penality should reduce to logK where K is the number of output
** rows.
*/
pNew->rRun += rLogSize;
}
whereLoopOutputAdjust(pWC, pNew);
rc = whereLoopInsert(pBuilder, pNew);
@@ -4920,7 +4936,7 @@ static i8 wherePathSatisfiesOrderBy(
}
}
} /* End the loop over all WhereLoops from outer-most down to inner-most */
if( obSat==obDone ) return nOrderBy;
if( obSat==obDone ) return (i8)nOrderBy;
if( !isOrderDistinct ){
for(i=nOrderBy-1; i>0; i--){
Bitmask m = MASKBIT(i) - 1;
@@ -5041,11 +5057,19 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags,
iLoop, pWLoop, &revMask);
if( isOrdered>=0 && isOrdered<nOrderBy ){
/* TUNING: Estimated cost of sorting cost as roughly N*log(N).
** If some but not all of the columns are in sorted order, then
** scale down the log(N) term. */
LogEst rScale = sqlite3LogEst((nOrderBy-isOrdered)*100/nOrderBy);
LogEst rSortCost = nRowEst + estLog(nRowEst) + rScale - 66;
/* TUNING: Estimated cost of sorting is N*log(N).
** If the order-by clause has X terms but only the last Y terms
** are out of order, then block-sorting will reduce the sorting
** cost to N*log(N)*log(Y/X). The log(Y/X) term is computed
** by rScale.
** TODO: Should the sorting cost get a small multiplier to help
** discourage the use of sorting and encourage the use of index
** scans instead?
*/
LogEst rScale, rSortCost;
assert( nOrderBy>0 );
rScale = sqlite3LogEst((nOrderBy-isOrdered)*100/nOrderBy) - 66;
rSortCost = nRowEst + estLog(nRowEst) + rScale;
/* TUNING: The cost of implementing DISTINCT using a B-TREE is
** also N*log(N) but it has a larger constant of proportionality.
** Multiply by 3.0. */