From: dan Date: Sat, 24 Jun 2017 18:10:29 +0000 (+0000) Subject: Consider the values bound to SQL variables when determining whether or not a X-Git-Tag: version-3.20.0~167^2~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5aa550cf3b257cd1e62812a8784caca440908ed8;p=thirdparty%2Fsqlite.git Consider the values bound to SQL variables when determining whether or not a partial index may be used. FossilOrigin-Name: 7b59c353b805c64689b4ae9df347705acbb5f116346ad77af8ce087da7893747 --- diff --git a/manifest b/manifest index 3b122ca8bd..795c5df67f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\sthe\sconfig.h\sheader\sis\sincluded\sby\sctime.c,\sif\sthat\sheader\sexists. -D 2017-06-24T16:35:00.182 +C Consider\sthe\svalues\sbound\sto\sSQL\svariables\swhen\sdetermining\swhether\sor\snot\sa\npartial\sindex\smay\sbe\sused. +D 2017-06-24T18:10:29.777 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 8eeb80162074004e906b53d7340a12a14c471a83743aab975947e95ce061efcc @@ -358,7 +358,7 @@ F src/ctime.c e9a6db1321c2353fe922533f202b85abb3084cdf569450abcabf55e21e104550 F src/date.c cc42a41c7422389860d40419a5e3bce5eaf6e7835c3ba2677751dc653550a5c7 F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d F src/delete.c 3213547e97b676c6fa79948b7a9ede4801ea04a01a2043241deafedf132ecf5d -F src/expr.c 452c6f3aa656aabf3eefe96bb5f316b2c987fbc12c647964e4ed880f193ca31f +F src/expr.c 9aea9dbac1169c5cda3ee5d288b9e6c25de597a38023f8104406e0312145ca8d F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 5ff2c895fe087756d8085dc1a9bc229b5670e2a65c3929dd87c71e43649af333 F src/func.c 9d52522cc8ae7f5cdadfe14594262f1618bc1f86083c4cd6da861b4cf5af6174 @@ -367,7 +367,7 @@ F src/hash.c 63d0ee752a3b92d4695b2b1f5259c4621b2cfebd F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4 F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c 974499a3999d339a4c1ba8ef129a988d9f136b3789e423808b38cdc19d28adbe +F src/insert.c bb70abf32c7c926745eb550938db9132309584a667a44c2db0e5fa3207600391 F src/legacy.c e88ed13c2d531decde75d42c2e35623fb9ce3cb0 F src/loadext.c a72909474dadce771d3669bf84bf689424f6f87d471fee898589c3ef9b2acfd9 F src/main.c 18f2145d572069dae91161add89446aec680aab296492a92ae5afcc2fc7c6b5a @@ -403,14 +403,14 @@ F src/pragma.h a8a949000214fefb6210330eed8ccbbb4f752619a9871f31b3dedd4a240277fd F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a F src/printf.c 8757834f1b54dae512fb25eb1acc8e94a0d15dd2290b58f2563f65973265adb2 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384 -F src/resolve.c adf3ef9843135b1383321ad751f16f5a40c3f37925154555a3e61653d2a954e8 +F src/resolve.c d1e69759e7a79c156c692793f5d16f82f9a60ce5e82efd95e4374b2423034946 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac -F src/select.c 35ccfae64cecfa843d54a5898c4ab7d6595ce03d147267fa5eecdc8eab39cd6a +F src/select.c 741937503c74d85e64828b63d5a4219d3cfce480a717efef635839606001b1ba F src/shell.c 2026e88e7892ba177eae79936285d781f1c449f7a7b4e8d86fd02739d4ead26b F src/sqlite.h.in 67fa8bd29808e7988e0ce36c8d4c6043eb1727f94522fc612687aa5af51931e6 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 58fd0676d3111d02e62e5a35992a7d3da5d3f88753acc174f2d37b774fbbdd28 -F src/sqliteInt.h 34a54fb47de2da1465f3d3ba1cd373db880bd5d588b0fe862a073ecacd6ddaae +F src/sqliteInt.h 770fd49c27345a46c9864470318aa0c384148128ab9ff6d8ea28d79720a326ce F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 @@ -486,10 +486,10 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344 F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71 F src/walker.c d46044e7a5842560dfe7122d93ff5145dd4a96f4d0bf5ba5910a7731b8c01e79 -F src/where.c 74b0a05487e44e8c5d28ebe3bd77ca9719b1d5114235bed48079aee309a0bb4e +F src/where.c 563cd034b1d09e6b64a88cafc47a6f37de708d07d03c68b1d4185d8b7f3618bf F src/whereInt.h 2a4b634d63ce488b46d4b0da8f2eaa8f9aeab202bc25ef76f007de5e3fba1f20 -F src/wherecode.c 339ee802d9d311acf0cba8b5a9a092e167ef71c3a777d4b3e57de25d193251c7 -F src/whereexpr.c a2fe3811d45af45a5c6667caabc15e01054fe6228c64e86e1f7d2ba5ef5284f9 +F src/wherecode.c f17f5d51e372168db51af637e265aa5e80f99fcc81bfead96b66e71a7732bc62 +F src/whereexpr.c 5567f180ad1c4b278fb7b5d0c9d2904a0fc570bb2fa802ae0b2f7981f4ff31ea F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d @@ -885,6 +885,7 @@ F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7 F test/index6.test b4fc812290067a578b98bb2667b676db89e202a7 F test/index7.test 7feababe16f2091b229c22aff2bcc1d4d6b9d2bb F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7 +F test/index9.test 896b05eff9587ff251453c647e4f0e6a9a136a801c535842d0afde6d659a6d0b F test/indexedby.test 9c4cd331224e57f79fbf411ae245e6272d415985 F test/indexexpr1.test 038b3befa74e5a75126b6e9dd2ae5df61c1c7cf7 F test/indexexpr2.test 68ee9dbe83fcf85e50f4d0bd1f742a082496f2ee5153f4be2a1861db84462bf7 @@ -1583,7 +1584,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P f0ec36d479ac4efaa0efd0594d032dd7b8ccdf84a4dc3644cd688762186fbcca -R 372aadc61aabb2f352679729d647f91e -U drh -Z 70448a4a6b9d4ba9f8d312e19786de1b +P c2ea62937ec8fabec72d3c7cd38d8e2cabbb5ce48638f8ce7ebefd6cd2716fd3 +R b8e9da98ffddd11a474e506223755851 +T *branch * partial-index-variables +T *sym-partial-index-variables * +T -sym-trunk * +U dan +Z 8e348d414463386c5669d14e46f9f0ff diff --git a/manifest.uuid b/manifest.uuid index 7e2f512050..34b7cb6ce6 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c2ea62937ec8fabec72d3c7cd38d8e2cabbb5ce48638f8ce7ebefd6cd2716fd3 \ No newline at end of file +7b59c353b805c64689b4ae9df347705acbb5f116346ad77af8ce087da7893747 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index 27cebdb834..89a4adddb8 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1829,7 +1829,7 @@ static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){ ** it constant. */ for(i=0; inExpr; i++){ Expr *p = pGroupBy->a[i].pExpr; - if( sqlite3ExprCompare(pExpr, p, -1)<2 ){ + if( sqlite3ExprCompare(0, pExpr, p, -1)<2 ){ CollSeq *pColl = sqlite3ExprCollSeq(pWalker->pParse, p); if( pColl==0 || sqlite3_stricmp("BINARY", pColl->zName)==0 ){ return WRC_Prune; @@ -4105,7 +4105,7 @@ int sqlite3ExprCodeAtInit( struct ExprList_item *pItem; int i; for(pItem=p->a, i=p->nExpr; i>0; pItem++, i--){ - if( pItem->reusable && sqlite3ExprCompare(pItem->pExpr,pExpr,-1)==0 ){ + if( pItem->reusable && sqlite3ExprCompare(0,pItem->pExpr,pExpr,-1)==0 ){ return pItem->u.iConstExprReg; } } @@ -4660,6 +4660,48 @@ void sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr, int dest,int jumpIfNull){ sqlite3ExprDelete(db, pCopy); } +/* +** Expression pVar is guaranteed to be an SQL variable. pExpr may be any +** type of expression. +** +** If pExpr is a simple SQL value - an integer, real, string, blob +** or NULL value - then the VDBE currently being prepared is configured +** to re-prepare each time a new value is bound to variable pVar. +** +** Additionally, if pExpr is a simple SQL value and the value is the +** same as that currently bound to variable pVar, non-zero is returned. +** Otherwise, if the values are not the same or if pExpr is not a simple +** SQL value, zero is returned. +*/ +static int exprCompareVariable(Parse *pParse, Expr *pVar, Expr *pExpr){ + int res = 0; + int iVar = pVar->iColumn; + Expr *p = pExpr; + + while( p->op==TK_UMINUS ) p = p->pLeft; + if( p->op==TK_NULL || p->op==TK_INTEGER + || p->op==TK_FLOAT || p->op==TK_STRING + || p->op==TK_BLOB + ){ + sqlite3VdbeSetVarmask(pParse->pVdbe, iVar); + sqlite3_value *pL; + pL = sqlite3VdbeGetBoundValue(pParse->pReprepare, iVar, SQLITE_AFF_BLOB); + if( pL ){ + sqlite3_value *pR = 0; + sqlite3ValueFromExpr(pParse->db, pExpr, SQLITE_UTF8, SQLITE_AFF_BLOB,&pR); + assert( pR || pParse->db->mallocFailed ); + if( pR && 0==sqlite3MemCompare(pL, pR, 0) ){ + res = 1; + } + sqlite3ValueFree(pR); + sqlite3ValueFree(pL); + }else if( p->op==TK_NULL ){ + res = 1; + } + } + + return res; +} /* ** Do a deep comparison of two expression trees. Return 0 if the two @@ -4682,12 +4724,21 @@ void sqlite3ExprIfFalseDup(Parse *pParse, Expr *pExpr, int dest,int jumpIfNull){ ** this routine is used, it does not hurt to get an extra 2 - that ** just might result in some slightly slower code. But returning ** an incorrect 0 or 1 could lead to a malfunction. +** +** Argument pParse should normally be NULL. If it is not NULL and +** expression pA contains SQL variable references, then the values +** currently bound to those variable references may be compared to +** simple SQL values in pB. See comments above function exprCompareVariable() +** for details. */ -int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){ +int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){ u32 combinedFlags; if( pA==0 || pB==0 ){ return pB==pA ? 0 : 2; } + if( pParse && pA->op==TK_VARIABLE && exprCompareVariable(pParse, pA, pB) ){ + return 0; + } combinedFlags = pA->flags | pB->flags; if( combinedFlags & EP_IntValue ){ if( (pA->flags&pB->flags&EP_IntValue)!=0 && pA->u.iValue==pB->u.iValue ){ @@ -4696,10 +4747,10 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){ return 2; } if( pA->op!=pB->op ){ - if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB, iTab)<2 ){ + if( pA->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA->pLeft,pB,iTab)<2 ){ return 1; } - if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft, iTab)<2 ){ + if( pB->op==TK_COLLATE && sqlite3ExprCompare(pParse, pA,pB->pLeft,iTab)<2 ){ return 1; } return 2; @@ -4714,8 +4765,8 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){ if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){ if( combinedFlags & EP_xIsSelect ) return 2; - if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2; - if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2; + if( sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2; + if( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2; if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2; if( ALWAYS((combinedFlags & EP_Reduced)==0) && pA->op!=TK_STRING ){ if( pA->iColumn!=pB->iColumn ) return 2; @@ -4750,7 +4801,7 @@ int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){ Expr *pExprA = pA->a[i].pExpr; Expr *pExprB = pB->a[i].pExpr; if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1; - if( sqlite3ExprCompare(pExprA, pExprB, iTab) ) return 1; + if( sqlite3ExprCompare(0, pExprA, pExprB, iTab) ) return 1; } return 0; } @@ -4760,7 +4811,7 @@ int sqlite3ExprListCompare(ExprList *pA, ExprList *pB, int iTab){ ** are ignored. */ int sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab){ - return sqlite3ExprCompare( + return sqlite3ExprCompare(0, sqlite3ExprSkipCollate(pA), sqlite3ExprSkipCollate(pB), iTab); @@ -4786,20 +4837,20 @@ int sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab){ ** improvement. Returning false might cause a performance reduction, but ** it will always give the correct answer and is hence always safe. */ -int sqlite3ExprImpliesExpr(Expr *pE1, Expr *pE2, int iTab){ - if( sqlite3ExprCompare(pE1, pE2, iTab)==0 ){ +int sqlite3ExprImpliesExpr(Parse *pParse, Expr *pE1, Expr *pE2, int iTab){ + if( sqlite3ExprCompare(pParse, pE1, pE2, iTab)==0 ){ return 1; } if( pE2->op==TK_OR - && (sqlite3ExprImpliesExpr(pE1, pE2->pLeft, iTab) - || sqlite3ExprImpliesExpr(pE1, pE2->pRight, iTab) ) + && (sqlite3ExprImpliesExpr(pParse, pE1, pE2->pLeft, iTab) + || sqlite3ExprImpliesExpr(pParse, pE1, pE2->pRight, iTab) ) ){ return 1; } if( pE2->op==TK_NOTNULL && pE1->op!=TK_ISNULL && pE1->op!=TK_IS ){ Expr *pX = sqlite3ExprSkipCollate(pE1->pLeft); testcase( pX!=pE1->pLeft ); - if( sqlite3ExprCompare(pX, pE2->pLeft, iTab)==0 ) return 1; + if( sqlite3ExprCompare(pParse, pX, pE2->pLeft, iTab)==0 ) return 1; } return 0; } @@ -5040,7 +5091,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ */ struct AggInfo_func *pItem = pAggInfo->aFunc; for(i=0; inFunc; i++, pItem++){ - if( sqlite3ExprCompare(pItem->pExpr, pExpr, -1)==0 ){ + if( sqlite3ExprCompare(0, pItem->pExpr, pExpr, -1)==0 ){ break; } } diff --git a/src/insert.c b/src/insert.c index e684eaafa9..f296740a3e 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1898,7 +1898,7 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){ } if( pSrc->aiColumn[i]==XN_EXPR ){ assert( pSrc->aColExpr!=0 && pDest->aColExpr!=0 ); - if( sqlite3ExprCompare(pSrc->aColExpr->a[i].pExpr, + if( sqlite3ExprCompare(0, pSrc->aColExpr->a[i].pExpr, pDest->aColExpr->a[i].pExpr, -1)!=0 ){ return 0; /* Different expressions in the index */ } @@ -1910,7 +1910,7 @@ static int xferCompatibleIndex(Index *pDest, Index *pSrc){ return 0; /* Different collating sequences */ } } - if( sqlite3ExprCompare(pSrc->pPartIdxWhere, pDest->pPartIdxWhere, -1) ){ + if( sqlite3ExprCompare(0, pSrc->pPartIdxWhere, pDest->pPartIdxWhere, -1) ){ return 0; /* Different WHERE clauses */ } diff --git a/src/resolve.c b/src/resolve.c index f10add1241..8cddfd80bc 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -910,7 +910,7 @@ static int resolveOrderByTermToExprList( ** result-set entry. */ for(i=0; inExpr; i++){ - if( sqlite3ExprCompare(pEList->a[i].pExpr, pE, -1)<2 ){ + if( sqlite3ExprCompare(0, pEList->a[i].pExpr, pE, -1)<2 ){ return i+1; } } @@ -1144,7 +1144,7 @@ static int resolveOrderGroupBy( return 1; } for(j=0; jpEList->nExpr; j++){ - if( sqlite3ExprCompare(pE, pSelect->pEList->a[j].pExpr, -1)==0 ){ + if( sqlite3ExprCompare(0, pE, pSelect->pEList->a[j].pExpr, -1)==0 ){ pItem->u.x.iOrderByCol = j+1; } } diff --git a/src/select.c b/src/select.c index 74747fadc2..ebe6ac46f7 100644 --- a/src/select.c +++ b/src/select.c @@ -5005,7 +5005,9 @@ static struct SrcList_item *isSelfJoinView( if( pItem->zName==0 ) continue; if( sqlite3_stricmp(pItem->zDatabase, pThis->zDatabase)!=0 ) continue; if( sqlite3_stricmp(pItem->zName, pThis->zName)!=0 ) continue; - if( sqlite3ExprCompare(pThis->pSelect->pWhere, pItem->pSelect->pWhere, -1) ){ + if( sqlite3ExprCompare(0, + pThis->pSelect->pWhere, pItem->pSelect->pWhere, -1) + ){ /* The view was modified by some other optimization such as ** pushDownWhereTerms() */ continue; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index ee83a511f2..8cab60977c 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3781,10 +3781,10 @@ void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*); void sqlite3Vacuum(Parse*,Token*); int sqlite3RunVacuum(char**, sqlite3*, int); char *sqlite3NameFromToken(sqlite3*, Token*); -int sqlite3ExprCompare(Expr*, Expr*, int); +int sqlite3ExprCompare(Parse*,Expr*, Expr*, int); int sqlite3ExprCompareSkip(Expr*, Expr*, int); int sqlite3ExprListCompare(ExprList*, ExprList*, int); -int sqlite3ExprImpliesExpr(Expr*, Expr*, int); +int sqlite3ExprImpliesExpr(Parse*,Expr*, Expr*, int); void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*); void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*); int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx); diff --git a/src/where.c b/src/where.c index 41bcb30314..cc09bbbf81 100644 --- a/src/where.c +++ b/src/where.c @@ -2654,7 +2654,7 @@ static int indexMightHelpWithOrderBy( }else if( (aColExpr = pIndex->aColExpr)!=0 ){ for(jj=0; jjnKeyCol; jj++){ if( pIndex->aiColumn[jj]!=XN_EXPR ) continue; - if( sqlite3ExprCompare(pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){ + if( sqlite3ExprCompare(0, pExpr,aColExpr->a[jj].pExpr,iCursor)==0 ){ return 1; } } @@ -2693,7 +2693,7 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){ } for(i=0, pTerm=pWC->a; inTerm; i++, pTerm++){ Expr *pExpr = pTerm->pExpr; - if( sqlite3ExprImpliesExpr(pExpr, pWhere, iTab) + if( sqlite3ExprImpliesExpr(pWC->pWInfo->pParse, pExpr, pWhere, iTab) && (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab) ){ return 1; @@ -3673,7 +3673,8 @@ static i8 wherePathSatisfiesOrderBy( if( pOBExpr->iTable!=iCur ) continue; if( pOBExpr->iColumn!=iColumn ) continue; }else{ - if( sqlite3ExprCompare(pOBExpr,pIndex->aColExpr->a[j].pExpr,iCur) ){ + if( sqlite3ExprCompare(0, + pOBExpr,pIndex->aColExpr->a[j].pExpr,iCur) ){ continue; } } diff --git a/src/wherecode.c b/src/wherecode.c index 7d1ea38596..dc982938ac 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -1058,7 +1058,7 @@ typedef struct IdxExprTrans { */ static int whereIndexExprTransNode(Walker *p, Expr *pExpr){ IdxExprTrans *pX = p->u.pIdxTrans; - if( sqlite3ExprCompare(pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){ + if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){ pExpr->op = TK_COLUMN; pExpr->iTable = pX->iIdxCur; pExpr->iColumn = pX->iIdxCol; diff --git a/src/whereexpr.c b/src/whereexpr.c index 3625efa1e3..53bc3dba12 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -406,8 +406,8 @@ static void whereCombineDisjuncts( && (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return; assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 ); assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 ); - if( sqlite3ExprCompare(pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return; - if( sqlite3ExprCompare(pOne->pExpr->pRight, pTwo->pExpr->pRight, -1) )return; + if( sqlite3ExprCompare(0,pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return; + if( sqlite3ExprCompare(0,pOne->pExpr->pRight, pTwo->pExpr->pRight,-1) )return; /* If we reach this point, it means the two subterms can be combined */ if( (eOp & (eOp-1))!=0 ){ if( eOp & (WO_LT|WO_LE) ){ diff --git a/test/index9.test b/test/index9.test new file mode 100644 index 0000000000..fe117887fd --- /dev/null +++ b/test/index9.test @@ -0,0 +1,82 @@ +# 2017 Jun 24 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# +# Test that partial indexes work with bound variables. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix index9 + +proc sqluses {sql} { + array unset ::T + uplevel [list db eval "EXPLAIN $sql" a { + if {$a(opcode)=="OpenRead"} { set ::T($a(p2)) 1 } + }] + + set in [join [array names ::T] ,] + db eval "SELECT name FROM sqlite_master WHERE rootpage IN ($in) ORDER BY 1" +} + +proc do_sqluses_test {tn sql objects} { + uplevel [list do_test $tn [list sqluses $sql] $objects] +} + +do_execsql_test 1.0 { + CREATE TABLE t1(x, y); + CREATE INDEX t1x ON t1(x) WHERE y=45; +} +set y [expr 45] +do_sqluses_test 1.1 { SELECT * FROM t1 WHERE x=? AND y=$y } {t1 t1x} +set y [expr 45.1] +do_sqluses_test 1.2 { SELECT * FROM t1 WHERE x=? AND y=$y } {t1} +set y [expr 44] +do_sqluses_test 1.3 { SELECT * FROM t1 WHERE x=? AND y=$y } {t1} +unset -nocomplain y +do_sqluses_test 1.4 { SELECT * FROM t1 WHERE x=? AND y=$y } {t1} +set y [string range "45" 0 end] +do_sqluses_test 1.5 { SELECT * FROM t1 WHERE x=? AND y=$y } {t1} + +do_execsql_test 2.0 { + CREATE INDEX t1x2 ON t1(x) WHERE y=-20111000111 +} +do_sqluses_test 2.1 { SELECT * FROM t1 WHERE y=$y ORDER BY x } {t1} +set y [expr -20111000111] +do_sqluses_test 2.2 { SELECT * FROM t1 WHERE y=$y ORDER BY x } {t1 t1x2} +set y [expr -20111000110] +do_sqluses_test 2.3 { SELECT * FROM t1 WHERE y=$y ORDER BY x } {t1} +set y [expr -20111000112] +do_sqluses_test 2.4 { SELECT * FROM t1 WHERE y=$y ORDER BY x } {t1} + +do_execsql_test 3.0 { + CREATE INDEX t1x3 ON t1(x) WHERE y=9223372036854775807 +} +set y [expr 9223372036854775807] +do_sqluses_test 3.1 { SELECT * FROM t1 WHERE y=$y ORDER BY x } {t1 t1x3} +set y [expr 9223372036854775808] +do_sqluses_test 3.2 { SELECT * FROM t1 WHERE y=$y ORDER BY x } {t1} +set y [expr 9223372036854775806] +do_sqluses_test 3.3 { SELECT * FROM t1 WHERE y=$y ORDER BY x } {t1} + +do_execsql_test 3.0 { + CREATE INDEX t1x4 ON t1(x) WHERE y=-9223372036854775808 +} +set y [expr -9223372036854775808] +do_sqluses_test 3.1 { SELECT * FROM t1 WHERE y=$y ORDER BY x } {t1 t1x4} +set y [expr -9223372036854775807] +do_sqluses_test 3.2 { SELECT * FROM t1 WHERE y=$y ORDER BY x } {t1} +set y [expr -9223372036854775809] +do_sqluses_test 3.3 { SELECT * FROM t1 WHERE y=$y ORDER BY x } {t1} +set y [expr -9223372036854775808] +do_sqluses_test 3.4 { SELECT * FROM t1 WHERE $y=y ORDER BY x } {t1 t1x4} + +finish_test +