diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/insert.c | 4 | ||||
-rw-r--r-- | src/vdbe.c | 4 | ||||
-rw-r--r-- | src/vdbeaux.c | 2 | ||||
-rw-r--r-- | src/where.c | 42 |
4 files changed, 32 insertions, 20 deletions
diff --git a/src/insert.c b/src/insert.c index bfcd2c253..eca3c12dd 100644 --- a/src/insert.c +++ b/src/insert.c @@ -47,7 +47,7 @@ void sqlite3OpenTable( ** 'd' INTEGER ** 'e' REAL ** -** An extra 'b' is appended to the end of the string to cover the +** An extra 'd' is appended to the end of the string to cover the ** rowid that appears as the last column in every index. ** ** Memory for the buffer containing the column index affinity string @@ -75,7 +75,7 @@ const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ for(n=0; n<pIdx->nColumn; n++){ pIdx->zColAff[n] = pTab->aCol[pIdx->aiColumn[n]].affinity; } - pIdx->zColAff[n++] = SQLITE_AFF_NONE; + pIdx->zColAff[n++] = SQLITE_AFF_INTEGER; pIdx->zColAff[n] = 0; } diff --git a/src/vdbe.c b/src/vdbe.c index 22e6d9c5b..e7fa05037 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -4616,9 +4616,9 @@ case OP_IdxGE: { /* jump */ r.pKeyInfo = pC->pKeyInfo; r.nField = (u16)pOp->p4.i; if( pOp->p5 ){ - r.flags = UNPACKED_INCRKEY | UNPACKED_IGNORE_ROWID; + r.flags = UNPACKED_INCRKEY | UNPACKED_PREFIX_MATCH; }else{ - r.flags = UNPACKED_IGNORE_ROWID; + r.flags = UNPACKED_PREFIX_MATCH; } r.aMem = &aMem[pOp->p3]; #ifdef SQLITE_DEBUG diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 75250238e..67b4ec759 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -3166,7 +3166,7 @@ int sqlite3VdbeIdxKeyCompare( if( rc ){ return rc; } - assert( pUnpacked->flags & UNPACKED_IGNORE_ROWID ); + assert( pUnpacked->flags & UNPACKED_PREFIX_SEARCH ); *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked); sqlite3VdbeMemRelease(&m); return SQLITE_OK; diff --git a/src/where.c b/src/where.c index 05414da58..a604d788c 100644 --- a/src/where.c +++ b/src/where.c @@ -604,7 +604,7 @@ static WhereTerm *findTerm( && pTerm->u.leftColumn==iColumn && (pTerm->eOperator & op)!=0 ){ - if( pIdx && pTerm->eOperator!=WO_ISNULL ){ + if( iColumn>=0 && pIdx && pTerm->eOperator!=WO_ISNULL ){ Expr *pX = pTerm->pExpr; CollSeq *pColl; char idxaff; @@ -3052,10 +3052,24 @@ static void bestBtreeIndex( #endif used |= pTerm->prereqRight; } - - /* Determine the value of rangeDiv */ - if( nEq<pProbe->nColumn && pProbe->bUnordered==0 ){ - int j = pProbe->aiColumn[nEq]; + + /* If the index being considered is UNIQUE, and there is an equality + ** constraint for all columns in the index, then this search will find + ** at most a single row. In this case set the WHERE_UNIQUE flag to + ** indicate this to the caller. + ** + ** Otherwise, if the search may find more than one row, test to see if + ** there is a range constraint on indexed column (nEq+1) that can be + ** optimized using the index. + */ + if( nEq==pProbe->nColumn && pProbe->onError!=OE_None ){ + testcase( wsFlags & WHERE_COLUMN_IN ); + testcase( wsFlags & WHERE_COLUMN_NULL ); + if( (wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){ + wsFlags |= WHERE_UNIQUE; + } + }else if( pProbe->bUnordered==0 ){ + int j = (nEq==pProbe->nColumn ? -1 : pProbe->aiColumn[nEq]); if( findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE|WO_GT|WO_GE, pIdx) ){ WhereTerm *pTop = findTerm(pWC, iCur, j, notReady, WO_LT|WO_LE, pIdx); WhereTerm *pBtm = findTerm(pWC, iCur, j, notReady, WO_GT|WO_GE, pIdx); @@ -3074,12 +3088,6 @@ static void bestBtreeIndex( } wsFlags |= (WHERE_COLUMN_RANGE|WHERE_ROWID_RANGE); } - }else if( pProbe->onError!=OE_None ){ - testcase( wsFlags & WHERE_COLUMN_IN ); - testcase( wsFlags & WHERE_COLUMN_NULL ); - if( (wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_NULL))==0 ){ - wsFlags |= WHERE_UNIQUE; - } } /* If there is an ORDER BY clause and the index being considered will @@ -3690,10 +3698,12 @@ static char *explainIndexRange(sqlite3 *db, WhereLevel *pLevel, Table *pTab){ j = i; if( pPlan->wsFlags&WHERE_BTM_LIMIT ){ - explainAppendTerm(&txt, i++, aCol[aiColumn[j]].zName, ">"); + char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName; + explainAppendTerm(&txt, i++, z, ">"); } if( pPlan->wsFlags&WHERE_TOP_LIMIT ){ - explainAppendTerm(&txt, i, aCol[aiColumn[j]].zName, "<"); + char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName; + explainAppendTerm(&txt, i, z, "<"); } sqlite3StrAccumAppend(&txt, ")", 1); return sqlite3StrAccumFinish(&txt); @@ -4051,7 +4061,7 @@ static Bitmask codeOneLoopStart( pIdx = pLevel->plan.u.pIdx; iIdxCur = pLevel->iIdxCur; - k = pIdx->aiColumn[nEq]; /* Column for inequality constraints */ + k = (nEq==pIdx->nColumn ? -1 : pIdx->aiColumn[nEq]); /* If this loop satisfies a sort order (pOrderBy) request that ** was passed to this function to implement a "SELECT min(x) ..." @@ -4097,7 +4107,9 @@ static Bitmask codeOneLoopStart( ** a forward order scan on a descending index, interchange the ** start and end terms (pRangeStart and pRangeEnd). */ - if( nEq<pIdx->nColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC) ){ + if( (nEq<pIdx->nColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC)) + || (bRev && pIdx->nColumn==nEq) + ){ SWAP(WhereTerm *, pRangeEnd, pRangeStart); } |