aboutsummaryrefslogtreecommitdiff
path: root/src/wherecode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/wherecode.c')
-rw-r--r--src/wherecode.c65
1 files changed, 50 insertions, 15 deletions
diff --git a/src/wherecode.c b/src/wherecode.c
index 0951e5e20..f1c6711af 100644
--- a/src/wherecode.c
+++ b/src/wherecode.c
@@ -110,27 +110,24 @@ static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop){
}
/*
-** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN
-** command, or if stmt_scanstatus_v2() stats are enabled, or if SQLITE_DEBUG
-** was defined at compile-time. If it is not a no-op, a single OP_Explain
-** opcode is added to the output to describe the table scan strategy in pLevel.
-**
-** If an OP_Explain opcode is added to the VM, its address is returned.
-** Otherwise, if no OP_Explain is coded, zero is returned.
+** This function sets the P4 value of an existing OP_Explain opcode to
+** text describing the loop in pLevel. If the OP_Explain opcode already has
+** a P4 value, it is freed before it is overwritten.
*/
-int sqlite3WhereExplainOneScan(
+void sqlite3WhereAddExplainText(
Parse *pParse, /* Parse context */
+ int addr, /* Address of OP_Explain opcode */
SrcList *pTabList, /* Table list this loop refers to */
WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
){
- int ret = 0;
#if !defined(SQLITE_DEBUG)
if( sqlite3ParseToplevel(pParse)->explain==2 || IS_STMT_SCANSTATUS(pParse->db) )
#endif
{
+ VdbeOp *pOp = sqlite3VdbeGetOp(pParse->pVdbe, addr);
+
SrcItem *pItem = &pTabList->a[pLevel->iFrom];
- Vdbe *v = pParse->pVdbe; /* VM being constructed */
sqlite3 *db = pParse->db; /* Database handle */
int isSearch; /* True for a SEARCH. False for SCAN. */
WhereLoop *pLoop; /* The controlling WhereLoop object */
@@ -139,9 +136,10 @@ int sqlite3WhereExplainOneScan(
StrAccum str; /* EQP output string */
char zBuf[100]; /* Initial space for EQP output string */
+ if( db->mallocFailed ) return;
+
pLoop = pLevel->pWLoop;
flags = pLoop->wsFlags;
- if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_OR_SUBCLAUSE) ) return 0;
isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
|| ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
@@ -165,7 +163,7 @@ int sqlite3WhereExplainOneScan(
zFmt = "AUTOMATIC PARTIAL COVERING INDEX";
}else if( flags & WHERE_AUTO_INDEX ){
zFmt = "AUTOMATIC COVERING INDEX";
- }else if( flags & WHERE_IDX_ONLY ){
+ }else if( flags & (WHERE_IDX_ONLY|WHERE_EXPRIDX) ){
zFmt = "COVERING INDEX %s";
}else{
zFmt = "INDEX %s";
@@ -219,9 +217,46 @@ int sqlite3WhereExplainOneScan(
#endif
zMsg = sqlite3StrAccumFinish(&str);
sqlite3ExplainBreakpoint("",zMsg);
- ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
- pParse->addrExplain, pLoop->rRun,
- zMsg, P4_DYNAMIC);
+
+ assert( pOp->opcode==OP_Explain );
+ assert( pOp->p4type==P4_DYNAMIC || pOp->p4.z==0 );
+ sqlite3DbFree(db, pOp->p4.z);
+ pOp->p4type = P4_DYNAMIC;
+ pOp->p4.z = sqlite3StrAccumFinish(&str);
+ }
+}
+
+
+/*
+** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN
+** command, or if stmt_scanstatus_v2() stats are enabled, or if SQLITE_DEBUG
+** was defined at compile-time. If it is not a no-op, a single OP_Explain
+** opcode is added to the output to describe the table scan strategy in pLevel.
+**
+** If an OP_Explain opcode is added to the VM, its address is returned.
+** Otherwise, if no OP_Explain is coded, zero is returned.
+*/
+int sqlite3WhereExplainOneScan(
+ Parse *pParse, /* Parse context */
+ SrcList *pTabList, /* Table list this loop refers to */
+ WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
+ u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
+){
+ int ret = 0;
+#if !defined(SQLITE_DEBUG)
+ if( sqlite3ParseToplevel(pParse)->explain==2 || IS_STMT_SCANSTATUS(pParse->db) )
+#endif
+ {
+ if( (pLevel->pWLoop->wsFlags & WHERE_MULTI_OR)==0
+ && (wctrlFlags & WHERE_OR_SUBCLAUSE)==0
+ ){
+ Vdbe *v = pParse->pVdbe;
+ int addr = sqlite3VdbeCurrentAddr(v);
+ ret = sqlite3VdbeAddOp3(
+ v, OP_Explain, addr, pParse->addrExplain, pLevel->pWLoop->rRun
+ );
+ sqlite3WhereAddExplainText(pParse, addr, pTabList, pLevel, wctrlFlags);
+ }
}
return ret;
}