aboutsummaryrefslogtreecommitdiff
path: root/src/where.c
diff options
context:
space:
mode:
authordan <dan@noemail.net>2014-10-31 20:11:32 +0000
committerdan <dan@noemail.net>2014-10-31 20:11:32 +0000
commit04489b6dce1b28fffb9afa524b0eb854a400da21 (patch)
tree73a1b1140f1910e31f7d1c44b377b139c31d9f52 /src/where.c
parent0fb5daed34ba6f16d761b8ad02b944ec59cf5c03 (diff)
downloadsqlite-04489b6dce1b28fffb9afa524b0eb854a400da21.tar.gz
sqlite-04489b6dce1b28fffb9afa524b0eb854a400da21.zip
Add the experimental sqlite3_stmt_scanstatus() API.
FossilOrigin-Name: 6a9bab34aeb6a01b612211a28c140de60a3e883c
Diffstat (limited to 'src/where.c')
-rw-r--r--src/where.c55
1 files changed, 43 insertions, 12 deletions
diff --git a/src/where.c b/src/where.c
index feccf2d11..3565327b5 100644
--- a/src/where.c
+++ b/src/where.c
@@ -2820,7 +2820,7 @@ static void explainOneScan(
int iFrom, /* Value for "from" column of output */
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
){
-#ifndef SQLITE_DEBUG
+#if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS)
if( pParse->explain==2 )
#endif
{
@@ -2831,20 +2831,38 @@ static void explainOneScan(
int isSearch; /* True for a SEARCH. False for SCAN. */
WhereLoop *pLoop; /* The controlling WhereLoop object */
u32 flags; /* Flags that describe this loop */
- char *zMsg; /* Text to add to EQP output */
StrAccum str; /* EQP output string */
char zBuf[100]; /* Initial space for EQP output string */
+ const char *zObj;
+ ExplainArg *pExplain;
+ i64 nEstRow; /* Estimated rows per scan of pLevel */
pLoop = pLevel->pWLoop;
flags = pLoop->wsFlags;
if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_ONETABLE_ONLY) ) return;
+ sqlite3StrAccumInit(&str, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
+ str.db = db;
+
+ /* Reserve space at the start of the buffer managed by the StrAccum
+ ** object for *pExplain. */
+ assert( sizeof(*pExplain)<=sizeof(zBuf) );
+ str.nChar = sizeof(*pExplain);
+
+ /* Append the object (table or index) name to the buffer. */
+ if( pItem->pSelect ){
+ zObj = "";
+ }else if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){
+ zObj = pLoop->u.btree.pIndex->zName;
+ }else{
+ zObj = pItem->zName;
+ }
+ sqlite3StrAccumAppend(&str, zObj, sqlite3Strlen30(zObj)+1);
+
+ /* Append the EQP text to the buffer */
isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
|| ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
|| (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
-
- sqlite3StrAccumInit(&str, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
- str.db = db;
sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN");
if( pItem->pSelect ){
sqlite3XPrintf(&str, 0, " SUBQUERY %d", pItem->iSelectId);
@@ -2901,15 +2919,28 @@ static void explainOneScan(
pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr);
}
#endif
+ nEstRow = pLoop->nOut>=10 ? sqlite3LogEstToInt(pLoop->nOut) : 1;
#ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS
- if( pLoop->nOut>=10 ){
- sqlite3XPrintf(&str, 0, " (~%llu rows)", sqlite3LogEstToInt(pLoop->nOut));
- }else{
- sqlite3StrAccumAppend(&str, " (~1 row)", 9);
- }
+ sqlite3XPrintf(&str, 0, " (~%llu rows)", nEstRow);
#endif
- zMsg = sqlite3StrAccumFinish(&str);
- sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg, P4_DYNAMIC);
+ pExplain = (ExplainArg*)sqlite3StrAccumFinish(&str);
+ assert( pExplain || db->mallocFailed );
+ if( pExplain ){
+ memset(pExplain, 0, sizeof(*pExplain));
+ if( pLoop->wsFlags & WHERE_INDEXED ){
+ pExplain->iCsr = pLevel->iIdxCur;
+ }else if( pItem->pSelect==0 ){
+ pExplain->iCsr = pLevel->iTabCur;
+ }else{
+ pExplain->iCsr = -1;
+ }
+ 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
+ );
+ }
}
}
#else