/ Check-in [4b589fbf]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Enhance sqlite3FindInIndex() so that it is able to make use of the primary keys at the end of an index.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | rowvalue
Files: files | file ages | folders
SHA1: 4b589fbfcc4265902de0f552961d2df497a184da
User & Date: drh 2016-08-26 19:31:29
Context
2016-08-26
19:47
Add test cases to rowvalue2.test. check-in: 078bb69e user: dan tags: rowvalue
19:31
Enhance sqlite3FindInIndex() so that it is able to make use of the primary keys at the end of an index. check-in: 4b589fbf user: drh tags: rowvalue
18:17
Fix a post-OOM crash in updateRangeAffinityStr(). Add several ALWAYS() macros on unreachable branches. check-in: 87d40195 user: drh tags: rowvalue
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/expr.c.

2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
....
2196
2197
2198
2199
2200
2201
2202


2203
2204

2205

2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218

2219
2220
2221
2222
2223
2224
2225
**   (?,?,?) IN (SELECT a, b, c FROM t1)
**   CREATE INDEX i1 ON t1(b, c, a);
**
** then aiMap[] is populated with {2, 0, 1}.
*/
#ifndef SQLITE_OMIT_SUBQUERY
int sqlite3FindInIndex(
  Parse *pParse, 
  Expr *pX, 
  u32 inFlags, 
  int *prRhsHasNull,
  int *aiMap
){
  Select *p;                            /* SELECT to the right of IN operator */
  int eType = 0;                        /* Type of RHS table. IN_INDEX_* */
  int iTab = pParse->nTab++;            /* Cursor of the RHS table */
  int mustBeUnique;                     /* True if RHS must be unique */
  Vdbe *v = sqlite3GetVdbe(pParse);     /* Virtual machine being coded */

................................................................................
      }

      /* The collation sequence used by the comparison. If an index is to
      ** be used in place of a temp-table, it must be ordered according
      ** to this collation sequence.  */

      for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){


        if( pIdx->nKeyCol<nExpr ) continue;
        if( mustBeUnique && (pIdx->nKeyCol!=nExpr || !IsUniqueIndex(pIdx)) ){

          continue;

        }

        for(i=0; i<nExpr; i++){
          Expr *pLhs = sqlite3VectorFieldSubexpr(pX->pLeft, i);
          Expr *pRhs = pEList->a[i].pExpr;
          CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
          int j;

          if( pReq==0 ) break;

          for(j=0; j<nExpr; j++){
            if( pIdx->aiColumn[j]!=pRhs->iColumn ) continue;
            assert( pIdx->azColl[j] );

            if( sqlite3StrICmp(pReq->zName, pIdx->azColl[j])!=0 ) continue;
            break;
          }
          if( j==nExpr ) break;
          if( aiMap ) aiMap[i] = j;
        }








|
|
|
|
|







 







>
>
|
|
>
|
>








|
<



>







2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
....
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218

2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
**   (?,?,?) IN (SELECT a, b, c FROM t1)
**   CREATE INDEX i1 ON t1(b, c, a);
**
** then aiMap[] is populated with {2, 0, 1}.
*/
#ifndef SQLITE_OMIT_SUBQUERY
int sqlite3FindInIndex(
  Parse *pParse,             /* Parsing context */
  Expr *pX,                  /* The right-hand side (RHS) of the IN operator */
  u32 inFlags,               /* IN_INDEX_LOOP, _MEMBERSHIP, and/or _NOOP_OK */
  int *prRhsHasNull,         /* Register holding NULL status.  See notes */
  int *aiMap                 /* Mapping from Index fields to RHS fields */
){
  Select *p;                            /* SELECT to the right of IN operator */
  int eType = 0;                        /* Type of RHS table. IN_INDEX_* */
  int iTab = pParse->nTab++;            /* Cursor of the RHS table */
  int mustBeUnique;                     /* True if RHS must be unique */
  Vdbe *v = sqlite3GetVdbe(pParse);     /* Virtual machine being coded */

................................................................................
      }

      /* The collation sequence used by the comparison. If an index is to
      ** be used in place of a temp-table, it must be ordered according
      ** to this collation sequence.  */

      for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){
        if( pIdx->nColumn<nExpr ) continue;
        if( mustBeUnique ){
          if( pIdx->nKeyCol>nExpr
           ||(pIdx->nColumn>nExpr && !IsUniqueIndex(pIdx))
          ){
            continue;
          }
        }

        for(i=0; i<nExpr; i++){
          Expr *pLhs = sqlite3VectorFieldSubexpr(pX->pLeft, i);
          Expr *pRhs = pEList->a[i].pExpr;
          CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
          int j;

          assert( pReq!=0 || pRhs->iColumn==XN_ROWID || pParse->nErr );

          for(j=0; j<nExpr; j++){
            if( pIdx->aiColumn[j]!=pRhs->iColumn ) continue;
            assert( pIdx->azColl[j] );
            if( pReq==0 ) continue;
            if( sqlite3StrICmp(pReq->zName, pIdx->azColl[j])!=0 ) continue;
            break;
          }
          if( j==nExpr ) break;
          if( aiMap ) aiMap[i] = j;
        }