From: dan Date: Sat, 1 Nov 2014 18:08:04 +0000 (+0000) Subject: Minor fixes and documentation improvements for sqlite3_stmt_scanstatus(). X-Git-Tag: version-3.8.8~192^2~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=89e71646df320b5ff107f618169227c5c7cac8eb;p=thirdparty%2Fsqlite.git Minor fixes and documentation improvements for sqlite3_stmt_scanstatus(). FossilOrigin-Name: 8d8cc9608d30bb65fffcfe488e904411cbbc7f41 --- diff --git a/manifest b/manifest index 39eaf23ca4..8582d6b5e8 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sexperimental\ssqlite3_stmt_scanstatus()\sAPI. -D 2014-10-31T20:11:32.562 +C Minor\sfixes\sand\sdocumentation\simprovements\sfor\ssqlite3_stmt_scanstatus(). +D 2014-11-01T18:08:04.130 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in cf57f673d77606ab0f2d9627ca52a9ba1464146a F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -229,7 +229,7 @@ F src/resolve.c 4965007d6497b6a4d7a6d98751cc39712885f952 F src/rowset.c eccf6af6d620aaa4579bd3b72c1b6395d9e9fa1e F src/select.c 428165951748151e87a15295b7357221433e311b F src/shell.c 282f8f5278e0c78eb442217531172ec9e1538796 -F src/sqlite.h.in 6e90cdb404e4fa8c0eb149ca79c11c6608a97ece +F src/sqlite.h.in aeba29025ba5fc721a11c1b81ed8745f93029590 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d F src/sqliteInt.h 4f86ac648ea398c1bb3db036062934cde257ea23 @@ -289,7 +289,7 @@ F src/update.c 3c4ecc282accf12d39edb8d524cf089645e55a13 F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c F src/util.c 3b627daa45c7308c1e36e3dbaa3f9ce7e5c7fa73 F src/vacuum.c 59f03f92bcff57faa6a8ca256eb29ccddfb0614a -F src/vdbe.c 80329be857cff3c2d6e8c1f594ac689166c44ae7 +F src/vdbe.c 5240bad20ce0b707afee211f0c21a862b54b1e0b F src/vdbe.h f8e5388173dbf8408da4ae1dcbf75911caf2253d F src/vdbeInt.h 284b2294c188474daa9b5ce2bd0200560cb0940d F src/vdbeapi.c 2afa2e162f290879ca9c51e8795a377035f1662a @@ -302,8 +302,8 @@ F src/vtab.c 2a30791bbd7926b589401bd09c3abb33de563793 F src/wal.c 10e7de7ce90865a68153f001a61f1d985cd17983 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804 -F src/where.c 344beac082f8f4f69ec7c4a669d74294475e5abe -F src/whereInt.h 19279cd0664ce1d90b9ad3ef0108cb494acfe455 +F src/where.c 636ca646c8f2f53fd66f9ed5c773e84cb0c4b762 +F src/whereInt.h 99d324a8f921d7a40c605a8b197350c3cb18977d F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test b35b4cd69fc913f90d39a575e171e1116c3a4bb7 @@ -801,7 +801,7 @@ F test/savepoint4.test c8f8159ade6d2acd9128be61e1230f1c1edc6cc0 F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7 F test/savepoint7.test fbf319a7b2dda089ec5be30a424a0e95f121d423 -F test/scanstatus.test a62dad3311fc51eab1d6977b082738bd2148fe07 +F test/scanstatus.test b4b1780bad243e1576329d05597b99f06886e4d2 F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481 F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5 F test/schema3.test 1bc1008e1f8cb5654b248c55f27249366eb7ed38 @@ -1211,10 +1211,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 67f0d469da28c023200239a1f3d0c6cef9ef0e45 -R 4c76f3e7b97f67c1dd65bda3a6e96149 -T *branch * scanstatus -T *sym-scanstatus * -T -sym-trunk * +P 6a9bab34aeb6a01b612211a28c140de60a3e883c +R d964f269915d57cf95d9198c6ba22665 U dan -Z 4994ca943ee260eeca8f493b4f59766a +Z 082decdd6298ff1a2330407f8d406dfb diff --git a/manifest.uuid b/manifest.uuid index b7984cac38..7325586095 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6a9bab34aeb6a01b612211a28c140de60a3e883c \ No newline at end of file +8d8cc9608d30bb65fffcfe488e904411cbbc7f41 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index ba20cb9890..51383426d9 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -7408,6 +7408,8 @@ int sqlite3_vtab_on_conflict(sqlite3 *); /* +** CAPI3REF: Prepared Statement Scan Statuses +** ** Return status data for a single loop within query pStmt. ** ** Parameter "idx" identifies the specific loop to retrieve statistics for. @@ -7415,7 +7417,25 @@ int sqlite3_vtab_on_conflict(sqlite3 *); ** zero or greater than or equal to the total number of loops used to implement ** the statement - a non-zero value is returned. In this case the final value ** of all five output parameters is undefined. Otherwise, if idx is in range, -** the output parameters are populated and zero returned. +** zero is returned and the output parameters set as follows: +** +** +** +** Output parameters *pzName and *pzExplain are set to point to buffers +** managed by the statement object. Both of these pointers may be invalidated +** by any API call on the same statement object, including an sqlite3_step() +** sqlite3_bind_*() call. ** ** Statistics may not be available for all loops in all statements. In cases ** where there exist loops with no available statistics, this function ignores @@ -7436,6 +7456,8 @@ SQLITE_EXPERIMENTAL int sqlite3_stmt_scanstatus( /* +** CAPI3REF: Zero Scan-Status Counters +** ** Zero all sqlite3_stmt_scanstatus() related event counters. ** ** This API is only available if the library is built with pre-processor diff --git a/src/vdbe.c b/src/vdbe.c index a92c0509b3..1abccfeeab 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -3889,6 +3889,7 @@ case OP_NotExists: { /* jump, in3 */ res = 0; iKey = pIn3->u.i; rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res); + IncrementExplainCounter(pC, nLoop); pC->movetoTarget = iKey; /* Used by OP_Delete */ pC->nullRow = 0; pC->cacheStatus = CACHE_STALE; @@ -3896,6 +3897,8 @@ case OP_NotExists: { /* jump, in3 */ VdbeBranchTaken(res!=0,2); if( res!=0 ){ pc = pOp->p2 - 1; + }else{ + IncrementExplainCounter(pC, nVisit); } pC->seekResult = res; break; diff --git a/src/where.c b/src/where.c index 3565327b52..ae3c12725e 100644 --- a/src/where.c +++ b/src/where.c @@ -2739,7 +2739,7 @@ static int codeAllEqualityTerms( return regBase; } -#ifndef SQLITE_OMIT_EXPLAIN +#if !defined(SQLITE_OMIT_EXPLAIN) || defined(SQLITE_ENABLE_STMT_SCANSTATUS) /* ** This routine is a helper for explainIndexRange() below ** @@ -2815,19 +2815,23 @@ static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop, Table *pTab){ static void explainOneScan( Parse *pParse, /* Parse context */ SrcList *pTabList, /* Table list this loop refers to */ - WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ + WhereInfo *pWInfo, /* WHERE clause this loop belongs to */ int iLevel, /* Value for "level" column of output */ - int iFrom, /* Value for "from" column of output */ u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ ){ #if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS) if( pParse->explain==2 ) #endif { + WhereLevel *pLevel = &pWInfo->a[iLevel]; struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom]; Vdbe *v = pParse->pVdbe; /* VM being constructed */ sqlite3 *db = pParse->db; /* Database handle */ - int iId = pParse->iSelectId; /* Select id (left-most output column) */ +#ifdef SQLITE_OMIT_EXPLAIN + int iId = 0; /* Select id (left-most output column) */ +#else + int iId = pParse->iSelectId; /* Select id (left-most output column) */ +#endif int isSearch; /* True for a SEARCH. False for SCAN. */ WhereLoop *pLoop; /* The controlling WhereLoop object */ u32 flags; /* Flags that describe this loop */ @@ -2839,7 +2843,7 @@ static void explainOneScan( pLoop = pLevel->pWLoop; flags = pLoop->wsFlags; - if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_ONETABLE_ONLY) ) return; + if( (flags&WHERE_MULTI_OR) ) return; sqlite3StrAccumInit(&str, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH); str.db = db; @@ -2865,7 +2869,11 @@ static void explainOneScan( || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX)); sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN"); if( pItem->pSelect ){ +#ifdef SQLITE_OMIT_EXPLAIN + sqlite3XPrintf(&str, 0, " SUBQUERY 0"); +#else sqlite3XPrintf(&str, 0, " SUBQUERY %d", pItem->iSelectId); +#endif }else{ sqlite3XPrintf(&str, 0, " TABLE %s", pItem->zName); } @@ -2937,15 +2945,15 @@ static void explainOneScan( pExplain->nEst = nEstRow; pExplain->zName = (const char*)&pExplain[1]; pExplain->zExplain = &pExplain->zName[sqlite3Strlen30(pExplain->zName)+1]; - sqlite3VdbeAddOp4(v, OP_Explain, - iId, iLevel, iFrom, (char*)pExplain,P4_EXPLAIN + pWInfo->iExplain = sqlite3VdbeAddOp4(v, OP_Explain, + iId, iLevel, pLevel->iFrom, (char*)pExplain,P4_EXPLAIN ); } } } #else -# define explainOneScan(u,v,w,x,y,z) -#endif /* SQLITE_OMIT_EXPLAIN */ +# define explainOneScan(v,w,x,y,z) +#endif /* !SQLITE_OMIT_EXPLAIN || SQLITE_ENABLE_STMT_SCANSTATUS */ /* @@ -3613,9 +3621,15 @@ static Bitmask codeOneLoopStart( assert( pSubWInfo || pParse->nErr || db->mallocFailed ); if( pSubWInfo ){ WhereLoop *pSubLoop; - explainOneScan( - pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0 - ); + + /* If an OP_Explain was added for this sub-loop, fix the P2 and + ** P3 parameters to it so that they are relative to the current + ** context. */ + if( pSubWInfo->iExplain!=0 ){ + sqlite3VdbeChangeP2(v, pSubWInfo->iExplain, iLevel); + sqlite3VdbeChangeP3(v, pSubWInfo->iExplain, pLevel->iFrom); + } + /* This is the sub-WHERE clause body. First skip over ** duplicate rows from prior sub-WHERE clauses, and record the ** rowid (or PRIMARY KEY) for the current row so that the same @@ -6455,7 +6469,7 @@ WhereInfo *sqlite3WhereBegin( if( db->mallocFailed ) goto whereBeginError; } #endif - explainOneScan(pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags); + explainOneScan(pParse, pTabList, pWInfo, ii, wctrlFlags); pLevel->addrBody = sqlite3VdbeCurrentAddr(v); notReady = codeOneLoopStart(pWInfo, ii, notReady); pWInfo->iContinue = pLevel->addrCont; diff --git a/src/whereInt.h b/src/whereInt.h index fd4cfdf88a..dcf0e00604 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -407,6 +407,7 @@ struct WhereInfo { int iTop; /* The very beginning of the WHERE loop */ int iContinue; /* Jump here to continue with next record */ int iBreak; /* Jump here to break out of the loop */ + int iExplain; /* Address of OP_Explain (if WHERE_ONETABLE_ONLY) */ int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */ WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */ diff --git a/test/scanstatus.test b/test/scanstatus.test index 69a92dcb6a..9df80f9ba8 100644 --- a/test/scanstatus.test +++ b/test/scanstatus.test @@ -53,16 +53,148 @@ do_scanstatus_test 1.4 { nLoop 2 nVisit 6 nEst 3 zName t2 zExplain {SCAN TABLE t2} } -do_execsql_test 1.5 { - ANALYZE; +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.6 { +do_scanstatus_test 1.7 { nLoop 1 nVisit 2 nEst 2 zName t2 zExplain {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid>?)} nLoop 2 nVisit 4 nEst 2 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 + {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid>?)} + nLoop 4 nVisit 8 nEst 2 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 + {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid>?)} + nLoop 0 nVisit 0 nEst 2 zName t1 zExplain {SCAN TABLE t1} +} + +#------------------------------------------------------------------------- +# Try a few different types of scans. +# +reset_db +do_execsql_test 2.1 { + CREATE TABLE x1(i INTEGER PRIMARY KEY, j); + INSERT INTO x1 VALUES(1, 'one'); + INSERT INTO x1 VALUES(2, 'two'); + INSERT INTO x1 VALUES(3, 'three'); + INSERT INTO x1 VALUES(4, 'four'); + CREATE INDEX x1j ON x1(j); + + SELECT * FROM x1 WHERE i=2; +} {2 two} + +do_scanstatus_test 2.2 { + nLoop 1 nVisit 1 nEst 1 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 + 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 4 nEst 262144 zName x1j + zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j='two' +} {2 two} +do_scanstatus_test 2.5.2 { + nLoop 1 nVisit 1 nEst 262144 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 + zExplain {SEARCH TABLE x1 USING COVERING INDEX x1j (j>? AND j? AND j