mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Consider the values bound to SQL variables when determining whether or not a
partial index may be used. FossilOrigin-Name: 7b59c353b805c64689b4ae9df347705acbb5f116346ad77af8ce087da7893747
This commit is contained in:
32
manifest
32
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
|
||||
|
@@ -1 +1 @@
|
||||
c2ea62937ec8fabec72d3c7cd38d8e2cabbb5ce48638f8ce7ebefd6cd2716fd3
|
||||
7b59c353b805c64689b4ae9df347705acbb5f116346ad77af8ce087da7893747
|
81
src/expr.c
81
src/expr.c
@@ -1829,7 +1829,7 @@ static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){
|
||||
** it constant. */
|
||||
for(i=0; i<pGroupBy->nExpr; 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; i<pAggInfo->nFunc; i++, pItem++){
|
||||
if( sqlite3ExprCompare(pItem->pExpr, pExpr, -1)==0 ){
|
||||
if( sqlite3ExprCompare(0, pItem->pExpr, pExpr, -1)==0 ){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@@ -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 */
|
||||
}
|
||||
|
||||
|
@@ -910,7 +910,7 @@ static int resolveOrderByTermToExprList(
|
||||
** result-set entry.
|
||||
*/
|
||||
for(i=0; i<pEList->nExpr; 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; j<pSelect->pEList->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;
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -2654,7 +2654,7 @@ static int indexMightHelpWithOrderBy(
|
||||
}else if( (aColExpr = pIndex->aColExpr)!=0 ){
|
||||
for(jj=0; jj<pIndex->nKeyCol; 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; i<pWC->nTerm; 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;
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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) ){
|
||||
|
82
test/index9.test
Normal file
82
test/index9.test
Normal file
@@ -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
|
||||
|
Reference in New Issue
Block a user