Index: src/shell.c
==================================================================
--- src/shell.c
+++ src/shell.c
@@ -1192,36 +1192,44 @@
static void display_scanstats(
sqlite3 *db, /* Database to query */
ShellState *pArg /* Pointer to ShellState */
){
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
- int i;
- fprintf(pArg->out, "-------- scanstats --------\n");
- for(i=0; 1; i++){
- sqlite3_stmt *p = pArg->pStmt;
- sqlite3_int64 nEst, nLoop, nVisit;
- const char *zExplain;
- if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){
- break;
- }
- sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
- sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&nEst);
- sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
-
- fprintf(pArg->out, "Loop %d: \"%s\"\n", i, zExplain);
- fprintf(pArg->out, " nLoop=%-8lld nVisit=%-8lld nEst=%-8lld\n",
- nLoop, nVisit, nEst
- );
- }
-#else
- fprintf(pArg->out, "-------- scanstats --------\n");
- fprintf(pArg->out,
- "sqlite3_stmt_scanstatus() unavailable - "
- "rebuild with SQLITE_ENABLE_STMT_SCANSTATUS\n"
- );
-#endif
- fprintf(pArg->out, "---------------------------\n");
+ int i, k, n, mx;
+ fprintf(pArg->out, "-------- scanstats --------\n");
+ mx = 0;
+ for(k=0; k<=mx; k++){
+ double rEstLoop = 1.0;
+ for(i=n=0; 1; i++){
+ sqlite3_stmt *p = pArg->pStmt;
+ sqlite3_int64 nLoop, nVisit;
+ double rEst;
+ int iSid;
+ const char *zExplain;
+ if( sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop) ){
+ break;
+ }
+ sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_SELECTID, (void*)&iSid);
+ if( iSid>mx ) mx = iSid;
+ if( iSid!=k ) continue;
+ if( n==0 ){
+ rEstLoop = (double)nLoop;
+ if( k>0 ) fprintf(pArg->out, "-------- subquery %d -------\n", k);
+ }
+ n++;
+ sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
+ sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EST, (void*)&rEst);
+ sqlite3_stmt_scanstatus(p, i, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
+ fprintf(pArg->out, "Loop %2d: %s\n", n, zExplain);
+ rEstLoop *= rEst;
+ fprintf(pArg->out, " nLoop=%-8lld nRow=%-8lld estRow=%-8lld estRow/Loop=%-8g\n",
+ nLoop, nVisit, (sqlite3_int64)rEstLoop, rEst
+ );
+ }
+ }
+ fprintf(pArg->out, "---------------------------\n");
+#endif
}
/*
** Parameter azArray points to a zero-terminated array of strings. zStr
** points to a single nul-terminated string. Return non-zero if zStr
@@ -1673,10 +1681,11 @@
".prompt MAIN CONTINUE Replace the standard prompts\n"
".quit Exit this program\n"
".read FILENAME Execute SQL in FILENAME\n"
".restore ?DB? FILE Restore content of DB (default \"main\") from FILE\n"
".save FILE Write in-memory database into FILE\n"
+ ".scanstats on|off Turn sqlite3_stmt_scanstatus() metrics on or off\n"
".schema ?TABLE? Show the CREATE statements\n"
" If TABLE specified, only show tables matching\n"
" LIKE pattern TABLE.\n"
".separator STRING ?NL? Change separator used by output mode and .import\n"
" NL is the end-of-line mark for CSV\n"
@@ -3058,10 +3067,13 @@
if( c=='s' && strncmp(azArg[0], "scanstats", n)==0 ){
if( nArg==2 ){
p->scanstatsOn = booleanValue(azArg[1]);
+#ifndef SQLITE_ENABLE_STMT_SCANSTATUS
+ fprintf(stderr, "Warning: .scanstats not available in this build.\n");
+#endif
}else{
fprintf(stderr, "Usage: .scanstats on|off\n");
rc = 1;
}
}else
Index: src/sqlite.h.in
==================================================================
--- src/sqlite.h.in
+++ src/sqlite.h.in
@@ -7438,17 +7438,19 @@
**
^The [sqlite3_int64] variable pointed to by the T parameter will be set to the
** total number of times that the X-th loop has run.
**
** [[SQLITE_SCANSTAT_NVISIT]] SQLITE_SCANSTAT_NVISIT
** ^The [sqlite3_int64] variable pointed to by the T parameter will be set to the
-** total number of rows visited by the X-th loop.
+** total number of rows examined by all iterations of the X-th loop.
**
** [[SQLITE_SCANSTAT_EST]] SQLITE_SCANSTAT_EST
-** ^The [sqlite3_int64] variable pointed to by the T parameter will be set to the
-** query planner's estimate for the number of rows visited for each
-** iteration of the X-th loop. If the query planner's estimate was accurate,
-** then this value should be approximately NVISIT/NLOOP.
+** ^The "double" variable pointed to by the T parameter will be set to the
+** query planner's estimate for the average number of rows output from each
+** iteration of the X-th loop. If the query planner's estimates was accurate,
+** then this value will approximate the quotient NVISIT/NLOOP and the
+** product of this value for all prior loops with the same SELECTID will
+** be the NLOOP value for the current loop.
**
** [[SQLITE_SCANSTAT_NAME]] SQLITE_SCANSTAT_NAME
** ^The "const char *" variable pointed to by the T parameter will be set to
** a zero-terminated UTF-8 string containing the name of the index or table used
** for the X-th loop.
@@ -7455,17 +7457,25 @@
**
** [[SQLITE_SCANSTAT_EXPLAIN]] SQLITE_SCANSTAT_EXPLAIN
** ^The "const char *" variable pointed to by the T parameter will be set to
** a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN] description
** for the X-th loop.
+**
+** [[SQLITE_SCANSTAT_SELECTID]] SQLITE_SCANSTAT_SELECT
+** ^The "int" variable pointed to by the T parameter will be set to the
+** "select-id" for the X-th loop. The select-id identifies which query or
+** subquery the loop is part of. The main query has a select-id of zero.
+** The select-id is the same value as is output in the first column
+** of an [EXPLAIN QUERY PLAN] query.
**
*/
#define SQLITE_SCANSTAT_NLOOP 0
#define SQLITE_SCANSTAT_NVISIT 1
#define SQLITE_SCANSTAT_EST 2
#define SQLITE_SCANSTAT_NAME 3
#define SQLITE_SCANSTAT_EXPLAIN 4
+#define SQLITE_SCANSTAT_SELECTID 5
/*
** CAPI3REF: Prepared Statement Scan Status
**
** Return status data for a single loop within query pStmt.
Index: src/test1.c
==================================================================
--- src/test1.c
+++ src/test1.c
@@ -2316,11 +2316,11 @@
const char *zName;
const char *zExplain;
sqlite3_int64 nLoop;
sqlite3_int64 nVisit;
- sqlite3_int64 nEst;
+ double rEst;
int res;
if( objc!=3 ){
Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX");
return TCL_ERROR;
@@ -2334,13 +2334,13 @@
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nLoop", -1));
Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nLoop));
sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nVisit", -1));
Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nVisit));
- sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EST, (void*)&nEst);
+ sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EST, (void*)&rEst);
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nEst", -1));
- Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nEst));
+ Tcl_ListObjAppendElement(0, pRet, Tcl_NewDoubleObj(rEst));
sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NAME, (void*)&zName);
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zName", -1));
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zName, -1));
sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zExplain", -1));
Index: src/vdbe.h
==================================================================
--- src/vdbe.h
+++ src/vdbe.h
@@ -281,11 +281,11 @@
# define VdbeCoverageNeverTaken(v)
# define VDBE_OFFSET_LINENO(x) 0
#endif
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
-void sqlite3VdbeScanStatus(Vdbe*, int, int, int, i64, const char*);
+void sqlite3VdbeScanStatus(Vdbe*, int, int, int, LogEst, const char*);
#else
# define sqlite3VdbeScanStatus(a,b,c,d,e)
#endif
#endif
Index: src/vdbeInt.h
==================================================================
--- src/vdbeInt.h
+++ src/vdbeInt.h
@@ -300,11 +300,12 @@
typedef struct ScanStatus ScanStatus;
struct ScanStatus {
int addrExplain; /* OP_Explain for loop */
int addrLoop; /* Address of "loops" counter */
int addrVisit; /* Address of "rows visited" counter */
- i64 nEst; /* Estimated rows per loop */
+ int iSelectID; /* The "Select-ID" for this loop */
+ LogEst nEst; /* Estimated output rows per loop */
char *zName; /* Name of table or index */
};
/*
** An instance of the virtual machine. This structure contains the complete
Index: src/vdbeapi.c
==================================================================
--- src/vdbeapi.c
+++ src/vdbeapi.c
@@ -1498,11 +1498,17 @@
case SQLITE_SCANSTAT_NVISIT: {
*(sqlite3_int64*)pOut = p->anExec[pScan->addrVisit];
break;
}
case SQLITE_SCANSTAT_EST: {
- *(sqlite3_int64*)pOut = pScan->nEst;
+ double r = 1.0;
+ LogEst x = pScan->nEst;
+ while( x<100 ){
+ x += 10;
+ r *= 0.5;
+ }
+ *(double*)pOut = r*sqlite3LogEstToInt(x);
break;
}
case SQLITE_SCANSTAT_NAME: {
*(const char**)pOut = pScan->zName;
break;
@@ -1512,10 +1518,18 @@
*(const char**)pOut = p->aOp[ pScan->addrExplain ].p4.z;
}else{
*(const char**)pOut = 0;
}
break;
+ }
+ case SQLITE_SCANSTAT_SELECTID: {
+ if( pScan->addrExplain ){
+ *(int*)pOut = p->aOp[ pScan->addrExplain ].p1;
+ }else{
+ *(int*)pOut = -1;
+ }
+ break;
}
default: {
return 1;
}
}
Index: src/vdbeaux.c
==================================================================
--- src/vdbeaux.c
+++ src/vdbeaux.c
@@ -604,11 +604,11 @@
void sqlite3VdbeScanStatus(
Vdbe *p, /* VM to add scanstatus() to */
int addrExplain, /* Address of OP_Explain (or 0) */
int addrLoop, /* Address of loop counter */
int addrVisit, /* Address of rows visited counter */
- i64 nEst, /* Estimated number of rows */
+ LogEst nEst, /* Estimated number of output rows */
const char *zName /* Name of table or index being scanned */
){
int nByte = (p->nScan+1) * sizeof(ScanStatus);
ScanStatus *aNew;
aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte);
Index: src/where.c
==================================================================
--- src/where.c
+++ src/where.c
@@ -2944,22 +2944,18 @@
SrcList *pSrclist, /* FROM clause pLvl reads data from */
WhereLevel *pLvl, /* Level to add scanstatus() entry for */
int addrExplain /* Address of OP_Explain (or 0) */
){
const char *zObj = 0;
- i64 nEst = 1;
WhereLoop *pLoop = pLvl->pWLoop;
if( (pLoop->wsFlags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){
zObj = pLoop->u.btree.pIndex->zName;
}else{
zObj = pSrclist->a[pLvl->iFrom].zName;
}
- if( pLoop->nOut>=10 ){
- nEst = sqlite3LogEstToInt(pLoop->nOut);
- }
sqlite3VdbeScanStatus(
- v, addrExplain, pLvl->addrBody, pLvl->addrVisit, nEst, zObj
+ v, addrExplain, pLvl->addrBody, pLvl->addrVisit, pLoop->nOut, zObj
);
}
#else
# define addScanStatus(a, b, c, d) ((void)d)
#endif
Index: test/scanstatus.test
==================================================================
--- test/scanstatus.test
+++ test/scanstatus.test
@@ -43,51 +43,51 @@
uplevel [list do_test $tn [list set {} $ret] [list {*}$res]]
}
do_execsql_test 1.1 { SELECT count(*) FROM t1, t2; } 6
do_scanstatus_test 1.2 {
- nLoop 1 nVisit 2 nEst 1048576 zName t1 zExplain {SCAN TABLE t1}
- nLoop 2 nVisit 6 nEst 1048576 zName t2 zExplain {SCAN TABLE t2}
+ nLoop 1 nVisit 2 nEst 1048576.0 zName t1 zExplain {SCAN TABLE t1}
+ nLoop 2 nVisit 6 nEst 1048576.0 zName t2 zExplain {SCAN TABLE t2}
}
do_execsql_test 1.3 {
ANALYZE;
SELECT count(*) FROM t1, t2;
} 6
do_scanstatus_test 1.4 {
- nLoop 1 nVisit 2 nEst 2 zName t1 zExplain {SCAN TABLE t1}
- nLoop 2 nVisit 6 nEst 3 zName t2 zExplain {SCAN TABLE t2}
+ nLoop 1 nVisit 2 nEst 2.0 zName t1 zExplain {SCAN TABLE t1}
+ nLoop 2 nVisit 6 nEst 3.0 zName t2 zExplain {SCAN TABLE t2}
}
do_execsql_test 1.5 { ANALYZE }
do_execsql_test 1.6 {
SELECT count(*) FROM t1, t2 WHERE t2.rowid>1;
} 4
do_scanstatus_test 1.7 {
- nLoop 1 nVisit 2 nEst 2 zName t2 zExplain
+ nLoop 1 nVisit 2 nEst 2.0 zName t2 zExplain
{SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid>?)}
- nLoop 2 nVisit 4 nEst 2 zName t1 zExplain {SCAN TABLE t1}
+ nLoop 2 nVisit 4 nEst 2.0 zName t1 zExplain {SCAN TABLE t1}
}
do_execsql_test 1.8 {
SELECT count(*) FROM t1, t2 WHERE t2.rowid>1;
} 4
do_scanstatus_test 1.9 {
- nLoop 2 nVisit 4 nEst 2 zName t2 zExplain
+ nLoop 2 nVisit 4 nEst 2.0 zName t2 zExplain
{SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid>?)}
- nLoop 4 nVisit 8 nEst 2 zName t1 zExplain {SCAN TABLE t1}
+ nLoop 4 nVisit 8 nEst 2.0 zName t1 zExplain {SCAN TABLE t1}
}
do_test 1.9 {
sqlite3_stmt_scanstatus_reset [db_last_stmt_ptr db]
} {}
do_scanstatus_test 1.10 {
- nLoop 0 nVisit 0 nEst 2 zName t2 zExplain
+ nLoop 0 nVisit 0 nEst 2.0 zName t2 zExplain
{SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid>?)}
- nLoop 0 nVisit 0 nEst 2 zName t1 zExplain {SCAN TABLE t1}
+ nLoop 0 nVisit 0 nEst 2.0 zName t1 zExplain {SCAN TABLE t1}
}
#-------------------------------------------------------------------------
# Try a few different types of scans.
#
@@ -102,43 +102,43 @@
SELECT * FROM x1 WHERE i=2;
} {2 two}
do_scanstatus_test 2.2 {
- nLoop 1 nVisit 1 nEst 1 zName x1
+ nLoop 1 nVisit 1 nEst 1.0 zName x1
zExplain {SEARCH TABLE x1 USING INTEGER PRIMARY KEY (rowid=?)}
}
do_execsql_test 2.3.1 {
SELECT * FROM x1 WHERE j='two'
} {2 two}
do_scanstatus_test 2.3.2 {
- nLoop 1 nVisit 1 nEst 10 zName x1j
+ nLoop 1 nVisit 1 nEst 10.0 zName x1j
zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j=?)}
}
do_execsql_test 2.4.1 {
SELECT * FROM x1 WHERE j<'two'
} {4 four 1 one 3 three}
do_scanstatus_test 2.4.2 {
- nLoop 1 nVisit 3 nEst 262144 zName x1j
+ nLoop 1 nVisit 3 nEst 262144.0 zName x1j
zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j)}
}
do_execsql_test 2.5.1 {
SELECT * FROM x1 WHERE j>='two'
} {2 two}
do_scanstatus_test 2.5.2 {
- nLoop 1 nVisit 1 nEst 262144 zName x1j
+ nLoop 1 nVisit 1 nEst 262144.0 zName x1j
zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j>?)}
}
do_execsql_test 2.6.1 {
SELECT * FROM x1 WHERE j BETWEEN 'three' AND 'two'
} {3 three 2 two}
do_scanstatus_test 2.6.2 {
- nLoop 1 nVisit 2 nEst 16384 zName x1j
+ nLoop 1 nVisit 2 nEst 16384.0 zName x1j
zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j>? AND j)}
}
do_execsql_test 2.7.1 {
CREATE TABLE x2(i INTEGER, j, k);
@@ -147,35 +147,35 @@
CREATE INDEX x2ij ON x2(i, j);
SELECT * FROM x2 WHERE j BETWEEN 'three' AND 'two'
} {3 three {3 three} 2 two {2 two}}
do_scanstatus_test 2.7.2 {
- nLoop 1 nVisit 2 nEst 16384 zName x2j
+ nLoop 1 nVisit 2 nEst 16384.0 zName x2j
zExplain {SEARCH TABLE x2 USING INDEX x2j (j>? AND j)}
}
do_execsql_test 2.8.1 {
SELECT * FROM x2 WHERE i=1 AND j='two'
}
do_scanstatus_test 2.8.2 {
- nLoop 1 nVisit 0 nEst 8 zName x2ij
+ nLoop 1 nVisit 0 nEst 8.0 zName x2ij
zExplain {SEARCH TABLE x2 USING INDEX x2ij (i=? AND j=?)}
}
do_execsql_test 2.9.1 {
SELECT * FROM x2 WHERE i=5 AND j='two'
}
do_scanstatus_test 2.9.2 {
- nLoop 1 nVisit 0 nEst 8 zName x2ij
+ nLoop 1 nVisit 0 nEst 8.0 zName x2ij
zExplain {SEARCH TABLE x2 USING INDEX x2ij (i=? AND j=?)}
}
do_execsql_test 2.10.1 {
SELECT * FROM x2 WHERE i=3 AND j='three'
} {3 three {3 three}}
do_scanstatus_test 2.10.2 {
- nLoop 1 nVisit 1 nEst 8 zName x2ij
+ nLoop 1 nVisit 1 nEst 8.0 zName x2ij
zExplain {SEARCH TABLE x2 USING INDEX x2ij (i=? AND j=?)}
}
#-------------------------------------------------------------------------
# Try with queries that use the OR optimization.
@@ -191,50 +191,50 @@
do_execsql_test 3.2.1 {
SELECT d FROM a1 WHERE (a=4 OR b=13)
} {4 13}
do_scanstatus_test 3.2.2 {
- nLoop 1 nVisit 1 nEst 10 zName a1a
+ nLoop 1 nVisit 1 nEst 10.0 zName a1a
zExplain {SEARCH TABLE a1 USING INDEX a1a (a=?)}
- nLoop 1 nVisit 1 nEst 10 zName a1bc
+ nLoop 1 nVisit 1 nEst 10.0 zName a1bc
zExplain {SEARCH TABLE a1 USING INDEX a1bc (b=?)}
}
do_execsql_test 3.2.1 {
SELECT count(*) FROM a1 WHERE (a BETWEEN 4 AND 12) OR (b BETWEEN 40 AND 60)
} {30}
do_scanstatus_test 3.2.2 {
- nLoop 1 nVisit 9 nEst 16384 zName a1a
+ nLoop 1 nVisit 9 nEst 16384.0 zName a1a
zExplain {SEARCH TABLE a1 USING INDEX a1a (a>? AND a)}
- nLoop 1 nVisit 21 nEst 16384 zName a1bc
+ nLoop 1 nVisit 21 nEst 16384.0 zName a1bc
zExplain {SEARCH TABLE a1 USING INDEX a1bc (b>? AND b)}
}
do_execsql_test 3.3.1 {
SELECT count(*) FROM a1 AS x, a1 AS y
WHERE (x.a BETWEEN 4 AND 12) AND (y.b BETWEEN 1 AND 10)
} {90}
do_scanstatus_test 3.2.2 {
- nLoop 1 nVisit 10 nEst 16384 zName a1bc
+ nLoop 1 nVisit 10 nEst 16384.0 zName a1bc
zExplain {SEARCH TABLE a1 AS y USING COVERING INDEX a1bc (b>? AND b)}
- nLoop 10 nVisit 90 nEst 16384 zName a1a
+ nLoop 10 nVisit 90 nEst 16384.0 zName a1a
zExplain {SEARCH TABLE a1 AS x USING COVERING INDEX a1a (a>? AND a)}
}
do_execsql_test 3.4.1 {
SELECT count(*) FROM a1 WHERE a IN (1, 5, 10, 15);
} {4}
do_scanstatus_test 3.4.2 {
- nLoop 1 nVisit 4 nEst 40 zName a1a
+ nLoop 1 nVisit 4 nEst 40.0 zName a1a
zExplain {SEARCH TABLE a1 USING COVERING INDEX a1a (a=?)}
}
do_execsql_test 3.4.1 {
SELECT count(*) FROM a1 WHERE rowid IN (1, 5, 10, 15);
} {4}
do_scanstatus_test 3.4.2 {
- nLoop 1 nVisit 4 nEst 4 zName a1
+ nLoop 1 nVisit 4 nEst 4.0 zName a1
zExplain {SEARCH TABLE a1 USING INTEGER PRIMARY KEY (rowid=?)}
}
#-------------------------------------------------------------------------
# Test that scanstatus() data is not available for searches performed
@@ -263,14 +263,14 @@
INSERT INTO c1 VALUES(1), (2), (3);
PRAGMA foreign_keys=on;
}
do_execsql_test 4.2.1 { DELETE FROM p1 WHERE x=4 }
do_scanstatus_test 4.2.2 {
- nLoop 1 nVisit 1 nEst 1 zName sqlite_autoindex_p1_1
+ nLoop 1 nVisit 1 nEst 1.0 zName sqlite_autoindex_p1_1
zExplain {SEARCH TABLE p1 USING INDEX sqlite_autoindex_p1_1 (x=?)}
- nLoop 1 nVisit 3 nEst 524288 zName c1 zExplain {SCAN TABLE c1}
+ nLoop 1 nVisit 3 nEst 524288.0 zName c1 zExplain {SCAN TABLE c1}
}
#-------------------------------------------------------------------------
# Further tests of different scan types.
#
@@ -310,21 +310,21 @@
do_execsql_test 5.1.1 {
SELECT count(*) FROM t1 WHERE a IN (SELECT b FROM t1 AS ii)
} {2}
do_scanstatus_test 5.1.2 {
- nLoop 1 nVisit 10 nEst 10 zName t1bc
+ nLoop 1 nVisit 10 nEst 10.0 zName t1bc
zExplain {SCAN TABLE t1 AS ii USING COVERING INDEX t1bc}
- nLoop 1 nVisit 2 nEst 8 zName sqlite_autoindex_t1_1
+ nLoop 1 nVisit 2 nEst 8.0 zName sqlite_autoindex_t1_1
zExplain {SEARCH TABLE t1 USING COVERING INDEX sqlite_autoindex_t1_1 (a=?)}
}
do_execsql_test 5.2.1 {
SELECT count(*) FROM t1 WHERE a IN (0, 1)
} {2}
do_scanstatus_test 5.2.2 {
- nLoop 1 nVisit 2 nEst 2 zName sqlite_autoindex_t1_1
+ nLoop 1 nVisit 2 nEst 2.0 zName sqlite_autoindex_t1_1
zExplain {SEARCH TABLE t1 USING COVERING INDEX sqlite_autoindex_t1_1 (a=?)}
}
do_eqp_test 5.3.1 {
SELECT count(*) FROM t2 WHERE y = 'j';
@@ -331,11 +331,11 @@
} {0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}}
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 zName t2xy zExplain
+ nLoop 1 nVisit 19 nEst 56.0 zName t2xy zExplain
{SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
}
do_eqp_test 5.4.1 {
SELECT count(*) FROM t1, t2 WHERE y = c;
@@ -345,13 +345,13 @@
}
do_execsql_test 5.4.2 {
SELECT count(*) FROM t1, t2 WHERE y = c;
} {200}
do_scanstatus_test 5.4.3 {
- nLoop 1 nVisit 10 nEst 10 zName t1bc
+ nLoop 1 nVisit 10 nEst 10.0 zName t1bc
zExplain {SCAN TABLE t1 USING COVERING INDEX t1bc}
- nLoop 10 nVisit 200 nEst 56 zName t2xy
+ nLoop 10 nVisit 200 nEst 56.0 zName t2xy
zExplain {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
}
do_eqp_test 5.5.1 {
SELECT count(*) FROM t1, t3 WHERE y = c;
@@ -361,12 +361,12 @@
}
do_execsql_test 5.5.2 {
SELECT count(*) FROM t1, t3 WHERE y = c;
} {200}
do_scanstatus_test 5.5.3 {
- nLoop 1 nVisit 501 nEst 480 zName t3 zExplain {SCAN TABLE t3}
- nLoop 501 nVisit 200 nEst 20 zName auto-index zExplain
+ nLoop 1 nVisit 501 nEst 480.0 zName t3 zExplain {SCAN TABLE t3}
+ nLoop 501 nVisit 200 nEst 20.0 zName auto-index zExplain
{SEARCH TABLE t1 USING AUTOMATIC COVERING INDEX (c=?)}
}
#-------------------------------------------------------------------------
# Virtual table scans
@@ -387,12 +387,12 @@
}
do_execsql_test 6.1.1 {
SELECT count(*) FROM ft1 WHERE ft1 MATCH 'd'
} {6}
do_scanstatus_test 6.1.2 {
- nLoop 1 nVisit 6 nEst 24 zName ft1 zExplain
+ nLoop 1 nVisit 6 nEst 24.0 zName ft1 zExplain
{SCAN TABLE ft1 VIRTUAL TABLE INDEX 3:}
}
}
finish_test