Futher simplifications to the NGQP. Fix some test cases to use

EXPLAIN QUERY PLAN rather than the (now obsolete) sqlite_query_plan
global variable.

FossilOrigin-Name: ae985db4fa08b5efbef5a834e852f0b05101264b
This commit is contained in:
drh 2013-05-30 19:29:19 +00:00
parent 70bdcc738e
commit 6fa978dade
5 changed files with 70 additions and 148 deletions

View File

@ -1,5 +1,5 @@
C The\sexpected\sresult\sin\sa\stest\scase\scan\sbe\sof\sthe\sform\s"*glob*"\sor\s"~*glob*"\sto\s\nmatch\sor\snot\smatch\sthe\sGLOB\spattern.\s\sThis\sis\suseful\sfor\smatching\nEXPLAIN\sQUERY\sPLAN\soutput\sthat\scontains\sregular\sexpression\ssyntax\scharacters\nlike\s"?",\s"(",\sand\s")".
D 2013-05-30T19:28:34.431
C Futher\ssimplifications\sto\sthe\sNGQP.\s\sFix\ssome\stest\scases\sto\suse\nEXPLAIN\sQUERY\sPLAN\srather\sthan\sthe\s(now\sobsolete)\ssqlite_query_plan\nglobal\svariable.
D 2013-05-30T19:29:19.963
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -225,7 +225,7 @@ F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c bedc37ec1a6bb9399944024d63f4c769971955a9
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c 2ecec9937e69bc17560ad886da35195daa7261b8
F src/test1.c 6d2a340eea1d866bf7059894491652a69a7ee802
F src/test1.c 5f9837aee1a0708ab2dbf67ce0b9c18e658cd36b
F src/test2.c 7355101c085304b90024f2261e056cdff13c6c35
F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c
F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df
@ -289,7 +289,7 @@ F src/vtab.c b05e5f1f4902461ba9f5fc49bb7eb7c3a0741a83
F src/wal.c 436bfceb141b9423c45119e68e444358ee0ed35d
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73
F src/where.c 296baae1cbfd99527d8c87f9773a6c98116f6b8a
F src/where.c 3e9b7b3323f78ec3056c5e3aa3443661bc590054
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
@ -1028,7 +1028,7 @@ F test/walro.test a31deb621033442a76c3a61e44929250d06f81b1
F test/walshared.test 6dda2293880c300baf5d791c307f653094585761
F test/walslow.test e7be6d9888f83aa5d3d3c7c08aa9b5c28b93609a
F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e
F test/where.test 15ac8611c9439a2c5f4a6ac10cfe4c1ec9854c24
F test/where.test 054a6b6f7933c5a5f50d0bcd650b5eccb450cc81
F test/where2.test 399b3178289925a0aa976b3d60ef139740540ecd
F test/where3.test 667e75642102c97a00bf9b23d3cb267db321d006
F test/where4.test e9b9e2f2f98f00379e6031db6a6fca29bae782a2
@ -1093,7 +1093,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
P 001539df4b74dc1cbceb010a91407003ab4d8735
R ae73b581603fe5cb9a5fdce5dbec1c53
P a3b4e261bd7e278f150872cce7b020af5ad8d2ed
R b028bf2657ab598aee5d4698a0488fdc
U drh
Z 68529a7f58c35b9a5dca06d2c9973260
Z 3432943259d0f5aa9c669ba0e80caf85

View File

@ -1 +1 @@
a3b4e261bd7e278f150872cce7b020af5ad8d2ed
ae985db4fa08b5efbef5a834e852f0b05101264b

View File

