When multiple constraints need to be evaluated for a row, do any constraints
that involve correlated subqueries last. Hence, the priority is index-covered constraints first, correlated subquery constraints last, and all others in the middle. This is a follow-on and improvement to the push-down optimization of check-in [d7bb79ed]. FossilOrigin-Name: c4cb90487f34937605732c3959891075e2aabfb0bd05e55c44565d65867093ea
This commit is contained in:
commit
90e39ec349
19
manifest
19
manifest
@ -1,5 +1,5 @@
|
||||
C For\ssqlite3TreeView()\sdebugging\soutput,\sshow\sthe\sExpr.flags\sfield\son\nscalar\ssubqueries.
|
||||
D 2017-07-10T13:24:58.019
|
||||
C When\smultiple\sconstraints\sneed\sto\sbe\sevaluated\sfor\sa\srow,\sdo\sany\sconstraints\nthat\sinvolve\scorrelated\ssubqueries\slast.\s\sHence,\sthe\spriority\sis\sindex-covered\nconstraints\sfirst,\scorrelated\ssubquery\sconstraints\slast,\sand\sall\sothers\sin\nthe\smiddle.\s\sThis\sis\sa\nfollow-on\sand\simprovement\sto\sthe\spush-down\soptimization\sof\scheck-in\s[d7bb79ed].
|
||||
D 2017-07-10T17:00:31.898
|
||||
F Makefile.in 081e48dfe7f995d57ce1a88ddf4d2917b4349158648a6cd45b42beae30de3a12
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 20850e3e8d4d4791e0531955852d768eb06f24138214870d543abb1a47346fba
|
||||
@ -530,9 +530,9 @@ F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344
|
||||
F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71
|
||||
F src/walker.c a7ca64ce08a83a20d32186fbe06bca9234e348cfcf07959ee322fdc3e8a6173a
|
||||
F src/where.c e7cc80943459ade4ccaeb5c7c10f8a0db8b797e0b0f2509de7efc557b76bf7b6
|
||||
F src/whereInt.h 2a4b634d63ce488b46d4b0da8f2eaa8f9aeab202bc25ef76f007de5e3fba1f20
|
||||
F src/wherecode.c f17f5d51e372168db51af637e265aa5e80f99fcc81bfead96b66e71a7732bc62
|
||||
F src/whereexpr.c fa51927cc6830b9d3155cafa4e589452ec023fe313a56550d2079dca6c52fbd8
|
||||
F src/whereInt.h 93bb90b77d39901eda31b44d8e90da1351193ccfe96876f89b58a93a33b84c3d
|
||||
F src/wherecode.c c0c4c31573486cd14bb2cbfc63e41eda591609e5190416261999f211bf97abc1
|
||||
F src/whereexpr.c bf983d2d33e325cd63a36c40b8de289fd3d7b4d9f2db9052fb8f59f7161a34a0
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
|
||||
@ -1091,7 +1091,7 @@ F test/printf.test b3ff34e73d59124140eaf89f7672e21bc2ca5fcc
|
||||
F test/printf2.test 9e6db85f81c63f2367c34a9d7db384088bd374ad
|
||||
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
|
||||
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
||||
F test/pushdown.test a5d2e5e66cc94cfb0989a5dd23e77427dd6c4313019155ba9051f52dfc5326aa
|
||||
F test/pushdown.test df9a5d1822531fc79fa46b622a7ee5fdf5cdc81fd2740443df59cc90b746abb6
|
||||
F test/queryonly.test 5f653159e0f552f0552d43259890c1089391dcca
|
||||
F test/quick.test 1681febc928d686362d50057c642f77a02c62e57
|
||||
F test/quota-glob.test 32901e9eed6705d68ca3faee2a06b73b57cb3c26
|
||||
@ -1628,7 +1628,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P f27b6370407842e2c175ea4aa9ce018723c57eaac0cccc1f8399bc20f33324be
|
||||
R fcaff20edc67c3421a07c8a2f98bc875
|
||||
P dc857a96b00f13ffdf77bc222bc5acbbe14a36ca51e5368b568b3177d1be737a 0ca7474f05e9f27f53f8c71f5a3ff99963ffef9be9c147869e096246d552d6f1
|
||||
R 6bf4c162edf7ff6903aaf314bb0ae2fb
|
||||
T +closed 0ca7474f05e9f27f53f8c71f5a3ff99963ffef9be9c147869e096246d552d6f1
|
||||
U drh
|
||||
Z 4c32d3cf2874c5b6c91c344882e30f5e
|
||||
Z acda2b95cccbca8a55a4e5255bd0a430
|
||||
|
@ -1 +1 @@
|
||||
dc857a96b00f13ffdf77bc222bc5acbbe14a36ca51e5368b568b3177d1be737a
|
||||
c4cb90487f34937605732c3959891075e2aabfb0bd05e55c44565d65867093ea
|
@ -284,6 +284,7 @@ struct WhereTerm {
|
||||
#define TERM_LIKECOND 0x200 /* Conditionally this LIKE operator term */
|
||||
#define TERM_LIKE 0x400 /* The original LIKE operator */
|
||||
#define TERM_IS 0x800 /* Term.pExpr is an IS operator */
|
||||
#define TERM_VARSELECT 0x1000 /* Term.pExpr contains a correlated sub-query */
|
||||
|
||||
/*
|
||||
** An instance of the WhereScan object is used as an iterator for locating
|
||||
@ -373,6 +374,7 @@ struct WhereAndInfo {
|
||||
** no gaps.
|
||||
*/
|
||||
struct WhereMaskSet {
|
||||
int bVarSelect; /* Used by sqlite3WhereExprUsage() */
|
||||
int n; /* Number of assigned cursor values */
|
||||
int ix[BMS]; /* Cursor assigned to each bit */
|
||||
};
|
||||
|
@ -1130,7 +1130,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
int iRowidReg = 0; /* Rowid is stored in this register, if not zero */
|
||||
int iReleaseReg = 0; /* Temp register to free before returning */
|
||||
Index *pIdx = 0; /* Index used by loop (if any) */
|
||||
int loopAgain; /* True if constraint generator loop should repeat */
|
||||
int iLoop; /* Iteration of constraint generator loop */
|
||||
|
||||
pParse = pWInfo->pParse;
|
||||
v = pParse->pVdbe;
|
||||
@ -2025,13 +2025,20 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
/* Insert code to test every subexpression that can be completely
|
||||
** computed using the current set of tables.
|
||||
**
|
||||
** This loop may run either once (pIdx==0) or twice (pIdx!=0). If
|
||||
** it is run twice, then the first iteration codes those sub-expressions
|
||||
** that can be computed using columns from pIdx only (without seeking
|
||||
** the main table cursor).
|
||||
** This loop may run between one and three times, depending on the
|
||||
** constraints to be generated. The value of stack variable iLoop
|
||||
** determines the constraints coded by each iteration, as follows:
|
||||
**
|
||||
** iLoop==1: Code only expressions that are entirely covered by pIdx.
|
||||
** iLoop==2: Code remaining expressions that do not contain correlated
|
||||
** sub-queries.
|
||||
** iLoop==3: Code all remaining expressions.
|
||||
**
|
||||
** An effort is made to skip unnecessary iterations of the loop.
|
||||
*/
|
||||
iLoop = (pIdx ? 1 : 2);
|
||||
do{
|
||||
loopAgain = 0;
|
||||
int iNext = 0; /* Next value for iLoop */
|
||||
for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
|
||||
Expr *pE;
|
||||
int skipLikeAddr = 0;
|
||||
@ -2049,10 +2056,16 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
|
||||
continue;
|
||||
}
|
||||
if( pIdx && !sqlite3ExprCoveredByIndex(pE, pLevel->iTabCur, pIdx) ){
|
||||
loopAgain = 1;
|
||||
|
||||
if( iLoop==1 && !sqlite3ExprCoveredByIndex(pE, pLevel->iTabCur, pIdx) ){
|
||||
iNext = 2;
|
||||
continue;
|
||||
}
|
||||
if( iLoop<3 && (pTerm->wtFlags & TERM_VARSELECT) ){
|
||||
if( iNext==0 ) iNext = 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( pTerm->wtFlags & TERM_LIKECOND ){
|
||||
/* If the TERM_LIKECOND flag is set, that means that the range search
|
||||
** is sufficient to guarantee that the LIKE operator is true, so we
|
||||
@ -2068,12 +2081,18 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
VdbeCoverage(v);
|
||||
#endif
|
||||
}
|
||||
#ifdef WHERETRACE_ENABLED /* 0xffff */
|
||||
if( sqlite3WhereTrace ){
|
||||
VdbeNoopComment((v, "WhereTerm[%d] (%p) priority=%d",
|
||||
pWC->nTerm-j, pTerm, iLoop));
|
||||
}
|
||||
#endif
|
||||
sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
|
||||
if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr);
|
||||
pTerm->wtFlags |= TERM_CODED;
|
||||
}
|
||||
pIdx = 0;
|
||||
}while( loopAgain );
|
||||
iLoop = iNext;
|
||||
}while( iLoop>0 );
|
||||
|
||||
/* Insert code to test for implied constraints based on transitivity
|
||||
** of the "==" operator.
|
||||
|
@ -951,7 +951,9 @@ static void exprAnalyze(
|
||||
}else{
|
||||
pTerm->prereqRight = sqlite3WhereExprUsage(pMaskSet, pExpr->pRight);
|
||||
}
|
||||
pMaskSet->bVarSelect = 0;
|
||||
prereqAll = sqlite3WhereExprUsage(pMaskSet, pExpr);
|
||||
if( pMaskSet->bVarSelect ) pTerm->wtFlags |= TERM_VARSELECT;
|
||||
if( ExprHasProperty(pExpr, EP_FromJoin) ){
|
||||
Bitmask x = sqlite3WhereGetMask(pMaskSet, pExpr->iRightJoinTable);
|
||||
prereqAll |= x;
|
||||
@ -1382,9 +1384,12 @@ Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){
|
||||
}
|
||||
mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0;
|
||||
assert( !ExprHasProperty(p, EP_TokenOnly) );
|
||||
if( p->pRight ) mask |= sqlite3WhereExprUsage(pMaskSet, p->pRight);
|
||||
if( p->pLeft ) mask |= sqlite3WhereExprUsage(pMaskSet, p->pLeft);
|
||||
if( ExprHasProperty(p, EP_xIsSelect) ){
|
||||
if( p->pRight ){
|
||||
mask |= sqlite3WhereExprUsage(pMaskSet, p->pRight);
|
||||
assert( p->x.pList==0 );
|
||||
}else if( ExprHasProperty(p, EP_xIsSelect) ){
|
||||
if( ExprHasProperty(p, EP_VarSelect) ) pMaskSet->bVarSelect = 1;
|
||||
mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
|
||||
}else if( p->x.pList ){
|
||||
mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
|
||||
|
@ -55,5 +55,38 @@ do_test 1.5 {
|
||||
execsql { SELECT * FROM t1 WHERE a=3 AND f(c) AND f(b) }
|
||||
set L
|
||||
} {b3}
|
||||
|
||||
#-----------------------------------------------
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE TABLE u1(a, b, c);
|
||||
CREATE TABLE u2(x, y, z);
|
||||
|
||||
INSERT INTO u1 VALUES('a1', 'b1', 'c1');
|
||||
INSERT INTO u2 VALUES('a1', 'b1', 'c1');
|
||||
}
|
||||
|
||||
do_test 2.1 {
|
||||
set L [list]
|
||||
execsql {
|
||||
SELECT * FROM u1 WHERE f('one')=123 AND 123=(
|
||||
SELECT x FROM u2 WHERE x=a AND f('two')
|
||||
)
|
||||
}
|
||||
set L
|
||||
} {one}
|
||||
|
||||
do_test 2.2 {
|
||||
set L [list]
|
||||
breakpoint
|
||||
execsql {
|
||||
SELECT * FROM u1 WHERE 123=(
|
||||
SELECT x FROM u2 WHERE x=a AND f('two')
|
||||
) AND f('three')=123
|
||||
}
|
||||
set L
|
||||
} {three}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
Loading…
x
Reference in New Issue
Block a user