/ Check-in [70b48a79]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Begin reengineering the EXPLAIN QUERY PLAN function to provide more intuitive output.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | rework-EQP
Files: files | file ages | folders
SHA3-256: 70b48a7972dfbb44af3ccd8ccd830e984bec88d80a78b3566a5de86a16e7fc14
User & Date: drh 2018-05-02 00:33:43
Context
2018-05-02
02:22
Improvements to the EQP display for compound select statements. check-in: 699a77e4 user: drh tags: rework-EQP
00:33
Begin reengineering the EXPLAIN QUERY PLAN function to provide more intuitive output. check-in: 70b48a79 user: drh tags: rework-EQP
2018-05-01
18:39
The SQLITE_ALLOW_SQLITE_MASTER_INDEX compile-time option allows a CREATE INDEX statement against the sqlite_master table. Once created, the index works, and is usable by legacy instances of SQLite. check-in: 853f3163 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/expr.c.

  2406   2406               if( aiMap ) aiMap[i] = j;
  2407   2407             }
  2408   2408     
  2409   2409             assert( i==nExpr || colUsed!=(MASKBIT(nExpr)-1) );
  2410   2410             if( colUsed==(MASKBIT(nExpr)-1) ){
  2411   2411               /* If we reach this point, that means the index pIdx is usable */
  2412   2412               int iAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
  2413         -#ifndef SQLITE_OMIT_EXPLAIN
  2414         -            sqlite3VdbeAddOp4(v, OP_Explain, 0, 0, 0,
  2415         -              sqlite3MPrintf(db, "USING INDEX %s FOR IN-OPERATOR",pIdx->zName),
  2416         -              P4_DYNAMIC);
  2417         -#endif
         2413  +            ExplainQueryPlan((pParse, 0,
         2414  +                              "USING INDEX %s FOR IN-OPERATOR",pIdx->zName));
  2418   2415               sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb);
  2419   2416               sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
  2420   2417               VdbeComment((v, "%s", pIdx->zName));
  2421   2418               assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 );
  2422   2419               eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0];
  2423   2420     
  2424   2421               if( prRhsHasNull ){
................................................................................
  2642   2639           **
  2643   2640           ** Generate code to write the results of the select into the temporary
  2644   2641           ** table allocated and opened above.
  2645   2642           */
  2646   2643           Select *pSelect = pExpr->x.pSelect;
  2647   2644           ExprList *pEList = pSelect->pEList;
  2648   2645   
  2649         -#ifndef SQLITE_OMIT_EXPLAIN
  2650         -        if( pParse->explain==2 ){
  2651         -          char *zMsg = sqlite3MPrintf(pParse->db, "EXECUTE %sLIST SUBQUERY %d",
  2652         -            jmpIfDynamic>=0?"":"CORRELATED ",
  2653         -            pParse->iNextSelectId
  2654         -          );
  2655         -          sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg,
  2656         -                            P4_DYNAMIC);
  2657         -        }
  2658         -#endif
  2659         -
         2646  +        ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY",
         2647  +            jmpIfDynamic>=0?"":"CORRELATED "
         2648  +        ));
         2649  +        ExplainQueryPlanSetId(pParse, pSelect);
  2660   2650           assert( !isRowid );
  2661   2651           /* If the LHS and RHS of the IN operator do not match, that
  2662   2652           ** error will have been caught long before we reach this point. */
  2663   2653           if( ALWAYS(pEList->nExpr==nVal) ){
  2664   2654             SelectDest dest;
  2665   2655             int i;
  2666   2656             sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
................................................................................
  2773   2763         Expr *pLimit;                         /* New limit expression */
  2774   2764   
  2775   2765         testcase( pExpr->op==TK_EXISTS );
  2776   2766         testcase( pExpr->op==TK_SELECT );
  2777   2767         assert( pExpr->op==TK_EXISTS || pExpr->op==TK_SELECT );
  2778   2768         assert( ExprHasProperty(pExpr, EP_xIsSelect) );
  2779   2769   
  2780         -#ifndef SQLITE_OMIT_EXPLAIN
  2781         -      if( pParse->explain==2 ){
  2782         -        char *zMsg = sqlite3MPrintf(pParse->db, "EXECUTE %sSCALAR SUBQUERY %d",
  2783         -            jmpIfDynamic>=0?"":"CORRELATED ",
  2784         -            pParse->iNextSelectId
  2785         -        );
  2786         -        sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg,
  2787         -                          P4_DYNAMIC);
  2788         -      }
  2789         -#endif
  2790         -
  2791   2770         pSel = pExpr->x.pSelect;
         2771  +      ExplainQueryPlan((pParse, 1, "%sSCALAR SUBQUERY",
         2772  +            jmpIfDynamic>=0?"":"CORRELATED "));
         2773  +      ExplainQueryPlanSetId(pParse, pSel);
  2792   2774         nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1;
  2793   2775         sqlite3SelectDestInit(&dest, 0, pParse->nMem+1);
  2794   2776         pParse->nMem += nReg;
  2795   2777         if( pExpr->op==TK_SELECT ){
  2796   2778           dest.eDest = SRT_Mem;
  2797   2779           dest.iSdst = dest.iSDParm;
  2798   2780           dest.nSdst = nReg;

Changes to src/select.c.

    17     17   /*
    18     18   ** Trace output macros
    19     19   */
    20     20   #if SELECTTRACE_ENABLED
    21     21   /***/ int sqlite3SelectTrace = 0;
    22     22   # define SELECTTRACE(K,P,S,X)  \
    23     23     if(sqlite3SelectTrace&(K))   \
    24         -    sqlite3DebugPrintf("%s/%d/%p: ",(S)->zSelName,(P)->iSelectId,(S)),\
           24  +    sqlite3DebugPrintf("%s/%d/%p: ",(S)->zSelName,(P)->addrExplain,(S)),\
    25     25       sqlite3DebugPrintf X
    26     26   #else
    27     27   # define SELECTTRACE(K,P,S,X)
    28     28   #endif
    29     29   
    30     30   
    31     31   /*
................................................................................
   143    143     pNew->pEList = pEList;
   144    144     pNew->op = TK_SELECT;
   145    145     pNew->selFlags = selFlags;
   146    146     pNew->iLimit = 0;
   147    147     pNew->iOffset = 0;
   148    148   #if SELECTTRACE_ENABLED
   149    149     pNew->zSelName[0] = 0;
          150  +#endif
          151  +#if SELECTTRACE_ENABLED || !defined(SQLITE_OMIT_EXPLAIN)
          152  +  pNew->iSelectId = 0;
   150    153   #endif
   151    154     pNew->addrOpenEphm[0] = -1;
   152    155     pNew->addrOpenEphm[1] = -1;
   153    156     pNew->nSelectRow = 0;
   154    157     if( pSrc==0 ) pSrc = sqlite3DbMallocZero(pParse->db, sizeof(*pSrc));
   155    158     pNew->pSrc = pSrc;
   156    159     pNew->pWhere = pWhere;
................................................................................
  1289   1292   **
  1290   1293   **   "USE TEMP B-TREE FOR xxx"
  1291   1294   **
  1292   1295   ** where xxx is one of "DISTINCT", "ORDER BY" or "GROUP BY". Exactly which
  1293   1296   ** is determined by the zUsage argument.
  1294   1297   */
  1295   1298   static void explainTempTable(Parse *pParse, const char *zUsage){
  1296         -  if( pParse->explain==2 ){
  1297         -    Vdbe *v = pParse->pVdbe;
  1298         -    char *zMsg = sqlite3MPrintf(pParse->db, "USE TEMP B-TREE FOR %s", zUsage);
  1299         -    sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
  1300         -  }
         1299  +  ExplainQueryPlan((pParse, 0, "USE TEMP B-TREE FOR %s", zUsage));
  1301   1300   }
  1302   1301   
  1303   1302   /*
  1304   1303   ** Assign expression b to lvalue a. A second, no-op, version of this macro
  1305   1304   ** is provided when SQLITE_OMIT_EXPLAIN is defined. This allows the code
  1306   1305   ** in sqlite3Select() to assign values to structure member variables that
  1307   1306   ** only exist if SQLITE_OMIT_EXPLAIN is not defined without polluting the
................................................................................
  1317   1316   
  1318   1317   #if !defined(SQLITE_OMIT_EXPLAIN) && !defined(SQLITE_OMIT_COMPOUND_SELECT)
  1319   1318   /*
  1320   1319   ** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function
  1321   1320   ** is a no-op. Otherwise, it adds a single row of output to the EQP result,
  1322   1321   ** where the caption is of one of the two forms:
  1323   1322   **
  1324         -**   "COMPOSITE SUBQUERIES iSub1 and iSub2 (op)"
  1325         -**   "COMPOSITE SUBQUERIES iSub1 and iSub2 USING TEMP B-TREE (op)"
         1323  +**   "COMPOSITE (op)"
         1324  +**   "COMPOSITE USING TEMP B-TREE (op)"
  1326   1325   **
  1327         -** where iSub1 and iSub2 are the integers passed as the corresponding
  1328         -** function parameters, and op is the text representation of the parameter
         1326  +** where op is the text representation of the parameter
  1329   1327   ** of the same name. The parameter "op" must be one of TK_UNION, TK_EXCEPT,
  1330   1328   ** TK_INTERSECT or TK_ALL. The first form is used if argument bUseTmp is 
  1331   1329   ** false, or the second form if it is true.
  1332   1330   */
  1333   1331   static void explainComposite(
  1334   1332     Parse *pParse,                  /* Parse context */
  1335   1333     int op,                         /* One of TK_UNION, TK_EXCEPT etc. */
  1336         -  int iSub1,                      /* Subquery id 1 */
  1337         -  int iSub2,                      /* Subquery id 2 */
  1338   1334     int bUseTmp                     /* True if a temp table was used */
  1339   1335   ){
  1340   1336     assert( op==TK_UNION || op==TK_EXCEPT || op==TK_INTERSECT || op==TK_ALL );
  1341         -  if( pParse->explain==2 ){
  1342         -    Vdbe *v = pParse->pVdbe;
  1343         -    char *zMsg = sqlite3MPrintf(
  1344         -        pParse->db, "COMPOUND SUBQUERIES %d AND %d %s(%s)", iSub1, iSub2,
  1345         -        bUseTmp?"USING TEMP B-TREE ":"", selectOpName(op)
  1346         -    );
  1347         -    sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
  1348         -  }
         1337  +  ExplainQueryPlan((pParse, 1, "COMPOUND %s(%s)",
         1338  +        bUseTmp?"USING TEMP B-TREE ":"", selectOpName(op)));
  1349   1339   }
  1350   1340   #else
  1351   1341   /* No-op versions of the explainXXX() functions and macros. */
  1352         -# define explainComposite(v,w,x,y,z)
         1342  +# define explainComposite(v,y,z)
  1353   1343   #endif
  1354   1344   
  1355   1345   /*
  1356   1346   ** If the inner loop was generated using a non-null pOrderBy argument,
  1357   1347   ** then the results were placed in a sorter.  After the loop is terminated
  1358   1348   ** we need to run the sorter and output the results.  The following
  1359   1349   ** routine generates the code needed to do that.
................................................................................
  2470   2460   ){
  2471   2461     int rc = SQLITE_OK;   /* Success code from a subroutine */
  2472   2462     Select *pPrior;       /* Another SELECT immediately to our left */
  2473   2463     Vdbe *v;              /* Generate code to this VDBE */
  2474   2464     SelectDest dest;      /* Alternative data destination */
  2475   2465     Select *pDelete = 0;  /* Chain of simple selects to delete */
  2476   2466     sqlite3 *db;          /* Database connection */
  2477         -#ifndef SQLITE_OMIT_EXPLAIN
  2478         -  int iSub1 = 0;        /* EQP id of left-hand query */
  2479         -  int iSub2 = 0;        /* EQP id of right-hand query */
  2480         -#endif
  2481   2467   
  2482   2468     /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs.  Only
  2483   2469     ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT.
  2484   2470     */
  2485   2471     assert( p && p->pPrior );  /* Calling function guarantees this much */
  2486   2472     assert( (p->selFlags & SF_Recursive)==0 || p->op==TK_ALL || p->op==TK_UNION );
  2487   2473     db = pParse->db;
................................................................................
  2528   2514     */
  2529   2515     if( p->pOrderBy ){
  2530   2516       return multiSelectOrderBy(pParse, p, pDest);
  2531   2517     }else
  2532   2518   
  2533   2519     /* Generate code for the left and right SELECT statements.
  2534   2520     */
         2521  +  explainComposite(pParse, p->op, p->op!=TK_ALL);
  2535   2522     switch( p->op ){
  2536   2523       case TK_ALL: {
  2537   2524         int addr = 0;
  2538   2525         int nLimit;
  2539   2526         assert( !pPrior->pLimit );
  2540   2527         pPrior->iLimit = p->iLimit;
  2541   2528         pPrior->iOffset = p->iOffset;
  2542   2529         pPrior->pLimit = p->pLimit;
  2543         -      explainSetInteger(iSub1, pParse->iNextSelectId);
  2544   2530         rc = sqlite3Select(pParse, pPrior, &dest);
  2545   2531         p->pLimit = 0;
  2546   2532         if( rc ){
  2547   2533           goto multi_select_end;
  2548   2534         }
  2549   2535         p->pPrior = 0;
  2550   2536         p->iLimit = pPrior->iLimit;
................................................................................
  2553   2539           addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
  2554   2540           VdbeComment((v, "Jump ahead if LIMIT reached"));
  2555   2541           if( p->iOffset ){
  2556   2542             sqlite3VdbeAddOp3(v, OP_OffsetLimit,
  2557   2543                               p->iLimit, p->iOffset+1, p->iOffset);
  2558   2544           }
  2559   2545         }
  2560         -      explainSetInteger(iSub2, pParse->iNextSelectId);
  2561   2546         rc = sqlite3Select(pParse, p, &dest);
  2562   2547         testcase( rc!=SQLITE_OK );
  2563   2548         pDelete = p->pPrior;
  2564   2549         p->pPrior = pPrior;
  2565   2550         p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
  2566   2551         if( pPrior->pLimit
  2567   2552          && sqlite3ExprIsInteger(pPrior->pLimit->pLeft, &nLimit)
................................................................................
  2605   2590           assert( p->pEList );
  2606   2591         }
  2607   2592   
  2608   2593         /* Code the SELECT statements to our left
  2609   2594         */
  2610   2595         assert( !pPrior->pOrderBy );
  2611   2596         sqlite3SelectDestInit(&uniondest, priorOp, unionTab);
  2612         -      explainSetInteger(iSub1, pParse->iNextSelectId);
  2613   2597         rc = sqlite3Select(pParse, pPrior, &uniondest);
  2614   2598         if( rc ){
  2615   2599           goto multi_select_end;
  2616   2600         }
  2617   2601   
  2618   2602         /* Code the current SELECT statement
  2619   2603         */
................................................................................
  2623   2607           assert( p->op==TK_UNION );
  2624   2608           op = SRT_Union;
  2625   2609         }
  2626   2610         p->pPrior = 0;
  2627   2611         pLimit = p->pLimit;
  2628   2612         p->pLimit = 0;
  2629   2613         uniondest.eDest = op;
  2630         -      explainSetInteger(iSub2, pParse->iNextSelectId);
  2631   2614         rc = sqlite3Select(pParse, p, &uniondest);
  2632   2615         testcase( rc!=SQLITE_OK );
  2633   2616         /* Query flattening in sqlite3Select() might refill p->pOrderBy.
  2634   2617         ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */
  2635   2618         sqlite3ExprListDelete(db, p->pOrderBy);
  2636   2619         pDelete = p->pPrior;
  2637   2620         p->pPrior = pPrior;
................................................................................
  2686   2669         p->addrOpenEphm[0] = addr;
  2687   2670         findRightmost(p)->selFlags |= SF_UsesEphemeral;
  2688   2671         assert( p->pEList );
  2689   2672   
  2690   2673         /* Code the SELECTs to our left into temporary table "tab1".
  2691   2674         */
  2692   2675         sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
  2693         -      explainSetInteger(iSub1, pParse->iNextSelectId);
  2694   2676         rc = sqlite3Select(pParse, pPrior, &intersectdest);
  2695   2677         if( rc ){
  2696   2678           goto multi_select_end;
  2697   2679         }
  2698   2680   
  2699   2681         /* Code the current SELECT into temporary table "tab2"
  2700   2682         */
................................................................................
  2701   2683         addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0);
  2702   2684         assert( p->addrOpenEphm[1] == -1 );
  2703   2685         p->addrOpenEphm[1] = addr;
  2704   2686         p->pPrior = 0;
  2705   2687         pLimit = p->pLimit;
  2706   2688         p->pLimit = 0;
  2707   2689         intersectdest.iSDParm = tab2;
  2708         -      explainSetInteger(iSub2, pParse->iNextSelectId);
  2709   2690         rc = sqlite3Select(pParse, p, &intersectdest);
  2710   2691         testcase( rc!=SQLITE_OK );
  2711   2692         pDelete = p->pPrior;
  2712   2693         p->pPrior = pPrior;
  2713   2694         if( p->nSelectRow>pPrior->nSelectRow ) p->nSelectRow = pPrior->nSelectRow;
  2714   2695         sqlite3ExprDelete(db, p->pLimit);
  2715   2696         p->pLimit = pLimit;
