Merge latest trunk changes into this branch.

FossilOrigin-Name: 9685880f7baeb670739fdcf2d9df08e22abaa699
This commit is contained in:
dan 2016-07-28 13:59:21 +00:00
commit 34c125747d
8 changed files with 182 additions and 18 deletions

View File

@ -1,5 +1,5 @@
C Fix\ssome\sproblems\swith\smulti-column\sIN(SELECT...)\sprocessing.
D 2016-07-27T19:33:04.107
C Merge\slatest\strunk\schanges\sinto\sthis\sbranch.
D 2016-07-28T13:59:21.728
F Makefile.in 6c20d44f72d4564f11652b26291a214c8367e5db
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc d66d0395c38571aab3804f8db0fa20707ae4609a
@ -337,7 +337,7 @@ F src/ctime.c 61949e83c4c36e37195a8398ebc752780b534d95
F src/date.c 1cc9fb516ec9932c6fd4d2a0d2f8bc4480145c39
F src/dbstat.c 4f6f7f52b49beb9636ffbd517cfe44a402ba4ad0
F src/delete.c 4aba4214a377ce8ddde2d2e609777bcc8235200f
F src/expr.c bee29fbb017db26ad1189d35b2a7fe6ff8da3722
F src/expr.c 82bc40bb27bc68b45303b560ab14eb16e39786a7
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c bc4145347595b7770f9a598cff1c848302cf5413
F src/func.c 61a4114cf7004f10c542cfabbab9f2bcb9033045
@ -388,7 +388,7 @@ F src/shell.c 9351fc6de11e1d908648c0a92d85627138e3dee5
F src/sqlite.h.in c6e68a4a47610631822a4f8f83a44c9f75339331
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 46f300b6e300e0fa916d7d58c44b53415b8471a9
F src/sqliteInt.h 9a6af8787f03f54ce02ff88bd45f89bb600c3a4c
F src/sqliteInt.h 65cf752e1a62cedb2430ecc0547a09833ea13616
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
F src/status.c 5b18f9526900f61189ab0b83f1ef41d9f871a2ab
F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
@ -463,7 +463,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
F src/wal.c 02eeecc265f6ffd0597378f5d8ae9070b62a406a
F src/wal.h 6dd221ed384afdc204bc61e25c23ef7fd5a511f2
F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354
F src/where.c 0b370db8ce08fac93a098f27eaf425d2269be376
F src/where.c df58d6ad7878a08aa96c652ccbc6d0949f8fa472
F src/whereInt.h 14dd243e13b81cbb0a66063d38b70f93a7d6e613
F src/wherecode.c 3aff7683566af3428f865904aafa7efb1fbd8701
F src/whereexpr.c b896f8ff6a53cbd3daaee84ec33e39098762bb46
@ -845,6 +845,7 @@ F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
F test/index6.test 43b4e29258b978fcdab84fc61df4f5212119dd09
F test/index7.test 9c6765a74fc3fcde7aebc5b3bd40d98df14a527c
F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7
F test/indexedby.test 9c4cd331224e57f79fbf411ae245e6272d415985
F test/indexexpr1.test cb71b6586177b840e28110dd952178bb2bdfedc2
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
@ -984,7 +985,7 @@ F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f
F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8
F test/pageropt.test 84e4cc5cbca285357f7906e99b21be4f2bf5abc0
F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305
F test/parser1.test 222b5cbf3e2e659fec1bf7d723488c8b9c94f1d0
F test/parser1.test 391b9bf9a229547a129c61ac345ed1a6f5eb1854
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
@ -1029,7 +1030,7 @@ F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd
F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7
F test/savepoint7.test cde525ea3075283eb950cdcdefe23ead4f700daa
F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2
F test/scanstatus.test 5253c219e331318a437f436268e0e82345700285
F test/scanstatus.test 030acbbdcea6a3fc676fee99edc84f6f16c0cf92
F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
F test/schema3.test 1bc1008e1f8cb5654b248c55f27249366eb7ed38
@ -1510,7 +1511,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P d4f3d52c5a11fc7ad7e8cad76361edbcef13a12f 4d59df02d3713b3e3804e1a88e676749b2794286
R 1d3755c62e27d021f9887ac09a170360
P 719a3b2035a335ca8b9704646b1d641011e3ea0e 6feff15cae8f0427be790355841d49c479c1c586
R 3c287799720eaa100d938a8b5fd4645d
U dan
Z 2549ddc5292b60c5848a8cde952880f9
Z 3b75e2ba5b9150b77f0261ae152b7ba4

View File

@ -1 +1 @@
719a3b2035a335ca8b9704646b1d641011e3ea0e
9685880f7baeb670739fdcf2d9df08e22abaa699

