1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-18 10:21:03 +03:00

Merge enhancements from trunk.

FossilOrigin-Name: 29570a604806e2a60a8eef7eaf1dce022d2a7004
This commit is contained in:
drh
2015-09-01 18:31:19 +00:00
40 changed files with 2976 additions and 354 deletions

View File

@@ -171,37 +171,37 @@ static void createMask(WhereMaskSet *pMaskSet, int iCursor){
*/
static WhereTerm *whereScanNext(WhereScan *pScan){
int iCur; /* The cursor on the LHS of the term */
int iColumn; /* The column on the LHS of the term. -1 for IPK */
i16 iColumn; /* The column on the LHS of the term. -1 for IPK */
Expr *pX; /* An expression being tested */
WhereClause *pWC; /* Shorthand for pScan->pWC */
WhereTerm *pTerm; /* The term being tested */
int k = pScan->k; /* Where to start scanning */
while( pScan->iEquiv<=pScan->nEquiv ){
iCur = pScan->aEquiv[pScan->iEquiv-2];
iColumn = pScan->aEquiv[pScan->iEquiv-1];
iCur = pScan->aiCur[pScan->iEquiv-1];
iColumn = pScan->aiColumn[pScan->iEquiv-1];
while( (pWC = pScan->pWC)!=0 ){
for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){
if( pTerm->leftCursor==iCur
&& pTerm->u.leftColumn==iColumn
&& (pScan->iEquiv<=2 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin))
&& (pScan->iEquiv<=1 || !ExprHasProperty(pTerm->pExpr, EP_FromJoin))
){
if( (pTerm->eOperator & WO_EQUIV)!=0
&& pScan->nEquiv<ArraySize(pScan->aEquiv)
&& pScan->nEquiv<ArraySize(pScan->aiCur)
){
int j;
pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight);
assert( pX->op==TK_COLUMN );
for(j=0; j<pScan->nEquiv; j+=2){
if( pScan->aEquiv[j]==pX->iTable
&& pScan->aEquiv[j+1]==pX->iColumn ){
for(j=0; j<pScan->nEquiv; j++){
if( pScan->aiCur[j]==pX->iTable
&& pScan->aiColumn[j]==pX->iColumn ){
break;
}
}
if( j==pScan->nEquiv ){
pScan->aEquiv[j] = pX->iTable;
pScan->aEquiv[j+1] = pX->iColumn;
pScan->nEquiv += 2;
pScan->aiCur[j] = pX->iTable;
pScan->aiColumn[j] = pX->iColumn;
pScan->nEquiv++;
}
}
if( (pTerm->eOperator & pScan->opMask)!=0 ){
@@ -223,8 +223,8 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
}
if( (pTerm->eOperator & (WO_EQ|WO_IS))!=0
&& (pX = pTerm->pExpr->pRight)->op==TK_COLUMN
&& pX->iTable==pScan->aEquiv[0]
&& pX->iColumn==pScan->aEquiv[1]
&& pX->iTable==pScan->aiCur[0]
&& pX->iColumn==pScan->aiColumn[0]
){
testcase( pTerm->eOperator & WO_IS );
continue;
@@ -239,7 +239,7 @@ static WhereTerm *whereScanNext(WhereScan *pScan){
}
pScan->pWC = pScan->pOrigWC;
k = 0;
pScan->iEquiv += 2;
pScan->iEquiv++;
}
return 0;
}
@@ -285,10 +285,10 @@ static WhereTerm *whereScanInit(
}
pScan->opMask = opMask;
pScan->k = 0;
pScan->aEquiv[0] = iCur;
pScan->aEquiv[1] = iColumn;
pScan->nEquiv = 2;
pScan->iEquiv = 2;
pScan->aiCur[0] = iCur;
pScan->aiColumn[0] = iColumn;
pScan->nEquiv = 1;
pScan->iEquiv = 1;
return whereScanNext(pScan);
}
@@ -301,12 +301,10 @@ static WhereTerm *whereScanInit(
** The term returned might by Y=<expr> if there is another constraint in
** the WHERE clause that specifies that X=Y. Any such constraints will be
** identified by the WO_EQUIV bit in the pTerm->eOperator field. The
** aEquiv[] array holds X and all its equivalents, with each SQL variable
** taking up two slots in aEquiv[]. The first slot is for the cursor number
** and the second is for the column number. There are 22 slots in aEquiv[]
** so that means we can look for X plus up to 10 other equivalent values.
** Hence a search for X will return <expr> if X=A1 and A1=A2 and A2=A3
** and ... and A9=A10 and A10=<expr>.
** aiCur[]/iaColumn[] arrays hold X and all its equivalents. There are 11
** slots in aiCur[]/aiColumn[] so that means we can look for X plus up to 10
** other equivalent values. Hence a search for X will return <expr> if X=A1
** and A1=A2 and A2=A3 and ... and A9=A10 and A10=<expr>.
**
** If there are multiple terms in the WHERE clause of the form "X <op> <expr>"
** then try for the one with no dependencies on <expr> - in other words where
@@ -1127,6 +1125,20 @@ static LogEst whereRangeAdjust(WhereTerm *pTerm, LogEst nNew){
return nRet;
}
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
/*
** Return the affinity for a single column of an index.
*/
static char sqlite3IndexColumnAffinity(sqlite3 *db, Index *pIdx, int iCol){
if( !pIdx->zColAff ){
if( sqlite3IndexAffinityStr(db, pIdx)==0 ) return SQLITE_AFF_BLOB;
}
return pIdx->zColAff[iCol];
}
#endif
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
/*
** This function is called to estimate the number of rows visited by a
@@ -1177,7 +1189,7 @@ static int whereRangeSkipScanEst(
int nUpper = p->nSample+1;
int rc = SQLITE_OK;
int iCol = p->aiColumn[nEq];
u8 aff = iCol>=0 ? p->pTable->aCol[iCol].affinity : SQLITE_AFF_INTEGER;
u8 aff = sqlite3IndexColumnAffinity(db, p, iCol);
CollSeq *pColl;
sqlite3_value *p1 = 0; /* Value extracted from pLower */
@@ -1325,11 +1337,8 @@ static int whereRangeScanEst(
testcase( pRec->nField!=pBuilder->nRecValid );
pRec->nField = pBuilder->nRecValid;
}
if( nEq==p->nKeyCol ){
aff = SQLITE_AFF_INTEGER;
}else{
aff = p->pTable->aCol[p->aiColumn[nEq]].affinity;
}
aff = sqlite3IndexColumnAffinity(pParse->db, p, nEq);
assert( nEq!=p->nKeyCol || aff==SQLITE_AFF_INTEGER );
/* Determine iLower and iUpper using ($P) only. */
if( nEq==0 ){
iLower = 0;
@@ -1487,7 +1496,7 @@ static int whereEqualScanEst(
return SQLITE_OK;
}
aff = p->pTable->aCol[p->aiColumn[nEq-1]].affinity;
aff = sqlite3IndexColumnAffinity(pParse->db, p, nEq-1);
rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq-1, &bOk);
pBuilder->pRec = pRec;
if( rc!=SQLITE_OK ) return rc;
@@ -1914,18 +1923,20 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
** and prereqs.
*/
if( pBuilder->pOrSet!=0 ){
if( pTemplate->nLTerm ){
#if WHERETRACE_ENABLED
u16 n = pBuilder->pOrSet->n;
int x =
u16 n = pBuilder->pOrSet->n;
int x =
#endif
whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun,
whereOrInsert(pBuilder->pOrSet, pTemplate->prereq, pTemplate->rRun,
pTemplate->nOut);
#if WHERETRACE_ENABLED /* 0x8 */
if( sqlite3WhereTrace & 0x8 ){
sqlite3DebugPrintf(x?" or-%d: ":" or-X: ", n);
whereLoopPrint(pTemplate, pBuilder->pWC);
}
if( sqlite3WhereTrace & 0x8 ){
sqlite3DebugPrintf(x?" or-%d: ":" or-X: ", n);
whereLoopPrint(pTemplate, pBuilder->pWC);
}
#endif
}
return SQLITE_OK;
}