................................................................................
  2733   2714         sqlite3VdbeResolveLabel(v, iBreak);
  2734   2715         sqlite3VdbeAddOp2(v, OP_Close, tab2, 0);
  2735   2716         sqlite3VdbeAddOp2(v, OP_Close, tab1, 0);
  2736   2717         break;
  2737   2718       }
  2738   2719     }
  2739   2720   
  2740         -  explainComposite(pParse, p->op, iSub1, iSub2, p->op!=TK_ALL);
         2721  +  ExplainQueryPlanPop(pParse);
  2741   2722   
  2742   2723     /* Compute collating sequences used by 
  2743   2724     ** temporary tables needed to implement the compound select.
  2744   2725     ** Attach the KeyInfo structure to all temporary tables.
  2745   2726     **
  2746   2727     ** This section is run by the right-most SELECT statement only.
  2747   2728     ** SELECT statements to the left always skip this part.  The right-most
................................................................................
  3072   3053     int op;               /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */
  3073   3054     KeyInfo *pKeyDup = 0; /* Comparison information for duplicate removal */
  3074   3055     KeyInfo *pKeyMerge;   /* Comparison information for merging rows */
  3075   3056     sqlite3 *db;          /* Database connection */
  3076   3057     ExprList *pOrderBy;   /* The ORDER BY clause */
  3077   3058     int nOrderBy;         /* Number of terms in the ORDER BY clause */
  3078   3059     int *aPermute;        /* Mapping from ORDER BY terms to result set columns */
  3079         -#ifndef SQLITE_OMIT_EXPLAIN
  3080         -  int iSub1;            /* EQP id of left-hand query */
  3081         -  int iSub2;            /* EQP id of right-hand query */
  3082         -#endif
  3083   3060   
  3084   3061     assert( p->pOrderBy!=0 );
  3085   3062     assert( pKeyDup==0 ); /* "Managed" code needs this.  Ticket #3382. */
  3086   3063     db = pParse->db;
  3087   3064     v = pParse->pVdbe;
  3088   3065     assert( v!=0 );       /* Already thrown the error if VDBE alloc failed */
  3089   3066     labelEnd = sqlite3VdbeMakeLabel(v);