View File

@ -4312,6 +4312,61 @@ int sqlite3ExprImpliesExpr(Expr *pE1, Expr *pE2, int iTab){
return 0;
}
/*
** An instance of the following structure is used by the tree walker
** to determine if an expression can be evaluated by reference to the
** index only, without having to do a search for the corresponding
** table entry. The IdxCover.pIdx field is the index. IdxCover.iCur
** is the cursor for the table.
*/
struct IdxCover {
Index *pIdx; /* The index to be tested for coverage */
int iCur; /* Cursor number for the table corresponding to the index */
};
/*
** Check to see if there are references to columns in table
** pWalker->u.pIdxCover->iCur can be satisfied using the index
** pWalker->u.pIdxCover->pIdx.
*/
static int exprIdxCover(Walker *pWalker, Expr *pExpr){
if( pExpr->op==TK_COLUMN
&& pExpr->iTable==pWalker->u.pIdxCover->iCur
&& sqlite3ColumnOfIndex(pWalker->u.pIdxCover->pIdx, pExpr->iColumn)<0
){
pWalker->eCode = 1;
return WRC_Abort;
}
return WRC_Continue;
}
/*
** Determine if an index pIdx on table with cursor iCur contains will
** the expression pExpr. Return true if the index does cover the
** expression and false if the pExpr expression references table columns
** that are not found in the index pIdx.
**
** An index covering an expression means that the expression can be
** evaluated using only the index and without having to lookup the
** corresponding table entry.
*/
int sqlite3ExprCoveredByIndex(
Expr *pExpr, /* The index to be tested */
int iCur, /* The cursor number for the corresponding table */
Index *pIdx /* The index that might be used for coverage */
){
Walker w;
struct IdxCover xcov;
memset(&w, 0, sizeof(w));
xcov.iCur = iCur;
xcov.pIdx = pIdx;
w.xExprCallback = exprIdxCover;
w.u.pIdxCover = &xcov;
sqlite3WalkExpr(&w, pExpr);
return !w.eCode;
}
/*
** An instance of the following structure is used by the tree walker
** to count references to table columns in the arguments of an

View File

@ -3258,6 +3258,7 @@ struct Walker {
struct SrcCount *pSrcCount; /* Counting column references */
struct CCurHint *pCCurHint; /* Used by codeCursorHint() */
int *aiCol; /* array of column indexes */
struct IdxCover *pIdxCover; /* Check for index coverage */
} u;
};
@ -3701,6 +3702,7 @@ int sqlite3ExprListCompare(ExprList*, ExprList*, int);
int sqlite3ExprImpliesExpr(Expr*, Expr*, int);
void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx);
int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
Vdbe *sqlite3GetVdbe(Parse*);
#ifndef SQLITE_OMIT_BUILTIN_TEST

View File

