mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Use the NGQP plan for EXPLAIN QUERY PLAN output. This change causes 207
errors in veryquick.test, many of which are benign. FossilOrigin-Name: f783e8e6b10de44029c7c5f57e4648a4a677ca1b
This commit is contained in:
14
manifest
14
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Allow\sthe\srowid\sat\sthe\send\sof\san\sindex\sto\sbe\sused\sin\sa\sconstraint\son\sthat\sindex.
|
C Use\sthe\sNGQP\splan\sfor\sEXPLAIN\sQUERY\sPLAN\soutput.\s\sThis\schange\scauses\s207\nerrors\sin\sveryquick.test,\smany\sof\swhich\sare\sbenign.
|
||||||
D 2013-05-22T17:01:17.424
|
D 2013-05-22T20:49:02.170
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in f6b58b7bdf6535f0f0620c486dd59aa4662c0b4f
|
F Makefile.in f6b58b7bdf6535f0f0620c486dd59aa4662c0b4f
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@@ -265,7 +265,7 @@ F src/vtab.c b05e5f1f4902461ba9f5fc49bb7eb7c3a0741a83
|
|||||||
F src/wal.c 436bfceb141b9423c45119e68e444358ee0ed35d
|
F src/wal.c 436bfceb141b9423c45119e68e444358ee0ed35d
|
||||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||||
F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73
|
F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73
|
||||||
F src/where.c 3ca12d203c0cca5bc36f0cd408a97ed5a9357047
|
F src/where.c 627bf1af3ab30e1efcc7ac362b15e7e945e9250d
|
||||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||||
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
|
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
|
||||||
@@ -779,7 +779,7 @@ F test/tclsqlite.test 37a61c2da7e3bfe3b8c1a2867199f6b860df5d43
|
|||||||
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
|
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
|
||||||
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||||
F test/temptrigger.test 26670ed7a39cf2296a7f0a9e0a1d7bdb7abe936d
|
F test/temptrigger.test 26670ed7a39cf2296a7f0a9e0a1d7bdb7abe936d
|
||||||
F test/tester.tcl 3b08771e6d601612fe62d13787db0e50aac4cf7b
|
F test/tester.tcl 693700993b7e0a5b7b2171b291a54cdbad1d86ff
|
||||||
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
|
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
|
||||||
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
|
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
|
||||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||||
@@ -1065,7 +1065,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||||
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
|
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
|
||||||
P 12c709b4369c7d94d7fb743d0d0da7a9350a3d16
|
P 9bf0524df7ca2e7fcd92b2878a8457264b3c7f6e
|
||||||
R 7322735243734361422a3e6e35778930
|
R 97f27b7ea9f3efcce127b9443ade87ed
|
||||||
U drh
|
U drh
|
||||||
Z fd0ab2669226a74d38406e095d929629
|
Z 96c17883fc9fb8d90fa5ada1b6415a79
|
||||||
|
@@ -1 +1 @@
|
|||||||
9bf0524df7ca2e7fcd92b2878a8457264b3c7f6e
|
f783e8e6b10de44029c7c5f57e4648a4a677ca1b
|
52
src/where.c
52
src/where.c
@@ -4168,16 +4168,16 @@ static void explainAppendTerm(
|
|||||||
** It is the responsibility of the caller to free the buffer when it is
|
** It is the responsibility of the caller to free the buffer when it is
|
||||||
** no longer required.
|
** no longer required.
|
||||||
*/
|
*/
|
||||||
static char *explainIndexRange(sqlite3 *db, WhereLevel *pLevel, Table *pTab){
|
static char *explainIndexRange(sqlite3 *db, WhereLoop *pLoop, Table *pTab){
|
||||||
WherePlan *pPlan = &pLevel->plan;
|
Index *pIndex = pLoop->u.btree.pIndex;
|
||||||
Index *pIndex = pPlan->u.pIdx;
|
int nEq = pLoop->u.btree.nEq;
|
||||||
int nEq = pPlan->nEq;
|
|
||||||
int i, j;
|
int i, j;
|
||||||
Column *aCol = pTab->aCol;
|
Column *aCol = pTab->aCol;
|
||||||
int *aiColumn = pIndex->aiColumn;
|
int *aiColumn = pIndex->aiColumn;
|
||||||
StrAccum txt;
|
StrAccum txt;
|
||||||
|
|
||||||
if( nEq==0 && (pPlan->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ){
|
if( pIndex==0 ) return 0;
|
||||||
|
if( nEq==0 && (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
sqlite3StrAccumInit(&txt, 0, 0, SQLITE_MAX_LENGTH);
|
sqlite3StrAccumInit(&txt, 0, 0, SQLITE_MAX_LENGTH);
|
||||||
@@ -4188,11 +4188,11 @@ static char *explainIndexRange(sqlite3 *db, WhereLevel *pLevel, Table *pTab){
|
|||||||
}
|
}
|
||||||
|
|
||||||
j = i;
|
j = i;
|
||||||
if( pPlan->wsFlags&WHERE_BTM_LIMIT ){
|
if( pLoop->wsFlags&WHERE_BTM_LIMIT ){
|
||||||
char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName;
|
char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName;
|
||||||
explainAppendTerm(&txt, i++, z, ">");
|
explainAppendTerm(&txt, i++, z, ">");
|
||||||
}
|
}
|
||||||
if( pPlan->wsFlags&WHERE_TOP_LIMIT ){
|
if( pLoop->wsFlags&WHERE_TOP_LIMIT ){
|
||||||
char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName;
|
char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName;
|
||||||
explainAppendTerm(&txt, i, z, "<");
|
explainAppendTerm(&txt, i, z, "<");
|
||||||
}
|
}
|
||||||
@@ -4215,7 +4215,6 @@ static void explainOneScan(
|
|||||||
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
|
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
|
||||||
){
|
){
|
||||||
if( pParse->explain==2 ){
|
if( pParse->explain==2 ){
|
||||||
u32 flags = pLevel->plan.wsFlags;
|
|
||||||
struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
|
struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
|
||||||
Vdbe *v = pParse->pVdbe; /* VM being constructed */
|
Vdbe *v = pParse->pVdbe; /* VM being constructed */
|
||||||
sqlite3 *db = pParse->db; /* Database handle */
|
sqlite3 *db = pParse->db; /* Database handle */
|
||||||
@@ -4223,12 +4222,16 @@ static void explainOneScan(
|
|||||||
sqlite3_int64 nRow; /* Expected number of rows visited by scan */
|
sqlite3_int64 nRow; /* Expected number of rows visited by scan */
|
||||||
int iId = pParse->iSelectId; /* Select id (left-most output column) */
|
int iId = pParse->iSelectId; /* Select id (left-most output column) */
|
||||||
int isSearch; /* True for a SEARCH. False for SCAN. */
|
int isSearch; /* True for a SEARCH. False for SCAN. */
|
||||||
|
WhereLoop *pLoop; /* The controlling WhereLoop object */
|
||||||
|
u32 flags; /* Flags that describe this loop */
|
||||||
|
|
||||||
|
pLoop = pLevel->pWLoop;
|
||||||
|
flags = pLoop->wsFlags;
|
||||||
if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_ONETABLE_ONLY) ) return;
|
if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_ONETABLE_ONLY) ) return;
|
||||||
|
|
||||||
isSearch = (pLevel->plan.nEq>0)
|
isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
|
||||||
|| (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
|
|| ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
|
||||||
|| (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
|
|| (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
|
||||||
|
|
||||||
zMsg = sqlite3MPrintf(db, "%s", isSearch?"SEARCH":"SCAN");
|
zMsg = sqlite3MPrintf(db, "%s", isSearch?"SEARCH":"SCAN");
|
||||||
if( pItem->pSelect ){
|
if( pItem->pSelect ){
|
||||||
@@ -4240,20 +4243,22 @@ static void explainOneScan(
|
|||||||
if( pItem->zAlias ){
|
if( pItem->zAlias ){
|
||||||
zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias);
|
zMsg = sqlite3MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias);
|
||||||
}
|
}
|
||||||
if( (flags & WHERE_INDEXED)!=0 ){
|
if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0
|
||||||
char *zWhere = explainIndexRange(db, pLevel, pItem->pTab);
|
&& pLoop->u.btree.pIndex!=0
|
||||||
|
){
|
||||||
|
char *zWhere = explainIndexRange(db, pLoop, pItem->pTab);
|
||||||
zMsg = sqlite3MAppendf(db, zMsg, "%s USING %s%sINDEX%s%s%s", zMsg,
|
zMsg = sqlite3MAppendf(db, zMsg, "%s USING %s%sINDEX%s%s%s", zMsg,
|
||||||
((flags & WHERE_TEMP_INDEX)?"AUTOMATIC ":""),
|
((flags & WHERE_TEMP_INDEX)?"AUTOMATIC ":""),
|
||||||
((flags & WHERE_IDX_ONLY)?"COVERING ":""),
|
((flags & WHERE_IDX_ONLY)?"COVERING ":""),
|
||||||
((flags & WHERE_TEMP_INDEX)?"":" "),
|
((flags & WHERE_TEMP_INDEX)?"":" "),
|
||||||
((flags & WHERE_TEMP_INDEX)?"": pLevel->plan.u.pIdx->zName),
|
((flags & WHERE_TEMP_INDEX)?"": pLoop->u.btree.pIndex->zName),
|
||||||
zWhere
|
zWhere
|
||||||
);
|
);
|
||||||
sqlite3DbFree(db, zWhere);
|
sqlite3DbFree(db, zWhere);
|
||||||
}else if( flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
|
}else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_INDEXED)!=0 ){
|
||||||
zMsg = sqlite3MAppendf(db, zMsg, "%s USING INTEGER PRIMARY KEY", zMsg);
|
zMsg = sqlite3MAppendf(db, zMsg, "%s USING INTEGER PRIMARY KEY", zMsg);
|
||||||
|
|
||||||
if( flags&WHERE_ROWID_EQ ){
|
if( flags&WHERE_COLUMN_EQ ){
|
||||||
zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid=?)", zMsg);
|
zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid=?)", zMsg);
|
||||||
}else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){
|
}else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){
|
||||||
zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid>? AND rowid<?)", zMsg);
|
zMsg = sqlite3MAppendf(db, zMsg, "%s (rowid>? AND rowid<?)", zMsg);
|
||||||
@@ -4265,16 +4270,15 @@ static void explainOneScan(
|
|||||||
}
|
}
|
||||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||||
else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
|
else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
|
||||||
sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
|
|
||||||
zMsg = sqlite3MAppendf(db, zMsg, "%s VIRTUAL TABLE INDEX %d:%s", zMsg,
|
zMsg = sqlite3MAppendf(db, zMsg, "%s VIRTUAL TABLE INDEX %d:%s", zMsg,
|
||||||
pVtabIdx->idxNum, pVtabIdx->idxStr);
|
pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if( wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX) ){
|
if( wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX) ){
|
||||||
testcase( wctrlFlags & WHERE_ORDERBY_MIN );
|
testcase( wctrlFlags & WHERE_ORDERBY_MIN );
|
||||||
nRow = 1;
|
nRow = 1;
|
||||||
}else{
|
}else{
|
||||||
nRow = (sqlite3_int64)pLevel->plan.nRow;
|
nRow = (sqlite3_int64)pLoop->nOut;
|
||||||
}
|
}
|
||||||
zMsg = sqlite3MAppendf(db, zMsg, "%s (~%lld rows)", zMsg, nRow);
|
zMsg = sqlite3MAppendf(db, zMsg, "%s (~%lld rows)", zMsg, nRow);
|
||||||
sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg, P4_DYNAMIC);
|
sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg, P4_DYNAMIC);
|
||||||
@@ -5263,7 +5267,8 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
|
|||||||
memcpy(p->aTerm, pTemplate->aTerm, p->nTerm*sizeof(p->aTerm[0]));
|
memcpy(p->aTerm, pTemplate->aTerm, p->nTerm*sizeof(p->aTerm[0]));
|
||||||
}
|
}
|
||||||
if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
|
if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
|
||||||
if( p->u.btree.pIndex && p->u.btree.pIndex && p->u.btree.pIndex->tnum==0 ){
|
Index *pIndex = p->u.btree.pIndex;
|
||||||
|
if( pIndex && pIndex->tnum==0 ){
|
||||||
p->u.btree.pIndex = 0;
|
p->u.btree.pIndex = 0;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
@@ -5310,6 +5315,7 @@ static int whereLoopAddBtreeIndex(
|
|||||||
}else{
|
}else{
|
||||||
opMask = WO_EQ|WO_IN|WO_ISNULL|WO_GT|WO_GE|WO_LT|WO_LE;
|
opMask = WO_EQ|WO_IN|WO_ISNULL|WO_GT|WO_GE|WO_LT|WO_LE;
|
||||||
}
|
}
|
||||||
|
if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
|
||||||
|
|
||||||
if( pNew->u.btree.nEq < pProbe->nColumn ){
|
if( pNew->u.btree.nEq < pProbe->nColumn ){
|
||||||
iCol = pProbe->aiColumn[pNew->u.btree.nEq];
|
iCol = pProbe->aiColumn[pNew->u.btree.nEq];
|
||||||
@@ -5472,6 +5478,7 @@ static int whereLoopAddBtree(
|
|||||||
for(pTerm=pWC->a; rc==SQLITE_OK && pTerm<pWCEnd; pTerm++){
|
for(pTerm=pWC->a; rc==SQLITE_OK && pTerm<pWCEnd; pTerm++){
|
||||||
if( termCanDriveIndex(pTerm, pSrc, 0) ){
|
if( termCanDriveIndex(pTerm, pSrc, 0) ){
|
||||||
pNew->u.btree.nEq = 1;
|
pNew->u.btree.nEq = 1;
|
||||||
|
pNew->u.btree.pIndex = 0;
|
||||||
pNew->nTerm = 1;
|
pNew->nTerm = 1;
|
||||||
pNew->aTerm[0] = pTerm;
|
pNew->aTerm[0] = pTerm;
|
||||||
pNew->rSetup = 2*rLogSize*pSrc->pTab->nRowEst;
|
pNew->rSetup = 2*rLogSize*pSrc->pTab->nRowEst;
|
||||||
@@ -5515,7 +5522,7 @@ static int whereLoopAddBtree(
|
|||||||
pNew->wsFlags = (m==0) ? WHERE_IDX_ONLY : 0;
|
pNew->wsFlags = (m==0) ? WHERE_IDX_ONLY : 0;
|
||||||
|
|
||||||
/* Full scan via index */
|
/* Full scan via index */
|
||||||
if( m==0 || b ){
|
if( (m==0 || b) && pProbe->bUnordered==0 ){
|
||||||
pNew->iSortIdx = b ? iSortIdx : 0;
|
pNew->iSortIdx = b ? iSortIdx : 0;
|
||||||
pNew->nOut = rSize;
|
pNew->nOut = rSize;
|
||||||
pNew->rRun = (m==0) ? (rSize + rLogSize)*(1+b) : (rSize*rLogSize);
|
pNew->rRun = (m==0) ? (rSize + rLogSize)*(1+b) : (rSize*rLogSize);
|
||||||
@@ -5892,10 +5899,9 @@ static int wherePathSatisfiesOrderBy(
|
|||||||
if( pLoop->u.btree.nEq!=1 ) isUnique = 0;
|
if( pLoop->u.btree.nEq!=1 ) isUnique = 0;
|
||||||
pIndex = 0;
|
pIndex = 0;
|
||||||
nColumn = 1;
|
nColumn = 1;
|
||||||
}else if( pLoop->u.btree.pIndex==0 ){
|
}else if( (pIndex = pLoop->u.btree.pIndex)==0 || pIndex->bUnordered ){
|
||||||
return 0;
|
return 0;
|
||||||
}else{
|
}else{
|
||||||
pIndex = pLoop->u.btree.pIndex;
|
|
||||||
nColumn = pIndex->nColumn;
|
nColumn = pIndex->nColumn;
|
||||||
if( pIndex->onError==OE_None ){
|
if( pIndex->onError==OE_None ){
|
||||||
isUnique = 0;
|
isUnique = 0;
|
||||||
|
@@ -793,9 +793,28 @@ proc finalize_testing {} {
|
|||||||
set nTest [incr_ntest]
|
set nTest [incr_ntest]
|
||||||
set nErr [set_test_counter errors]
|
set nErr [set_test_counter errors]
|
||||||
|
|
||||||
puts "$nErr errors out of $nTest tests"
|
set nKnown 0
|
||||||
if {$nErr>0} {
|
if {[file readable known-problems.txt]} {
|
||||||
puts "Failures on these tests: [set_test_counter fail_list]"
|
set fd [open known-problems.txt]
|
||||||
|
set content [read $fd]
|
||||||
|
close $fd
|
||||||
|
foreach x $content {set known_error($x) 1}
|
||||||
|
foreach x [set_test_counter fail_list] {
|
||||||
|
if {[info exists known_error($x)]} {incr nKnown}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if {$nKnown>0} {
|
||||||
|
puts "[expr {$nErr-$nKnown}] new errors and $nKnown known errors\
|
||||||
|
out of $nTest tests"
|
||||||
|
} else {
|
||||||
|
puts "$nErr errors out of $nTest tests"
|
||||||
|
}
|
||||||
|
if {$nErr>$nKnown} {
|
||||||
|
puts -nonewline "Failures on these tests:"
|
||||||
|
foreach x [set_test_counter fail_list] {
|
||||||
|
if {![info exists known_error($x)]} {puts -nonewline " $x"}
|
||||||
|
}
|
||||||
|
puts ""
|
||||||
}
|
}
|
||||||
foreach warning [set_test_counter warn_list] {
|
foreach warning [set_test_counter warn_list] {
|
||||||
puts "Warning: $warning"
|
puts "Warning: $warning"
|
||||||
|
Reference in New Issue
Block a user