................................................................................
  3194   3171   
  3195   3172     regAddrA = ++pParse->nMem;
  3196   3173     regAddrB = ++pParse->nMem;
  3197   3174     regOutA = ++pParse->nMem;
  3198   3175     regOutB = ++pParse->nMem;
  3199   3176     sqlite3SelectDestInit(&destA, SRT_Coroutine, regAddrA);
  3200   3177     sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB);
         3178  +  explainComposite(pParse, p->op, 0);
         3179  +
  3201   3180   
  3202   3181     /* Generate a coroutine to evaluate the SELECT statement to the
  3203   3182     ** left of the compound operator - the "A" select.
  3204   3183     */
  3205   3184     addrSelectA = sqlite3VdbeCurrentAddr(v) + 1;
  3206   3185     addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrA, 0, addrSelectA);
  3207   3186     VdbeComment((v, "left SELECT"));
  3208   3187     pPrior->iLimit = regLimitA;
  3209         -  explainSetInteger(iSub1, pParse->iNextSelectId);
  3210   3188     sqlite3Select(pParse, pPrior, &destA);
  3211   3189     sqlite3VdbeEndCoroutine(v, regAddrA);
  3212   3190     sqlite3VdbeJumpHere(v, addr1);
  3213   3191   
  3214   3192     /* Generate a coroutine to evaluate the SELECT statement on 
  3215   3193     ** the right - the "B" select
  3216   3194     */
