Index: src/where.c ================================================================== --- src/where.c +++ src/where.c @@ -4308,10 +4308,13 @@ while( pWInfo->pLoops ){ WhereLoop *p = pWInfo->pLoops; pWInfo->pLoops = p->pNextLoop; whereLoopDelete(db, p); } + if( pWInfo->bShortcut ){ + whereLoopClear(db, pWInfo->a[0].pWLoop); + } sqlite3DbFree(db, pWInfo); } } /* @@ -5558,11 +5561,10 @@ u8 priorJoinType = 0; WhereLoop *pNew; /* Loop over the tables in the join, from left to right */ pNew = pBuilder->pNew; - whereLoopInit(pNew); for(iTab=0, pItem=pTabList->a; iTabiTab = iTab; pNew->maskSelf = getMask(&pWInfo->sMaskSet, pItem->iCursor); if( ((pItem->jointype|priorJoinType) & (JT_LEFT|JT_CROSS))!=0 ){ mExtra = mPrior; @@ -6274,11 +6276,11 @@ ** ** Return non-zero on success, if this query can be handled by this ** no-frills query planner. Return zero if this query needs the ** general-purpose query planner. */ -static int whereShortCut(WhereLoopBuilder *pBuilder){ +static int whereShortCut(sqlite3 *db, WhereLoopBuilder *pBuilder){ WhereInfo *pWInfo; struct SrcList_item *pItem; WhereClause *pWC; WhereTerm *pTerm; WhereLoop *pLoop; @@ -6309,15 +6311,18 @@ pLoop->rRun = 33; /* 33==sqlite3LogEst(10) */ }else{ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ u32 mask = WO_EQ; assert( pLoop->aLTermSpace==pLoop->aLTerm ); + if( HasRowid(pTab)==0 && IsPrimaryKeyIndex(pIdx) ){ + mask |= WO_IS; + if( whereLoopResize(db, pLoop, pIdx->nKeyCol) ) return 1; + }else if( !IsUniqueIndex(pIdx) || pIdx->pPartIdxWhere!=0 || pIdx->nKeyCol>ArraySize(pLoop->aLTermSpace) ) continue; - if( HasRowid(pTab)==0 && IsPrimaryKeyIndex(pIdx) ) mask |= WO_IS; for(j=0; jnKeyCol; j++){ pTerm = findTerm(pWC, iCur, pIdx->aiColumn[j], 0, mask, pIdx); if( pTerm==0 ) break; pLoop->aLTerm[j] = pTerm; } @@ -6345,10 +6350,11 @@ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; } #ifdef SQLITE_DEBUG pLoop->cId = '0'; #endif + pWInfo->bShortcut = 1; return 1; } return 0; } @@ -6615,11 +6621,11 @@ whereTermPrint(&sWLB.pWC->a[i], i); } } #endif - if( nTabList!=1 || whereShortCut(&sWLB)==0 ){ + if( nTabList!=1 || whereShortCut(db, &sWLB)==0 ){ rc = whereLoopAddAll(&sWLB); if( rc ) goto whereBeginError; /* Display all of the WhereLoop objects if wheretrace is enabled */ #ifdef WHERETRACE_ENABLED /* !=0 */ Index: src/whereInt.h ================================================================== --- src/whereInt.h +++ src/whereInt.h @@ -410,10 +410,11 @@ u8 sorted; /* True if really sorted (not just grouped) */ u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */ u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */ u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */ u8 nLevel; /* Number of nested loop */ + u8 bShortcut; /* Plan generated by whereShortCut() */ int iTop; /* The very beginning of the WHERE loop */ int iContinue; /* Jump here to continue with next record */ int iBreak; /* Jump here to break out of the loop */ int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */ Index: test/whereK.test ================================================================== --- test/whereK.test +++ test/whereK.test @@ -55,9 +55,23 @@ do_execsql_test 1.4.1 { SELECT v FROM t1 WHERE w IS 3 AND x = 3 } {C} do_execsql_test 1.4.2 { SELECT v FROM t1 WHERE w = '4' AND x IS 4 } {d} do_eqp_test 1.5.1 { SELECT b FROM t3 WHERE a IS ? } {/SCAN TABLE/} do_eqp_test 1.5.2 { SELECT b FROM t3 WHERE a = ? } {/SEARCH TABLE/} + +#------------------------------------------------------------------------- +# Check that this works with PRIMARY KEY indexes that have large numbers +# of columns. + +do_execsql_test 2.1.1 { + CREATE TABLE x1(a, b, c, d, e, f, g, h, i, + PRIMARY KEY(a, b, c, d, e, f, g) + ) WITHOUT ROWID; +} +do_eqp_test 2.1.2 { + SELECT i FROM x1 WHERE + a IS ? AND b IS ? AND c IS ? AND d IS ? AND e IS ? AND f IS ? AND g IS ? +} {/SEARCH TABLE/} finish_test