@ -2539,11 +2539,11 @@ static int whereLoopAddBtreeIndex(
pNew->nSkip++;
pNew->aLTerm[pNew->nLTerm++] = 0;
pNew->wsFlags |= WHERE_SKIPSCAN;
nIter = pProbe->aiRowLogEst[saved_nEq] - pProbe->aiRowLogEst[saved_nEq+1];
nIter = pProbe->aiRowLogEst[saved_nEq]+1 - pProbe->aiRowLogEst[saved_nEq+1];
pNew->nOut -= nIter;
/* TUNING: Because uncertainties in the estimates for skip-scan queries,
** add a 1.375 fudge factor to make skip-scan slightly less likely. */
nIter += 5;
nIter += 4;
whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter + nInMul);
pNew->nOut = saved_nOut;
pNew->u.btree.nEq = saved_nEq;
@ -2838,11 +2838,34 @@ static int whereLoopAddBtree(
/* The cost of visiting the index rows is N*K, where K is
** between 1.1 and 3.0, depending on the relative sizes of the
** index and table rows. If this is a non-covering index scan,
** also add the cost of visiting table rows (N*3.0). */
** index and table rows. */
pNew->rRun = rSize + 1 + (15*pProbe->szIdxRow)/pTab->szTabRow;
if( m!=0 ){
pNew->rRun = sqlite3LogEstAdd(pNew->rRun, rSize+16);
/* If this is a non-covering index scan, add in the cost of
** doing table lookups. The cost will be 3x the number of
** lookups. Take into account WHERE clause terms that can be
** satisfied using just the index, and that do not require a
** table lookup. */
LogEst nLookup = rSize + 16; /* Base cost: N*3 */
int ii;
int iCur = pSrc->iCursor;
WhereClause *pWC = &pWInfo->sWC;
for(ii=0; ii<pWC->nTerm; ii++){
WhereTerm *pTerm = &pWC->a[ii];
if( !sqlite3ExprCoveredByIndex(pTerm->pExpr, iCur, pProbe) ){
break;
}
/* pTerm can be evaluated using just the index. So reduce
** the expected number of table lookups accordingly */
if( pTerm->truthProb<=0 ){
nLookup += pTerm->truthProb;
}else{
nLookup--;
if( pTerm->eOperator & (WO_EQ|WO_IS) ) nLookup -= 19;
}
}
pNew->rRun = sqlite3LogEstAdd(pNew->rRun, nLookup);
}
ApplyCostMultiplier(pNew->rRun, pTab->costMult);
whereLoopOutputAdjust(pWC, pNew, rSize);

60
test/index8.test Normal file
View File

@ -0,0 +1,60 @@
# 2016-07-27
#
# 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 cases for ORDER BY and LIMIT on an index scan.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Performance regression reported at
# http://www.mail-archive.com/sqlite-users@mailinglists.sqlite.org/msg98615.html
#
# Caused by the ORDER BY LIMIT optionation for check-in
# https://sqlite.org/src/info/bf46179d44843769
#
# Fixed on approximately 2016-07-27 by changes that compute a better score
# for index scans by taking into account WHERE clause constraints that can
# be handled by the index and do not require a table lookup.
#
do_execsql_test 1.0 {
CREATE TABLE t1(a,b,c,d);
WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<100)
INSERT INTO t1(a,b,c,d)
SELECT x/10, x%10, x%19, x FROM c;
CREATE INDEX t1abc ON t1(a,b,c);
SELECT * FROM t1 WHERE c=4 ORDER BY a, b LIMIT 2;
} {0 4 4 4 2 3 4 23}
# Prior to the fix, the following EQP would show a table scan and a sort
# rather than an index scan.
#
do_execsql_test 1.0eqp {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE c=4 ORDER BY a, b LIMIT 2;
} {/SCAN TABLE t1 USING INDEX t1abc/}
# If we change the index so that it no longer covers the WHERE clause,
# then we should (correctly) revert to using a table scan.
#
do_execsql_test 1.1 {
DROP INDEX t1abc;
CREATE INDEX t1abd ON t1(a,b,d);
SELECT * FROM t1 WHERE c=4 ORDER BY a, b LIMIT 2;
} {0 4 4 4 2 3 4 23}
do_execsql_test 1.1eqp {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE c=4 ORDER BY a, b LIMIT 2;
} {~/USING INDEX/}
finish_test

View File

@ -76,4 +76,27 @@ do_catchsql_test parser1-2.2 {
SELECT x FROM c;
} {1 {syntax error after column name "x"}}
# Verify that the comma between multiple table constraints is
# optional.
#
# The missing comma is technically a syntax error. But we have to support
# it because there might be legacy databases that omit the commas in their
# sqlite_master tables.
#
do_execsql_test parser1-3.1 {
CREATE TABLE t300(id INTEGER PRIMARY KEY);
CREATE TABLE t301(
id INTEGER PRIMARY KEY,
c1 INTEGER NOT NULL,
c2 INTEGER NOT NULL,
c3 BOOLEAN NOT NULL DEFAULT 0,
FOREIGN KEY(c1) REFERENCES t300(id) ON DELETE CASCADE ON UPDATE RESTRICT
/* no comma */
FOREIGN KEY(c2) REFERENCES t300(id) ON DELETE CASCADE ON UPDATE RESTRICT
/* no comma */
UNIQUE(c1, c2)
);
PRAGMA foreign_key_list(t301);
} {0 0 t300 c2 id RESTRICT CASCADE NONE 1 0 t300 c1 id RESTRICT CASCADE NONE}
finish_test

View File

@ -333,7 +333,7 @@ do_execsql_test 5.3.2 {
SELECT count(*) FROM t2 WHERE y = 'j';
} {19}
do_scanstatus_test 5.3.3 {
nLoop 1 nVisit 19 nEst 56.0 zName t2xy zExplain
nLoop 1 nVisit 19 nEst 52.0 zName t2xy zExplain
{SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
}
@ -349,7 +349,7 @@ do_execsql_test 5.4.2 {
do_scanstatus_test 5.4.3 {
nLoop 1 nVisit 10 nEst 10.0 zName t1bc
zExplain {SCAN TABLE t1 USING COVERING INDEX t1bc}
nLoop 10 nVisit 200 nEst 56.0 zName t2xy
nLoop 10 nVisit 200 nEst 52.0 zName t2xy
zExplain {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
}