................................................................................
  3217   3195     addrSelectB = sqlite3VdbeCurrentAddr(v) + 1;
  3218   3196     addr1 = sqlite3VdbeAddOp3(v, OP_InitCoroutine, regAddrB, 0, addrSelectB);
  3219   3197     VdbeComment((v, "right SELECT"));
  3220   3198     savedLimit = p->iLimit;
  3221   3199     savedOffset = p->iOffset;
  3222   3200     p->iLimit = regLimitB;
  3223   3201     p->iOffset = 0;  
  3224         -  explainSetInteger(iSub2, pParse->iNextSelectId);
  3225   3202     sqlite3Select(pParse, p, &destB);
  3226   3203     p->iLimit = savedLimit;
  3227   3204     p->iOffset = savedOffset;
  3228   3205     sqlite3VdbeEndCoroutine(v, regAddrB);
  3229   3206   
  3230   3207     /* Generate a subroutine that outputs the current row of the A
  3231   3208     ** select as the next output row of the compound select.
................................................................................
  3329   3306       sqlite3SelectDelete(db, p->pPrior);
  3330   3307     }
  3331   3308     p->pPrior = pPrior;
  3332   3309     pPrior->pNext = p;
  3333   3310   
  3334   3311     /*** TBD:  Insert subroutine calls to close cursors on incomplete
  3335   3312     **** subqueries ****/
  3336         -  explainComposite(pParse, p->op, iSub1, iSub2, 0);
         3313  +  ExplainQueryPlanPop(pParse);
  3337   3314     return pParse->nErr!=0;
  3338   3315   }
  3339   3316   #endif
  3340   3317   
  3341   3318   #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
  3342   3319   
  3343   3320   /* An instance of the SubstContext object describes an substitution edit
................................................................................
  5117   5094   static void explainSimpleCount(
  5118   5095     Parse *pParse,                  /* Parse context */
  5119   5096     Table *pTab,                    /* Table being queried */
  5120   5097     Index *pIdx                     /* Index used to optimize scan, or NULL */
  5121   5098   ){
  5122   5099     if( pParse->explain==2 ){
  5123   5100       int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx)));
  5124         -    char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s%s%s",
         5101  +    sqlite3VdbeExplain(pParse, 0, "SCAN TABLE %s%s%s",
  5125   5102           pTab->zName,
  5126   5103           bCover ? " USING COVERING INDEX " : "",
  5127   5104           bCover ? pIdx->zName : ""
  5128   5105       );
  5129         -    sqlite3VdbeAddOp4(
  5130         -        pParse->pVdbe, OP_Explain, pParse->iSelectId, 0, 0, zEqp, P4_DYNAMIC
  5131         -    );
  5132   5106     }
  5133   5107   }
  5134   5108   #else
  5135   5109   # define explainSimpleCount(a,b,c)
  5136   5110   #endif
  5137   5111   
  5138   5112   /*
................................................................................
  5337   5311     SortCtx sSort;         /* Info on how to code the ORDER BY clause */
  5338   5312     AggInfo sAggInfo;      /* Information used by aggregate queries */
  5339   5313     int iEnd;              /* Address of the end of the query */
  5340   5314     sqlite3 *db;           /* The database connection */
  5341   5315     ExprList *pMinMaxOrderBy = 0;  /* Added ORDER BY for min/max queries */
  5342   5316     u8 minMaxFlag;                 /* Flag for min/max queries */
  5343   5317   
  5344         -#ifndef SQLITE_OMIT_EXPLAIN
  5345         -  int iRestoreSelectId = pParse->iSelectId;
  5346         -  pParse->iSelectId = pParse->iNextSelectId++;
  5347         -#endif
  5348         -
  5349   5318     db = pParse->db;
         5319  +  v = sqlite3GetVdbe(pParse);
  5350   5320     if( p==0 || db->mallocFailed || pParse->nErr ){
  5351   5321       return 1;
  5352   5322     }
  5353   5323     if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
  5354   5324     memset(&sAggInfo, 0, sizeof(sAggInfo));
  5355         -#if SELECTTRACE_ENABLED
  5356   5325   #ifndef SQLITE_OMIT_EXPLAIN
  5357         -  p->iSelectId = pParse->iSelectId;
         5326  +  if( p->iSelectId==0 && pParse->addrExplain ){
         5327  +    ExplainQueryPlan((pParse, 1, "SUBQUERY"));
         5328  +    p->iSelectId = pParse->addrExplain;
         5329  +  }
  5358   5330   #endif
  5359         -  SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->iSelectId));
         5331  +#if SELECTTRACE_ENABLED
         5332  +  SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain));
  5360   5333     if( sqlite3SelectTrace & 0x100 ){
  5361   5334       sqlite3TreeViewSelect(0, p, 0);
  5362   5335     }
  5363   5336   #endif
  5364   5337   
  5365   5338     assert( p->pOrderBy==0 || pDest->eDest!=SRT_DistFifo );
  5366   5339     assert( p->pOrderBy==0 || pDest->eDest!=SRT_Fifo );
................................................................................
  5389   5362   #if SELECTTRACE_ENABLED
  5390   5363     if( sqlite3SelectTrace & 0x104 ){
  5391   5364       SELECTTRACE(0x104,pParse,p, ("after name resolution:\n"));
  5392   5365       sqlite3TreeViewSelect(0, p, 0);
  5393   5366     }
  5394   5367   #endif
  5395   5368   
  5396         -  /* Get a pointer the VDBE under construction, allocating a new VDBE if one
  5397         -  ** does not already exist */
  5398         -  v = sqlite3GetVdbe(pParse);
  5399         -  if( v==0 ) goto select_end;
  5400   5369     if( pDest->eDest==SRT_Output ){
  5401   5370       generateColumnNames(pParse, p);
  5402   5371     }
  5403   5372   
  5404   5373     /* Try to various optimizations (flattening subqueries, and strength
  5405   5374     ** reduction of join operators) in the FROM clause up into the main query
  5406   5375     */
