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:
87
src/where.c
87
src/where.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user