@ -6302,8 +6302,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
extern int sqlite3WalTrace;
#endif
#ifdef SQLITE_TEST
extern char sqlite3_query_plan[];
static char *query_plan = sqlite3_query_plan;
#ifdef SQLITE_ENABLE_FTS3
extern int sqlite3_fts3_enable_parentheses;
#endif
@ -6357,8 +6355,11 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
(char*)&sqlite3_os_type, TCL_LINK_INT);
#endif
#ifdef SQLITE_TEST
Tcl_LinkVar(interp, "sqlite_query_plan",
(char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
{
static const char *query_plan = "*** OBSOLETE VARIABLE ***";
Tcl_LinkVar(interp, "sqlite_query_plan",
(char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
}
#endif
#ifdef SQLITE_DEBUG
Tcl_LinkVar(interp, "sqlite_where_trace",

View File

@ -326,33 +326,22 @@ struct WhereLoopBuilder {
** WhereLevel.wsFlags. These flags determine which search
** strategies are appropriate.
*/
#define WHERE_ROWID_EQ 0x00000001 /* rowid=EXPR or rowid IN (...) */
#define WHERE_ROWID_RANGE 0x00000002 /* rowid<EXPR and/or rowid>EXPR */
#define WHERE_NULL_OK 0x00000004 /* Ok to use WO_ISNULL */
#define WHERE_IPK 0x00000008 /* x is the INTEGER PRIMARY KEY */
#define WHERE_COLUMN_EQ 0x00000010 /* x=EXPR or x IN (...) or x IS NULL */
#define WHERE_COLUMN_RANGE 0x00000020 /* x<EXPR and/or x>EXPR */
#define WHERE_COLUMN_IN 0x00000040 /* x IN (...) */
#define WHERE_COLUMN_NULL 0x00000080 /* x IS NULL */
#define WHERE_INDEXED 0x000000f0 /* Anything that uses an index */
#define WHERE_NOT_FULLSCAN 0x000200f3 /* Does not do a full table scan */
#define WHERE_IN_ABLE 0x000100f1 /* Able to support an IN operator */
#define WHERE_TOP_LIMIT 0x00000100 /* x<EXPR or x<=EXPR constraint */
#define WHERE_BTM_LIMIT 0x00000200 /* x>EXPR or x>=EXPR constraint */
#define WHERE_BOTH_LIMIT 0x00000300 /* Both x>EXPR and x<EXPR */
#define WHERE_IDX_ONLY 0x00000400 /* Use index only - omit table */
#define WHERE_ORDERED 0x00000800 /* Output will appear in correct order */
#define WHERE_REVERSE 0x00001000 /* Scan in reverse order */
#define WHERE_UNIQUE 0x00002000 /* Selects no more than one row */
#define WHERE_ALL_UNIQUE 0x00004000 /* This and all prior have one row */
#define WHERE_OB_UNIQUE 0x00008000 /* Values in ORDER BY columns are
** different for every output row */
#define WHERE_VIRTUALTABLE 0x00010000 /* Use virtual-table processing */
#define WHERE_MULTI_OR 0x00020000 /* OR using multiple indices */
#define WHERE_TEMP_INDEX 0x00040000 /* Uses an ephemeral index */
#define WHERE_DISTINCT 0x00080000 /* Correct order for DISTINCT */
#define WHERE_COVER_SCAN 0x00100000 /* Full scan of a covering index */
#define WHERE_SINGLE_ROW 0x00200000 /* No more than one row guaranteed */
#define WHERE_COLUMN_EQ 0x00000001 /* x=EXPR or x IN (...) or x IS NULL */
#define WHERE_COLUMN_RANGE 0x00000002 /* x<EXPR and/or x>EXPR */
#define WHERE_COLUMN_IN 0x00000004 /* x IN (...) */
#define WHERE_COLUMN_NULL 0x00000008 /* x IS NULL */
#define WHERE_TOP_LIMIT 0x00000010 /* x<EXPR or x<=EXPR constraint */
#define WHERE_BTM_LIMIT 0x00000020 /* x>EXPR or x>=EXPR constraint */
#define WHERE_BOTH_LIMIT 0x00000030 /* Both x>EXPR and x<EXPR */
#define WHERE_IDX_ONLY 0x00000040 /* Use index only - omit table */
#define WHERE_IPK 0x00000100 /* x is the INTEGER PRIMARY KEY */
#define WHERE_INDEXED 0x00000200 /* WhereLoop.u.btree.pIndex is valid */
#define WHERE_VIRTUALTABLE 0x00000400 /* WhereLoop.u.vtab is valid */
#define WHERE_IN_ABLE 0x00000800 /* Able to support an IN operator */
#define WHERE_UNIQUE 0x00001000 /* Selects no more than one row */
#define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */
#define WHERE_TEMP_INDEX 0x00004000 /* Uses an ephemeral index */
#define WHERE_COVER_SCAN 0x00008000 /* Full scan of a covering index */
/*
** This module contains many separate subroutines that work together to
@ -2671,7 +2660,8 @@ static int codeEqualityTerm(
}
iTab = pX->iTable;
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
assert( pLoop->wsFlags & WHERE_IN_ABLE );
assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
pLoop->wsFlags |= WHERE_IN_ABLE;
if( pLevel->u.in.nIn==0 ){
pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
}
@ -3193,7 +3183,8 @@ static Bitmask codeOneLoopStart(
sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg);
sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
}
}else if( pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ|WHERE_IDX_ONLY) ){
}else if( pLoop->wsFlags & (WHERE_COLUMN_RANGE | WHERE_COLUMN_NULL |
WHERE_COLUMN_EQ | WHERE_IDX_ONLY) ){
/* Case 4: A scan using an index.
**
** The WHERE clause may contain zero or more equality
@ -3746,18 +3737,6 @@ static Bitmask codeOneLoopStart(
return newNotReady;
}
#if defined(SQLITE_TEST)
/*
** The following variable holds a text description of query plan generated
** by the most recent call to sqlite3WhereBegin(). Each call to WhereBegin
** overwrites the previous. This information is used for testing and
** analysis only.
*/
char sqlite3_query_plan[BMS*2*40]; /* Text of the join */
static int nQPlan = 0; /* Next free slow in _query_plan[] */
#endif /* SQLITE_TEST */
#ifdef WHERETRACE_ENABLED
/*
** Print a WhereLoop object for debugging purposes
@ -3793,7 +3772,7 @@ static void whereLoopPrint(WhereLoop *p, SrcList *pTabList){
sqlite3DebugPrintf(" %-15s", z);
sqlite3_free(z);
}
sqlite3DebugPrintf(" fg %08x N %d", p->wsFlags, p->nTerm);
sqlite3DebugPrintf(" fg %05x N %d", p->wsFlags, p->nTerm);
sqlite3DebugPrintf(" cost %.2g,%.2g,%.2g\n",
p->prereq, p->rSetup, p->rRun, p->nOut);
}
@ -3810,6 +3789,10 @@ static void whereLoopClear(sqlite3 *db, WhereLoop *p){
if( p->u.vtab.needFree ) sqlite3_free(p->u.vtab.idxStr);
p->u.vtab.needFree = 0;
p->u.vtab.idxStr = 0;
}else if( (p->wsFlags & WHERE_TEMP_INDEX)!=0 && p->u.btree.pIndex!=0 ){
sqlite3DbFree(db, p->u.btree.pIndex->zColAff);
sqlite3DbFree(db, p->u.btree.pIndex);
p->u.btree.pIndex = 0;
}
}
@ -3826,16 +3809,6 @@ static void whereLoopDelete(sqlite3 *db, WhereLoop *p){
*/
static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
if( ALWAYS(pWInfo) ){
int i;
for(i=0; i<pWInfo->nLevel; i++){
if( pWInfo->a[i].pWLoop->wsFlags & WHERE_TEMP_INDEX ){
Index *pIdx = pWInfo->a[i].pWLoop->u.btree.pIndex;
if( pIdx ){
sqlite3DbFree(db, pIdx->zColAff);
sqlite3DbFree(db, pIdx);
}
}
}
whereClauseClear(pWInfo->pWC);
while( pWInfo->pLoops ){
WhereLoop *p = pWInfo->pLoops;
@ -4026,10 +3999,14 @@ static int whereLoopAddBtreeIndex(
}
pNew->u.btree.nEq++;
pNew->nOut = (double)iRowEst * nInMul * nIn;
}else if( pTerm->eOperator & (WO_EQ|WO_ISNULL) ){
}else if( pTerm->eOperator & (WO_EQ) ){
pNew->wsFlags |= WHERE_COLUMN_EQ;
pNew->u.btree.nEq++;
pNew->nOut = (double)iRowEst * nInMul;
}else if( pTerm->eOperator & (WO_ISNULL) ){
pNew->wsFlags |= WHERE_COLUMN_NULL;
pNew->u.btree.nEq++;
pNew->nOut = (double)iRowEst * nInMul;
}else if( pTerm->eOperator & (WO_GT|WO_GE) ){
pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
pNew->nOut = savedLoop.nOut/3;
@ -4197,7 +4174,7 @@ static int whereLoopAddBtree(
m &= ~(((Bitmask)1)<<x);
}
}
pNew->wsFlags = (m==0) ? WHERE_IDX_ONLY : 0;
pNew->wsFlags = (m==0) ? (WHERE_IDX_ONLY|WHERE_INDEXED) : WHERE_INDEXED;
/* Full scan via index */
if( (m==0 || b) && pProbe->bUnordered==0 ){
@ -5246,62 +5223,7 @@ WhereInfo *sqlite3WhereBegin(
pWInfo->iContinue = pLevel->addrCont;
}
#if defined(SQLITE_TEST) && 0 /* For testing and debugging use only */
/* Record in the query plan information about the current table
** and the index used to access it (if any). If the table itself
** is not used, its name is just '{}'. If no index is used
** the index is listed as "{}". If the primary key is used the
** index name is '*'.
*/
for(ii=0; ii<nTabList; ii++){
char *z;
int n;
int w;
struct SrcList_item *pTabItem;
pLevel = &pWInfo->a[ii];
w = pLevel->plan.wsFlags;
pTabItem = &pTabList->a[pLevel->iFrom];
z = pTabItem->zAlias;
if( z==0 ) z = pTabItem->pTab->zName;
n = sqlite3Strlen30(z);
if( n+nQPlan < sizeof(sqlite3_query_plan)-10 ){
if( (w & WHERE_IDX_ONLY)!=0 && (w & WHERE_COVER_SCAN)==0 ){
memcpy(&sqlite3_query_plan[nQPlan], "{}", 2);
nQPlan += 2;
}else{
memcpy(&sqlite3_query_plan[nQPlan], z, n);
nQPlan += n;
}
sqlite3_query_plan[nQPlan++] = ' ';
}
testcase( w & WHERE_ROWID_EQ );
testcase( w & WHERE_ROWID_RANGE );
if( w & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
memcpy(&sqlite3_query_plan[nQPlan], "* ", 2);
nQPlan += 2;
}else if( (w & WHERE_INDEXED)!=0 && (w & WHERE_COVER_SCAN)==0 ){
n = sqlite3Strlen30(pLevel->plan.u.pIdx->zName);
if( n+nQPlan < sizeof(sqlite3_query_plan)-2 ){
memcpy(&sqlite3_query_plan[nQPlan], pLevel->plan.u.pIdx->zName, n);
nQPlan += n;
sqlite3_query_plan[nQPlan++] = ' ';
}
}else{
memcpy(&sqlite3_query_plan[nQPlan], "{} ", 3);
nQPlan += 3;
}
}
while( nQPlan>0 && sqlite3_query_plan[nQPlan-1]==' ' ){
sqlite3_query_plan[--nQPlan] = 0;
}
sqlite3_query_plan[nQPlan] = 0;
nQPlan = 0;
#endif /* SQLITE_TEST // Testing and debugging use only */
/* Record the continuation address in the WhereInfo structure. Then
** clean up and return.
*/
/* Done. */
return pWInfo;
/* Jump here if malloc fails */

View File

@ -65,9 +65,9 @@ proc count sql {
do_test where-1.1.1 {
count {SELECT x, y, w FROM t1 WHERE w=10}
} {3 121 10 3}
do_test where-1.1.2 {
set sqlite_query_plan
} {t1 i1w}
do_eqp_test where-1.1.2 {
SELECT x, y, w FROM t1 WHERE w=10
} {*SEARCH TABLE t1 USING INDEX i1w (w=?) *}
do_test where-1.1.3 {
db status step
} {0}
@ -77,15 +77,15 @@ do_test where-1.1.4 {
do_test where-1.1.5 {
db status step
} {99}
do_test where-1.1.6 {
set sqlite_query_plan
} {t1 {}}
do_eqp_test where-1.1.6 {
SELECT x, y, w FROM t1 WHERE +w=10
} {*SCAN TABLE t1 *}
do_test where-1.1.7 {
count {SELECT x, y, w AS abc FROM t1 WHERE abc=10}
} {3 121 10 3}
do_test where-1.1.8 {
set sqlite_query_plan
} {t1 i1w}
do_eqp_test where-1.1.8 {
SELECT x, y, w AS abc FROM t1 WHERE abc=10
} {*SEARCH TABLE t1 USING INDEX i1w (w=?) *}
do_test where-1.1.9 {
db status step
} {0}
@ -104,21 +104,21 @@ do_test where-1.3.2 {
do_test where-1.4.1 {
count {SELECT w, x, y FROM t1 WHERE 11=w AND x>2}
} {11 3 144 3}
do_test where-1.4.2 {
set sqlite_query_plan
} {t1 i1w}
do_eqp_test where-1.4.2 {
SELECT w, x, y FROM t1 WHERE 11=w AND x>2
} {*SEARCH TABLE t1 USING INDEX i1w (w=?) *}
do_test where-1.4.3 {
count {SELECT w AS a, x AS b, y FROM t1 WHERE 11=a AND b>2}
} {11 3 144 3}
do_test where-1.4.4 {
set sqlite_query_plan
} {t1 i1w}
do_eqp_test where-1.4.4 {
SELECT w AS a, x AS b, y FROM t1 WHERE 11=a AND b>2
} {*SEARCH TABLE t1 USING INDEX i1w (w=?) *}
do_test where-1.5 {
count {SELECT x, y FROM t1 WHERE y<200 AND w=11 AND x>2}
} {3 144 3}
do_test where-1.5.2 {
set sqlite_query_plan
} {t1 i1w}
do_eqp_test where-1.5.2 {
SELECT x, y FROM t1 WHERE y<200 AND w=11 AND x>2
} {*SEARCH TABLE t1 USING INDEX i1w (w=?) *}
do_test where-1.6 {
count {SELECT x, y FROM t1 WHERE y<200 AND x>2 AND w=11}
} {3 144 3}
@ -128,13 +128,12 @@ do_test where-1.7 {
do_test where-1.8 {
count {SELECT x, y FROM t1 WHERE w>10 AND y=144 AND x=3}
} {3 144 3}
do_test where-1.8.2 {
set sqlite_query_plan
} {t1 i1xy}
do_test where-1.8.3 {
count {SELECT x, y FROM t1 WHERE y=144 AND x=3}
set sqlite_query_plan
} {{} i1xy}
do_eqp_test where-1.8.2 {
SELECT x, y FROM t1 WHERE w>10 AND y=144 AND x=3
} {*SEARCH TABLE t1 USING INDEX i1xy (x=? AND y=?) *}
do_eqp_test where-1.8.3 {
SELECT x, y FROM t1 WHERE y=144 AND x=3
} {*SEARCH TABLE t1 USING COVERING INDEX i1xy (x=? AND y=?) *}
do_test where-1.9 {
count {SELECT x, y FROM t1 WHERE y=144 AND w>10 AND x=3}
} {3 144 3}