................................................................................
  5487   5456     /* Handle compound SELECT statements using the separate multiSelect()
  5488   5457     ** procedure.
  5489   5458     */
  5490   5459     if( p->pPrior ){
  5491   5460       rc = multiSelect(pParse, p, pDest);
  5492   5461   #if SELECTTRACE_ENABLED
  5493   5462       SELECTTRACE(0x1,pParse,p,("end compound-select processing\n"));
  5494         -    if( pParse->iSelectId==0 && (sqlite3SelectTrace & 0x2000)!=0 ){
         5463  +    if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
  5495   5464         sqlite3TreeViewSelect(0, p, 0);
  5496   5465       }
  5497   5466   #endif
  5498         -    explainSetInteger(pParse->iSelectId, iRestoreSelectId);
         5467  +    sqlite3VdbeExplainPop(pParse);
  5499   5468       return rc;
  5500   5469     }
  5501   5470   #endif
  5502   5471   
  5503   5472     /* For each term in the FROM clause, do two things:
  5504   5473     ** (1) Authorized unreferenced tables
  5505   5474     ** (2) Generate code for all sub-queries
................................................................................
  5603   5572         int addrTop = sqlite3VdbeCurrentAddr(v)+1;
  5604   5573        
  5605   5574         pItem->regReturn = ++pParse->nMem;
  5606   5575         sqlite3VdbeAddOp3(v, OP_InitCoroutine, pItem->regReturn, 0, addrTop);
  5607   5576         VdbeComment((v, "%s", pItem->pTab->zName));
  5608   5577         pItem->addrFillSub = addrTop;
  5609   5578         sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
  5610         -      explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
         5579  +      ExplainQueryPlan((pParse, 1, "CO-ROUTINE %p", pSub));
         5580  +      ExplainQueryPlanSetId(pParse, pSub);
  5611   5581         sqlite3Select(pParse, pSub, &dest);
  5612   5582         pItem->pTab->nRowLogEst = pSub->nSelectRow;
  5613   5583         pItem->fg.viaCoroutine = 1;
  5614   5584         pItem->regResult = dest.iSdst;
  5615   5585         sqlite3VdbeEndCoroutine(v, pItem->regReturn);
  5616   5586         sqlite3VdbeJumpHere(v, addrTop-1);
  5617   5587         sqlite3ClearTempRegCache(pParse);
................................................................................
  5638   5608           VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
  5639   5609         }else{
  5640   5610           VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
  5641   5611         }
  5642   5612         pPrior = isSelfJoinView(pTabList, pItem);
  5643   5613         if( pPrior ){
  5644   5614           sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
  5645         -        explainSetInteger(pItem->iSelectId, pPrior->iSelectId);
  5646   5615           assert( pPrior->pSelect!=0 );
  5647   5616           pSub->nSelectRow = pPrior->pSelect->nSelectRow;
  5648   5617         }else{
  5649   5618           sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
  5650         -        explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
         5619  +        ExplainQueryPlan((pParse, 1, "MATERIALIZE %p", pSub));
         5620  +        ExplainQueryPlanSetId(pParse,pSub);
  5651   5621           sqlite3Select(pParse, pSub, &dest);
  5652   5622         }
  5653   5623         pItem->pTab->nRowLogEst = pSub->nSelectRow;
  5654   5624         if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
  5655   5625         retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
  5656   5626         VdbeComment((v, "end %s", pItem->pTab->zName));
  5657   5627         sqlite3VdbeChangeP1(v, topAddr, retAddr);
................................................................................
  6281   6251     */
  6282   6252   select_end:
  6283   6253     sqlite3ExprListDelete(db, pMinMaxOrderBy);
  6284   6254     sqlite3DbFree(db, sAggInfo.aCol);
  6285   6255     sqlite3DbFree(db, sAggInfo.aFunc);
  6286   6256   #if SELECTTRACE_ENABLED
  6287   6257     SELECTTRACE(0x1,pParse,p,("end processing\n"));
  6288         -  if( pParse->iSelectId==0 && (sqlite3SelectTrace & 0x2000)!=0 ){
         6258  +  if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
  6289   6259       sqlite3TreeViewSelect(0, p, 0);
  6290   6260     }
  6291   6261   #endif
  6292         -  explainSetInteger(pParse->iSelectId, iRestoreSelectId);
         6262  +  ExplainQueryPlanPop(pParse);
  6293   6263     return rc;
  6294   6264   }

Changes to src/shell.c.in.

   977    977     sqlite3expert *pExpert;
   978    978     int bVerbose;
   979    979   };
   980    980   
   981    981   /* A single line in the EQP output */
   982    982   typedef struct EQPGraphRow EQPGraphRow;
   983    983   struct EQPGraphRow {
   984         -  int iSelectId;        /* The SelectID for this row */
          984  +  int iEqpId;           /* ID for this row */
          985  +  int iParentId;        /* ID of the parent row */
   985    986     EQPGraphRow *pNext;   /* Next row in sequence */
   986    987     char zText[1];        /* Text to display for this row */
   987    988   };
   988    989   
   989    990   /* All EQP output is collected into an instance of the following */
   990    991   typedef struct EQPGraph EQPGraph;
   991    992   struct EQPGraph {
................................................................................
   999   1000   ** instance of the following structure.
  1000   1001   */
  1001   1002   typedef struct ShellState ShellState;
  1002   1003   struct ShellState {
  1003   1004     sqlite3 *db;           /* The database */
  1004   1005     u8 autoExplain;        /* Automatically turn on .explain mode */
  1005   1006     u8 autoEQP;            /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */
         1007  +  u8 autoEQPtest;        /* autoEQP is in test mode */
  1006   1008     u8 statsOn;            /* True to display memory stats before each finalize */
  1007   1009     u8 scanstatsOn;        /* True to display scan stats before each finalize */
  1008   1010     u8 openMode;           /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
  1009   1011     u8 doXdgOpen;          /* Invoke start/open/xdg-open in output_reset() */
  1010   1012     u8 nEqpLevel;          /* Depth of the EQP output graph */
  1011   1013     unsigned mEqpLines;    /* Mask of veritical lines in the EQP output graph */
  1012   1014     int outCount;          /* Revert to stdout when reaching zero */
................................................................................
  1049   1051   #endif
  1050   1052     ExpertInfo expert;        /* Valid if previous command was ".expert OPT..." */
  1051   1053   };
  1052   1054   
  1053   1055   
  1054   1056   /* Allowed values for ShellState.autoEQP
  1055   1057   */
  1056         -#define AUTOEQP_off      0
  1057         -#define AUTOEQP_on       1
  1058         -#define AUTOEQP_trigger  2
  1059         -#define AUTOEQP_full     3
         1058  +#define AUTOEQP_off      0           /* Automatic EXPLAIN QUERY PLAN is off */
         1059  +#define AUTOEQP_on       1           /* Automatic EQP is on */
         1060  +#define AUTOEQP_trigger  2           /* On and also show plans for triggers */
         1061  +#define AUTOEQP_full     3           /* Show full EXPLAIN */
  1060   1062   
  1061   1063   /* Allowed values for ShellState.openMode
  1062   1064   */
  1063   1065   #define SHELL_OPEN_UNSPEC     0      /* No open-mode specified */
  1064   1066   #define SHELL_OPEN_NORMAL     1      /* Normal database file */
  1065   1067   #define SHELL_OPEN_APPENDVFS  2      /* Use appendvfs */
  1066   1068   #define SHELL_OPEN_ZIPFILE    3      /* Use the zipfile virtual table */
................................................................................
  1663   1665     }
  1664   1666     return 1;
  1665   1667   }
  1666   1668   
  1667   1669   /*
  1668   1670   ** Add a new entry to the EXPLAIN QUERY PLAN data
  1669   1671   */
  1670         -static void eqp_append(ShellState *p, int iSelectId, const char *zText){
         1672  +static void eqp_append(ShellState *p, int iEqpId, int p2, const char *zText){
  1671   1673     EQPGraphRow *pNew;
  1672   1674     int nText = strlen30(zText);
         1675  +  if( p->autoEQPtest ){
         1676  +    utf8_printf(p->out, "%d,%d,%s\n", iEqpId, p2, zText);
         1677  +  }
  1673   1678     pNew = sqlite3_malloc64( sizeof(*pNew) + nText );
  1674   1679     if( pNew==0 ) shell_out_of_memory();
  1675         -  pNew->iSelectId = iSelectId;
         1680  +  pNew->iEqpId = iEqpId;
         1681  +  pNew->iParentId = p2;
  1676   1682     memcpy(pNew->zText, zText, nText+1);
  1677   1683     pNew->pNext = 0;
  1678   1684     if( p->sGraph.pLast ){
  1679   1685       p->sGraph.pLast->pNext = pNew;
  1680   1686     }else{
  1681   1687       p->sGraph.pRow = pNew;
  1682   1688     }
................................................................................
  1692   1698     for(pRow = p->sGraph.pRow; pRow; pRow = pNext){
  1693   1699       pNext = pRow->pNext;
  1694   1700       sqlite3_free(pRow);
  1695   1701     }
  1696   1702     memset(&p->sGraph, 0, sizeof(p->sGraph));
  1697   1703   }
  1698   1704   
  1699         -/* Return the next EXPLAIN QUERY PLAN line with iSelectId that occurs after
         1705  +/* Return the next EXPLAIN QUERY PLAN line with iEqpId that occurs after
  1700   1706   ** pOld, or return the first such line if pOld is NULL
  1701   1707   */
  1702         -static EQPGraphRow *eqp_next_row(ShellState *p, int iSelectId, EQPGraphRow *pOld){
         1708  +static EQPGraphRow *eqp_next_row(ShellState *p, int iEqpId, EQPGraphRow *pOld){
  1703   1709     EQPGraphRow *pRow = pOld ? pOld->pNext : p->sGraph.pRow;
  1704         -  while( pRow && pRow->iSelectId!=iSelectId ) pRow = pRow->pNext;
         1710  +  while( pRow && pRow->iParentId!=iEqpId ) pRow = pRow->pNext;
  1705   1711     return pRow;
  1706   1712   }
  1707   1713   
  1708         -/* Render a single level of the graph shell having iSelectId.  Called
         1714  +/* Render a single level of the graph that has iEqpId as its parent.  Called
  1709   1715   ** recursively to render sublevels.
  1710   1716   */
  1711         -static void eqp_render_level(ShellState *p, int iSelectId){
         1717  +static void eqp_render_level(ShellState *p, int iEqpId){
  1712   1718     EQPGraphRow *pRow, *pNext;
  1713         -  int i;
  1714   1719     int n = strlen30(p->sGraph.zPrefix);
  1715   1720     char *z;
  1716         -  for(pRow = eqp_next_row(p, iSelectId, 0); pRow; pRow = pNext){
  1717         -    pNext = eqp_next_row(p, iSelectId, pRow);
         1721  +  for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
         1722  +    pNext = eqp_next_row(p, iEqpId, pRow);
  1718   1723       z = pRow->zText;
  1719   1724       utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, pNext ? "|--" : "`--", z);
  1720         -    if( n<sizeof(p->sGraph.zPrefix)-7 && (z = strstr(z, " SUBQUER"))!=0 ){
         1725  +    if( n<sizeof(p->sGraph.zPrefix)-7 ){
  1721   1726         memcpy(&p->sGraph.zPrefix[n], pNext ? "|  " : "   ", 4);
  1722         -      if( strncmp(z, " SUBQUERY ", 9)==0 && (i = atoi(z+10))>iSelectId ){
  1723         -        eqp_render_level(p, i);
  1724         -      }else if( strncmp(z, " SUBQUERIES ", 12)==0 ){
  1725         -        i = atoi(z+12);
  1726         -        if( i>iSelectId ){
  1727         -          utf8_printf(p->out, "%s|--SUBQUERY %d\n", p->sGraph.zPrefix, i);
  1728         -          memcpy(&p->sGraph.zPrefix[n+3],"|  ",4);
  1729         -          eqp_render_level(p, i);
  1730         -        }
  1731         -        z = strstr(z, " AND ");
  1732         -        if( z && (i = atoi(z+5))>iSelectId ){
  1733         -          p->sGraph.zPrefix[n+3] = 0;
  1734         -          utf8_printf(p->out, "%s`--SUBQUERY %d\n", p->sGraph.zPrefix, i);
  1735         -          memcpy(&p->sGraph.zPrefix[n+3],"   ",4);
  1736         -          eqp_render_level(p, i);
  1737         -        }
  1738         -      }
         1727  +      eqp_render_level(p, pRow->iEqpId);
  1739   1728         p->sGraph.zPrefix[n] = 0;
  1740   1729       }
  1741   1730     }
  1742   1731   }
  1743   1732   
  1744   1733   /*
  1745   1734   ** Display and reset the EXPLAIN QUERY PLAN data
................................................................................
  2110   2099           if( i>0 ) utf8_printf(p->out, "%s", p->colSeparator);
  2111   2100           utf8_printf(p->out,"%s",azArg[i] ? azArg[i] : p->nullValue);
  2112   2101         }
  2113   2102         utf8_printf(p->out, "%s", p->rowSeparator);
  2114   2103         break;
  2115   2104       }
  2116   2105       case MODE_EQP: {
  2117         -      eqp_append(p, atoi(azArg[0]), azArg[3]);
         2106  +      eqp_append(p, atoi(azArg[0]), atoi(azArg[1]), azArg[3]);
  2118   2107         break;
  2119   2108       }
  2120   2109     }
  2121   2110     return 0;
  2122   2111   }
  2123   2112   
  2124   2113   /*
................................................................................
  2952   2941             sqlite3_db_config(db, SQLITE_DBCONFIG_TRIGGER_EQP, 1, 0);
  2953   2942           }
  2954   2943           zEQP = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zStmtSql);
  2955   2944           rc = sqlite3_prepare_v2(db, zEQP, -1, &pExplain, 0);
  2956   2945           if( rc==SQLITE_OK ){
  2957   2946             while( sqlite3_step(pExplain)==SQLITE_ROW ){
  2958   2947               const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
  2959         -            int iSelectId = sqlite3_column_int(pExplain, 0);
         2948  +            int iEqpId = sqlite3_column_int(pExplain, 0);
         2949  +            int iParentId = sqlite3_column_int(pExplain, 1);
  2960   2950               if( zEQPLine[0]=='-' ) eqp_render(pArg);
  2961         -            eqp_append(pArg, iSelectId, zEQPLine);
         2951  +            eqp_append(pArg, iEqpId, iParentId, zEQPLine);
  2962   2952             }
  2963   2953             eqp_render(pArg);
  2964   2954           }
  2965   2955           sqlite3_finalize(pExplain);
  2966   2956           sqlite3_free(zEQP);
  2967   2957           if( pArg->autoEQP>=AUTOEQP_full ){
  2968   2958             /* Also do an EXPLAIN for ".eqp full" mode */
................................................................................
  5910   5900         raw_printf(stderr, "Usage: .echo on|off\n");
  5911   5901         rc = 1;
  5912   5902       }
  5913   5903     }else
  5914   5904   
  5915   5905     if( c=='e' && strncmp(azArg[0], "eqp", n)==0 ){
  5916   5906       if( nArg==2 ){
         5907  +      p->autoEQPtest = 0;
  5917   5908         if( strcmp(azArg[1],"full")==0 ){
  5918   5909           p->autoEQP = AUTOEQP_full;
  5919   5910         }else if( strcmp(azArg[1],"trigger")==0 ){
  5920   5911           p->autoEQP = AUTOEQP_trigger;
         5912  +      }else if( strcmp(azArg[1],"test")==0 ){
         5913  +        p->autoEQP = AUTOEQP_on;
         5914  +        p->autoEQPtest = 1;
  5921   5915         }else{
  5922   5916           p->autoEQP = (u8)booleanValue(azArg[1]);
  5923   5917         }
  5924   5918       }else{
  5925   5919         raw_printf(stderr, "Usage: .eqp off|on|trigger|full\n");
  5926   5920         rc = 1;
  5927   5921       }

Changes to src/sqliteInt.h.

  2605   2605         unsigned notIndexed :1;    /* True if there is a NOT INDEXED clause */
  2606   2606         unsigned isIndexedBy :1;   /* True if there is an INDEXED BY clause */
  2607   2607         unsigned isTabFunc :1;     /* True if table-valued-function syntax */
  2608   2608         unsigned isCorrelated :1;  /* True if sub-query is correlated */
  2609   2609         unsigned viaCoroutine :1;  /* Implemented as a co-routine */
  2610   2610         unsigned isRecursive :1;   /* True for recursive reference in WITH */
  2611   2611       } fg;
  2612         -#ifndef SQLITE_OMIT_EXPLAIN
  2613         -    u8 iSelectId;     /* If pSelect!=0, the id of the sub-select in EQP */
  2614         -#endif
  2615   2612       int iCursor;      /* The VDBE cursor number used to access this table */
  2616   2613       Expr *pOn;        /* The ON clause of a join */
  2617   2614       IdList *pUsing;   /* The USING clause of a join */
  2618   2615       Bitmask colUsed;  /* Bit N (1<<N) set if column N of pTab is used */
  2619   2616       union {
  2620   2617         char *zIndexedBy;    /* Identifier from "INDEXED BY <zIndex>" clause */
  2621   2618         ExprList *pFuncArg;  /* Arguments to table-valued-function */
................................................................................
  2779   2776     ExprList *pEList;      /* The fields of the result */
  2780   2777     u8 op;                 /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
  2781   2778     LogEst nSelectRow;     /* Estimated number of result rows */
  2782   2779     u32 selFlags;          /* Various SF_* values */
  2783   2780     int iLimit, iOffset;   /* Memory registers holding LIMIT & OFFSET counters */
  2784   2781   #if SELECTTRACE_ENABLED
  2785   2782     char zSelName[12];     /* Symbolic name of this SELECT use for debugging */
         2783  +#endif
         2784  +#if defined(SQLITETRACE_ENABLED) || !defined(SQLITE_OMIT_EXPLAIN)
  2786   2785     u32 iSelectId;         /* EXPLAIN QUERY PLAN select ID */
  2787   2786   #endif
  2788   2787     int addrOpenEphm[2];   /* OP_OpenEphem opcodes related to this select */
  2789   2788     SrcList *pSrc;         /* The FROM clause */
  2790   2789     Expr *pWhere;          /* The WHERE clause */
  2791   2790     ExprList *pGroupBy;    /* The GROUP BY clause */
  2792   2791     Expr *pHaving;         /* The HAVING clause */
................................................................................
  3091   3090     u8 explain;               /* True if the EXPLAIN flag is found on the query */
  3092   3091   #ifndef SQLITE_OMIT_VIRTUALTABLE
  3093   3092     u8 declareVtab;           /* True if inside sqlite3_declare_vtab() */
  3094   3093     int nVtabLock;            /* Number of virtual tables to lock */
  3095   3094   #endif
  3096   3095     int nHeight;              /* Expression tree height of current sub-select */
  3097   3096   #ifndef SQLITE_OMIT_EXPLAIN
  3098         -  int iSelectId;            /* ID of current select for EXPLAIN output */
  3099         -  int iNextSelectId;        /* Next available select ID for EXPLAIN output */
         3097  +  int addrExplain;          /* Address of current OP_Explain opcode */
  3100   3098   #endif
  3101   3099     VList *pVList;            /* Mapping between variable names and numbers */
  3102   3100     Vdbe *pReprepare;         /* VM being reprepared (sqlite3Reprepare()) */
  3103   3101     const char *zTail;        /* All SQL text past the last semicolon parsed */
  3104   3102     Table *pNewTable;         /* A table being constructed by CREATE TABLE */
  3105   3103     Trigger *pNewTrigger;     /* Trigger under construct by a CREATE TRIGGER */
  3106   3104     const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */

Changes to src/vdbe.h.

   193    193   #if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
   194    194     void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N);
   195    195     void sqlite3VdbeVerifyNoResultRow(Vdbe *p);
   196    196   #else
   197    197   # define sqlite3VdbeVerifyNoMallocRequired(A,B)
   198    198   # define sqlite3VdbeVerifyNoResultRow(A)
   199    199   #endif
   200         -VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno);
          200  +VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno);
          201  +#ifndef SQLITE_OMIT_EXPLAIN
          202  +  void sqlite3VdbeExplain(Parse*,u8,const char*,...);
          203  +  void sqlite3VdbeExplainPop(Parse*);
          204  +  int sqlite3VdbeExplainParent(Parse*);
          205  +# define ExplainQueryPlan(P)        sqlite3VdbeExplain P
          206  +# define ExplainQueryPlanPop(P)     sqlite3VdbeExplainPop(P)
          207  +# define ExplainQueryPlanParent(P)  sqlite3VdbeExplainParent(P)
          208  +# define ExplainQueryPlanSetId(P,S) (S)->iSelectId=(P)->addrExplain
          209  +#else
          210  +# define ExplainQueryPlan(P)
          211  +# define ExplainQueryPlanPop(P)
          212  +# define ExplainQueryPlanParent(P) 0
          213  +# define ExplainQueryPlanSetId(P,S)
          214  +#endif
   201    215   void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
   202    216   void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8);
   203    217   void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
   204    218   void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
   205    219   void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
   206    220   void sqlite3VdbeChangeP5(Vdbe*, u16 P5);
   207    221   void sqlite3VdbeJumpHere(Vdbe*, int addr);

Changes to src/vdbeaux.c.

   299    299     int p4type          /* P4 operand type */
   300    300   ){
   301    301     char *p4copy = sqlite3DbMallocRawNN(sqlite3VdbeDb(p), 8);
   302    302     if( p4copy ) memcpy(p4copy, zP4, 8);
   303    303     return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type);
   304    304   }
   305    305   
          306  +#ifndef SQLITE_OMIT_EXPLAIN
          307  +/*
          308  +** Return the address of the current EXPLAIN QUERY PLAN baseline.
          309  +** 0 means "none".
          310  +*/
          311  +int sqlite3VdbeExplainParent(Parse *pParse){
          312  +  VdbeOp *pOp;
          313  +  if( pParse->addrExplain==0 ) return 0;
          314  +  pOp = sqlite3VdbeGetOp(pParse->pVdbe, pParse->addrExplain);
          315  +  return pOp->p2;
          316  +}
          317  +
          318  +/*
          319  +** Add a new OP_Explain opcode.
          320  +**
          321  +** If the bPush flag is true, then make this opcode the parent for
          322  +** subsequent Explains until sqlite3VdbeExplainPop() is called.
          323  +*/
          324  +void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){
          325  +  if( pParse->explain==2 ){
          326  +    char *zMsg;
          327  +    Vdbe *v = pParse->pVdbe;
          328  +    va_list ap;
          329  +    int iThis;
          330  +    va_start(ap, zFmt);
          331  +    zMsg = sqlite3VMPrintf(pParse->db, zFmt, ap);
          332  +    va_end(ap);
          333  +    v = pParse->pVdbe;
          334  +    iThis = v->nOp;
          335  +    sqlite3VdbeAddOp4(v, OP_Explain, iThis, pParse->addrExplain, 0,
          336  +                      zMsg, P4_DYNAMIC);
          337  +    if( bPush) pParse->addrExplain = iThis;
          338  +  }
          339  +}
          340  +
          341  +/*
          342  +** Pop the EXPLAIN QUERY PLAN stack one level.
          343  +*/
          344  +void sqlite3VdbeExplainPop(Parse *pParse){
          345  +  pParse->addrExplain = sqlite3VdbeExplainParent(pParse);
          346  +}
          347  +#endif /* SQLITE_OMIT_EXPLAIN */
          348  +
   306    349   /*
   307    350   ** Add an OP_ParseSchema opcode.  This routine is broken out from
   308    351   ** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees
   309    352   ** as having been used.
   310    353   **
   311    354   ** The zWhere string must have been obtained from sqlite3_malloc().
   312    355   ** This routine will take ownership of the allocated memory.

Changes to src/wherecode.c.

   130    130   #if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS)
   131    131     if( sqlite3ParseToplevel(pParse)->explain==2 )
   132    132   #endif
   133    133     {
   134    134       struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
   135    135       Vdbe *v = pParse->pVdbe;      /* VM being constructed */
   136    136       sqlite3 *db = pParse->db;     /* Database handle */
   137         -    int iId = pParse->iSelectId;  /* Select id (left-most output column) */
   138    137       int isSearch;                 /* True for a SEARCH. False for SCAN. */
   139    138       WhereLoop *pLoop;             /* The controlling WhereLoop object */
   140    139       u32 flags;                    /* Flags that describe this loop */
   141    140       char *zMsg;                   /* Text to add to EQP output */
   142    141       StrAccum str;                 /* EQP output string */
   143    142       char zBuf[100];               /* Initial space for EQP output string */
   144    143   
................................................................................
   149    148       isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0
   150    149               || ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
   151    150               || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
   152    151   
   153    152       sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
   154    153       sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN");
   155    154       if( pItem->pSelect ){
   156         -      sqlite3XPrintf(&str, " SUBQUERY %d", pItem->iSelectId);
          155  +      sqlite3XPrintf(&str, " SUBQUERY %p", pItem->pSelect);
   157    156       }else{
   158    157         sqlite3XPrintf(&str, " TABLE %s", pItem->zName);
   159    158       }
   160    159   
   161    160       if( pItem->zAlias ){
   162    161         sqlite3XPrintf(&str, " AS %s", pItem->zAlias);
   163    162       }
................................................................................
   210    209       if( pLoop->nOut>=10 ){
   211    210         sqlite3XPrintf(&str, " (~%llu rows)", sqlite3LogEstToInt(pLoop->nOut));
   212    211       }else{
   213    212         sqlite3StrAccumAppend(&str, " (~1 row)", 9);
   214    213       }
   215    214   #endif
   216    215       zMsg = sqlite3StrAccumFinish(&str);
   217         -    ret = sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg,P4_DYNAMIC);
          216  +    ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
          217  +                            pParse->addrExplain, 0, zMsg,P4_DYNAMIC);
   218    218     }
   219    219     return ret;
   220    220   }
   221    221   #endif /* SQLITE_OMIT_EXPLAIN */
   222    222   
   223    223   #ifdef SQLITE_ENABLE_STMT_SCANSTATUS
   224    224   /*