/ Check-in [2fcac056]
Login

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

Overview
Comment:Merge EXPLAIN enhancements from trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | omit-rowid
Files: files | file ages | folders
SHA1: 2fcac056074f0a23884ab5425003a7ca1d35c2a8
User & Date: drh 2013-10-30 02:37:50
Context
2013-10-30
13:46
In the P4 column of the EXPLAIN listing, abbreviate "keyinfo" as just "k" and "BINARY" as just "B". check-in: 72d45eb7 user: drh tags: omit-rowid
02:37
Merge EXPLAIN enhancements from trunk. check-in: 2fcac056 user: drh tags: omit-rowid
02:28
Add the SQLITE_ENABLE_EXPLAIN_COMMENTS compile-time option to enable extra commentary in the EXPLAIN output. Formerly, this was only available with SQLITE_DEBUG. check-in: e1a89b56 user: drh tags: trunk
2013-10-29
20:47
Import the automatic comment generating changes from trunk. check-in: 8bb51da1 user: drh tags: omit-rowid
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to mkopcodec.awk.

    10     10   #
    11     11   BEGIN {
    12     12     print "/* Automatically generated.  Do not edit */"
    13     13     print "/* See the mkopcodec.awk script for details. */"
    14     14     printf "#if !defined(SQLITE_OMIT_EXPLAIN)"
    15     15     printf    " || defined(VDBE_PROFILE)"
    16     16     print     " || defined(SQLITE_DEBUG)"
    17         -  print "#if defined(SQLITE_DEBUG)"
           17  +  print "#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) || defined(SQLITE_DEBUG)"
    18     18     print "# define OpHelp(X) \"\\0\" X"
    19     19     print "#else"
    20     20     print "# define OpHelp(X)"
    21     21     print "#endif"
    22     22     print "const char *sqlite3OpcodeName(int i){"
    23     23     print " static const char *const azName[] = { \"?\","
    24     24     mx = 0

Changes to src/sqliteInt.h.

   213    213   #if !defined(NDEBUG) && !defined(SQLITE_DEBUG) 
   214    214   # define NDEBUG 1
   215    215   #endif
   216    216   #if defined(NDEBUG) && defined(SQLITE_DEBUG)
   217    217   # undef NDEBUG
   218    218   #endif
   219    219   
          220  +/*
          221  +** Enable SQLITE_ENABLE_EXPLAIN_COMMENTS if SQLITE_DEBUG is turned on.
          222  +*/
          223  +#if !defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) && defined(SQLITE_DEBUG)
          224  +# define SQLITE_ENABLE_EXPLAIN_COMMENTS 1
          225  +#endif
          226  +
   220    227   /*
   221    228   ** The testcase() macro is used to aid in coverage testing.  When 
   222    229   ** doing coverage testing, the condition inside the argument to
   223    230   ** testcase() must be evaluated both true and false in order to
   224    231   ** get full branch coverage.  The testcase() macro is inserted
   225    232   ** to help ensure adequate test coverage in places where simple
   226    233   ** condition/decision coverage is inadequate.  For example, testcase()

Changes to src/trigger.c.

   780    780         sqlite3VdbeAddOp0(v, OP_ResetCount);
   781    781       }
   782    782     }
   783    783   
   784    784     return 0;
   785    785   }
   786    786   
   787         -#ifdef SQLITE_DEBUG
          787  +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
   788    788   /*
   789    789   ** This function is used to add VdbeComment() annotations to a VDBE
   790    790   ** program. It is not used in production code, only for debugging.
   791    791   */
   792    792   static const char *onErrorText(int onError){
   793    793     switch( onError ){
   794    794       case OE_Abort:    return "abort";

Changes to src/vdbe.c.

  1031   1031     }
  1032   1032     sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static);
  1033   1033     UPDATE_MAX_BLOBSIZE(pOut);
  1034   1034     break;
  1035   1035   }
  1036   1036   
  1037   1037   /* Opcode: Move P1 P2 P3 * *
  1038         -** Synopsis:  r[P2]=r[P1] N=P3
         1038  +** Synopsis:  r[P2@P3]=r[P1@P3]
  1039   1039   **
  1040   1040   ** Move the values in register P1..P1+P3 over into
  1041   1041   ** registers P2..P2+P3.  Registers P1..P1+P3 are
  1042   1042   ** left holding a NULL.  It is an error for register ranges
  1043   1043   ** P1..P1+P3 and P2..P2+P3 to overlap.
  1044   1044   */
  1045   1045   case OP_Move: {
................................................................................
  1074   1074       pIn1++;
  1075   1075       pOut++;
  1076   1076     }
  1077   1077     break;
  1078   1078   }
  1079   1079   
  1080   1080   /* Opcode: Copy P1 P2 P3 * *
  1081         -** Synopsis: r[P2]=r[P1] N=P3
         1081  +** Synopsis: r[P2@P3]=r[P1@P3]
  1082   1082   **
  1083   1083   ** Make a copy of registers P1..P1+P3 into registers P2..P2+P3.
  1084   1084   **
  1085   1085   ** This instruction makes a deep copy of the value.  A duplicate
  1086   1086   ** is made of any string or blob constant.  See also OP_SCopy.
  1087   1087   */
  1088   1088   case OP_Copy: {
................................................................................
  1128   1128     if( pOut->pScopyFrom==0 ) pOut->pScopyFrom = pIn1;
  1129   1129   #endif
  1130   1130     REGISTER_TRACE(pOp->p2, pOut);
  1131   1131     break;
  1132   1132   }
  1133   1133   
  1134   1134   /* Opcode: ResultRow P1 P2 * * *
  1135         -** Synopsis:  output=r[P1].. columns=P1
         1135  +** Synopsis:  output=r[P1@P2]
  1136   1136   **
  1137   1137   ** The registers P1 through P1+P2-1 contain a single row of
  1138   1138   ** results. This opcode causes the sqlite3_step() call to terminate
  1139   1139   ** with an SQLITE_ROW return code and it sets up the sqlite3_stmt
  1140   1140   ** structure to provide access to the top P1 values as the result
  1141   1141   ** row.
  1142   1142   */
................................................................................
  1396   1396     if( pOp->p1 ){
  1397   1397       sqlite3VdbeMemSetInt64(&aMem[pOp->p1], 0);
  1398   1398     }
  1399   1399     break;
  1400   1400   }
  1401   1401   
  1402   1402   /* Opcode: Function P1 P2 P3 P4 P5
  1403         -** Synopsis: r[P3]=func(r[P2]..) N=P5
         1403  +** Synopsis: r[P3]=func(r[P2@P5])
  1404   1404   **
  1405   1405   ** Invoke a user function (P4 is a pointer to a Function structure that
  1406   1406   ** defines the function) with P5 arguments taken from register P2 and
  1407   1407   ** successors.  The result of the function is stored in register P3.
  1408   1408   ** Register P3 must not be one of the function inputs.
  1409   1409   **
  1410   1410   ** P1 is a 32-bit bitmask indicating whether or not each argument to the 
................................................................................
  2509   2509   op_column_out:
  2510   2510     UPDATE_MAX_BLOBSIZE(pDest);
  2511   2511     REGISTER_TRACE(pOp->p3, pDest);
  2512   2512     break;
  2513   2513   }
  2514   2514   
  2515   2515   /* Opcode: Affinity P1 P2 * P4 *
  2516         -** Synopsis: affinity(r[P1]) N=P2
         2516  +** Synopsis: affinity(r[P1@P2])
  2517   2517   **
  2518   2518   ** Apply affinities to a range of P2 registers starting with P1.
  2519   2519   **
  2520   2520   ** P4 is a string that is P2 characters long. The nth character of the
  2521   2521   ** string indicates the column affinity that should be used for the nth
  2522   2522   ** memory cell in the range.
  2523   2523   */
................................................................................
  2536   2536       applyAffinity(pIn1, cAff, encoding);
  2537   2537       pIn1++;
  2538   2538     }
  2539   2539     break;
  2540   2540   }
  2541   2541   
  2542   2542   /* Opcode: MakeRecord P1 P2 P3 P4 *
  2543         -** Synopsis: r[P3]=rec(r[P1]..) N=P2
         2543  +** Synopsis: r[P3]=mkrec(r[P1@P2])
  2544   2544   **
  2545   2545   ** Convert P2 registers beginning with P1 into the [record format]
  2546   2546   ** use as a data record in a database table or as a key
  2547   2547   ** in an index.  The OP_Column opcode can decode the record later.
  2548   2548   **
  2549   2549   ** P4 may be a string that is P2 characters long.  The nth character of the
  2550   2550   ** string indicates the column affinity that should be used for the nth
................................................................................
  3375   3375     pCx->pKeyInfo->enc = ENC(p->db);
  3376   3376     pCx->isSorter = 1;
  3377   3377     rc = sqlite3VdbeSorterInit(db, pCx);
  3378   3378     break;
  3379   3379   }
  3380   3380   
  3381   3381   /* Opcode: OpenPseudo P1 P2 P3 * P5
  3382         -** Synopsis: content in r[P2].. N=P3
         3382  +** Synopsis: content in r[P2@P3]
  3383   3383   **
  3384   3384   ** Open a new cursor that points to a fake table that contains a single
  3385   3385   ** row of data.  The content of that one row in the content of memory
  3386   3386   ** register P2 when P5==0.  In other words, cursor P1 becomes an alias for the 
  3387   3387   ** MEM_Blob content contained in register P2.  When P5==1, then the
  3388   3388   ** row is represented by P3 consecutive registers beginning with P2.
  3389   3389   **
................................................................................
  3418   3418     assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  3419   3419     sqlite3VdbeFreeCursor(p, p->apCsr[pOp->p1]);
  3420   3420     p->apCsr[pOp->p1] = 0;
  3421   3421     break;
  3422   3422   }
  3423   3423   
  3424   3424   /* Opcode: SeekGe P1 P2 P3 P4 *
  3425         -** Synopsis: key=r[P3].. N=P4
         3425  +** Synopsis: key=r[P3@P4]
  3426   3426   **
  3427   3427   ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), 
  3428   3428   ** use the value in register P3 as the key.  If cursor P1 refers 
  3429   3429   ** to an SQL index, then P3 is the first in an array of P4 registers 
  3430   3430   ** that are used as an unpacked index key. 
  3431   3431   **
  3432   3432   ** Reposition cursor P1 so that  it points to the smallest entry that 
  3433   3433   ** is greater than or equal to the key value. If there are no records 
  3434   3434   ** greater than or equal to the key and P2 is not zero, then jump to P2.
  3435   3435   **
  3436   3436   ** See also: Found, NotFound, Distinct, SeekLt, SeekGt, SeekLe
  3437   3437   */
  3438   3438   /* Opcode: SeekGt P1 P2 P3 P4 *
  3439         -** Synopsis: key=r[P3].. N=P4
         3439  +** Synopsis: key=r[P3@P4]
  3440   3440   **
  3441   3441   ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), 
  3442   3442   ** use the value in register P3 as a key. If cursor P1 refers 
  3443   3443   ** to an SQL index, then P3 is the first in an array of P4 registers 
  3444   3444   ** that are used as an unpacked index key. 
  3445   3445   **
  3446   3446   ** Reposition cursor P1 so that  it points to the smallest entry that 
  3447   3447   ** is greater than the key value. If there are no records greater than 
  3448   3448   ** the key and P2 is not zero, then jump to P2.
  3449   3449   **
  3450   3450   ** See also: Found, NotFound, Distinct, SeekLt, SeekGe, SeekLe
  3451   3451   */
  3452   3452   /* Opcode: SeekLt P1 P2 P3 P4 * 
  3453         -** Synopsis: key=r[P3].. N=P4
         3453  +** Synopsis: key=r[P3@P4]
  3454   3454   **
  3455   3455   ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), 
  3456   3456   ** use the value in register P3 as a key. If cursor P1 refers 
  3457   3457   ** to an SQL index, then P3 is the first in an array of P4 registers 
  3458   3458   ** that are used as an unpacked index key. 
  3459   3459   **
  3460   3460   ** Reposition cursor P1 so that  it points to the largest entry that 
  3461   3461   ** is less than the key value. If there are no records less than 
  3462   3462   ** the key and P2 is not zero, then jump to P2.
  3463   3463   **
  3464   3464   ** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLe
  3465   3465   */
  3466   3466   /* Opcode: SeekLe P1 P2 P3 P4 *
  3467         -** Synopsis: key=r[P3].. N=P4
         3467  +** Synopsis: key=r[P3@P4]
  3468   3468   **
  3469   3469   ** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), 
  3470   3470   ** use the value in register P3 as a key. If cursor P1 refers 
  3471   3471   ** to an SQL index, then P3 is the first in an array of P4 registers 
  3472   3472   ** that are used as an unpacked index key. 
  3473   3473   **
  3474   3474   ** Reposition cursor P1 so that it points to the largest entry that 
................................................................................
  3654   3654       pC->deferredMoveto = 1;
  3655   3655     }
  3656   3656     break;
  3657   3657   }
  3658   3658     
  3659   3659   
  3660   3660   /* Opcode: Found P1 P2 P3 P4 *
  3661         -** Synopsis: key=r[P3].. N=P4
         3661  +** Synopsis: key=r[P3@P4]
  3662   3662   **
  3663   3663   ** If P4==0 then register P3 holds a blob constructed by MakeRecord.  If
  3664   3664   ** P4>0 then register P3 is the first of P4 registers that form an unpacked
  3665   3665   ** record.
  3666   3666   **
  3667   3667   ** Cursor P1 is on an index btree.  If the record identified by P3 and P4
  3668   3668   ** is a prefix of any entry in P1 then a jump is made to P2 and
  3669   3669   ** P1 is left pointing at the matching entry.
  3670   3670   **
  3671   3671   ** See also: NotFound, NoConflict, NotExists. SeekGe
  3672   3672   */
  3673   3673   /* Opcode: NotFound P1 P2 P3 P4 *
  3674         -** Synopsis: key=r[P3] N=P4
         3674  +** Synopsis: key=r[P3@P4]
  3675   3675   **
  3676   3676   ** If P4==0 then register P3 holds a blob constructed by MakeRecord.  If
  3677   3677   ** P4>0 then register P3 is the first of P4 registers that form an unpacked
  3678   3678   ** record.
  3679   3679   ** 
  3680   3680   ** Cursor P1 is on an index btree.  If the record identified by P3 and P4
  3681   3681   ** is not the prefix of any entry in P1 then a jump is made to P2.  If P1 
................................................................................
  3682   3682   ** does contain an entry whose prefix matches the P3/P4 record then control
  3683   3683   ** falls through to the next instruction and P1 is left pointing at the
  3684   3684   ** matching entry.
  3685   3685   **
  3686   3686   ** See also: Found, NotExists, NoConflict
  3687   3687   */
  3688   3688   /* Opcode: NoConflict P1 P2 P3 P4 *
         3689  +** Synopsis: key=r[P3@P4]
  3689   3690   **
  3690   3691   ** If P4==0 then register P3 holds a blob constructed by MakeRecord.  If
  3691   3692   ** P4>0 then register P3 is the first of P4 registers that form an unpacked
  3692   3693   ** record.
  3693   3694   ** 
  3694   3695   ** Cursor P1 is on an index btree.  If the record identified by P3 and P4
  3695   3696   ** contains any NULL value, jump immediately to P2.  If all terms of the
................................................................................
  4581   4582         }
  4582   4583       }
  4583   4584     }
  4584   4585     break;
  4585   4586   }
  4586   4587   
  4587   4588   /* Opcode: IdxDelete P1 P2 P3 * *
  4588         -** Synopsis: key=r[P2]..
         4589  +** Synopsis: key=r[P2@P3]
  4589   4590   **
  4590   4591   ** The content of P3 registers starting at register P2 form
  4591   4592   ** an unpacked index key. This opcode removes that entry from the 
  4592   4593   ** index opened by cursor P1.
  4593   4594   */
  4594   4595   case OP_IdxDelete: {
  4595   4596     VdbeCursor *pC;
................................................................................
  4654   4655         pOut->flags = MEM_Int;
  4655   4656       }
  4656   4657     }
  4657   4658     break;
  4658   4659   }
  4659   4660   
  4660   4661   /* Opcode: IdxGE P1 P2 P3 P4 P5
  4661         -** Synopsis: key=r[P3] N=P4
         4662  +** Synopsis: key=r[P3@P4]
  4662   4663   **
  4663   4664   ** The P4 register values beginning with P3 form an unpacked index 
  4664   4665   ** key that omits the ROWID.  Compare this key value against the index 
  4665   4666   ** that P1 is currently pointing to, ignoring the ROWID on the P1 index.
  4666   4667   **
  4667   4668   ** If the P1 index entry is greater than or equal to the key value
  4668   4669   ** then jump to P2.  Otherwise fall through to the next instruction.
................................................................................
  4669   4670   **
  4670   4671   ** If P5 is non-zero then the key value is increased by an epsilon 
  4671   4672   ** prior to the comparison.  This make the opcode work like IdxGT except
  4672   4673   ** that if the key from register P3 is a prefix of the key in the cursor,
  4673   4674   ** the result is false whereas it would be true with IdxGT.
  4674   4675   */
  4675   4676   /* Opcode: IdxLT P1 P2 P3 P4 P5
  4676         -** Synopsis: key=r[P3] N=P4
         4677  +** Synopsis: key=r[P3@P4]
  4677   4678   **
  4678   4679   ** The P4 register values beginning with P3 form an unpacked index 
  4679   4680   ** key that omits the ROWID.  Compare this key value against the index 
  4680   4681   ** that P1 is currently pointing to, ignoring the ROWID on the P1 index.
  4681   4682   **
  4682   4683   ** If the P1 index entry is less than the key value then jump to P2.
  4683   4684   ** Otherwise fall through to the next instruction.
................................................................................
  5412   5413     if( pIn1->u.i==0 ){
  5413   5414        pc = pOp->p2 - 1;
  5414   5415     }
  5415   5416     break;
  5416   5417   }
  5417   5418   
  5418   5419   /* Opcode: AggStep * P2 P3 P4 P5
  5419         -** Synopsis: accum=r[P3] step(r[P2]..) N=P5
         5420  +** Synopsis: accum=r[P3] step(r[P2@P5])
  5420   5421   **
  5421   5422   ** Execute the step function for an aggregate.  The
  5422   5423   ** function has P5 arguments.   P4 is a pointer to the FuncDef
  5423   5424   ** structure that specifies the function.  Use register
  5424   5425   ** P3 as the accumulator.
  5425   5426   **
  5426   5427   ** The P5 arguments are taken from register P2 and its
................................................................................
  6030   6031     }
  6031   6032     break;
  6032   6033   }
  6033   6034   #endif
  6034   6035   
  6035   6036   #ifndef SQLITE_OMIT_VIRTUALTABLE
  6036   6037   /* Opcode: VUpdate P1 P2 P3 P4 *
  6037         -** Synopsis: data=r[P3] N=P2
         6038  +** Synopsis: data=r[P3@P2]
  6038   6039   **
  6039   6040   ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
  6040   6041   ** This opcode invokes the corresponding xUpdate method. P2 values
  6041   6042   ** are contiguous memory cells starting at P3 to pass to the xUpdate 
  6042   6043   ** invocation. The value in register (P3+P2-1) corresponds to the 
  6043   6044   ** p2th element of the argv array passed to xUpdate.
  6044   6045   **

Changes to src/vdbe.h.

    57     57       Mem *pMem;             /* Used when p4type is P4_MEM */
    58     58       VTable *pVtab;         /* Used when p4type is P4_VTAB */
    59     59       KeyInfo *pKeyInfo;     /* Used when p4type is P4_KEYINFO */
    60     60       int *ai;               /* Used when p4type is P4_INTARRAY */
    61     61       SubProgram *pProgram;  /* Used when p4type is P4_SUBPROGRAM */
    62     62       int (*xAdvance)(BtCursor *, int *);
    63     63     } p4;
    64         -#ifdef SQLITE_DEBUG
           64  +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
    65     65     char *zComment;          /* Comment to improve readability */
    66     66   #endif
    67     67   #ifdef VDBE_PROFILE
    68     68     int cnt;                 /* Number of times this instruction was executed */
    69     69     u64 cycles;              /* Total time spent executing this instruction */
    70     70   #endif
    71     71   };
................................................................................
   215    215   UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
   216    216   
   217    217   #ifndef SQLITE_OMIT_TRIGGER
   218    218   void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
   219    219   #endif
   220    220   
   221    221   
   222         -#ifndef NDEBUG
          222  +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
   223    223     void sqlite3VdbeComment(Vdbe*, const char*, ...);
   224    224   # define VdbeComment(X)  sqlite3VdbeComment X
   225    225     void sqlite3VdbeNoopComment(Vdbe*, const char*, ...);
   226    226   # define VdbeNoopComment(X)  sqlite3VdbeNoopComment X
   227    227   #else
   228    228   # define VdbeComment(X)
   229    229   # define VdbeNoopComment(X)
   230    230   #endif
   231    231   
   232    232   #endif

Changes to src/vdbeaux.c.

   140    140     pOp->opcode = (u8)op;
   141    141     pOp->p5 = 0;
   142    142     pOp->p1 = p1;
   143    143     pOp->p2 = p2;
   144    144     pOp->p3 = p3;
   145    145     pOp->p4.p = 0;
   146    146     pOp->p4type = P4_NOTUSED;
   147         -#ifdef SQLITE_DEBUG
          147  +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
   148    148     pOp->zComment = 0;
          149  +#endif
          150  +#ifdef SQLITE_DEBUG
   149    151     if( p->db->flags & SQLITE_VdbeAddopTrace ){
   150    152       sqlite3VdbePrintOp(0, i, &p->aOp[i]);
   151    153     }
   152    154   #endif
   153    155   #ifdef VDBE_PROFILE
   154    156     pOp->cycles = 0;
   155    157     pOp->cnt = 0;
................................................................................
   528    530         }else{
   529    531           pOut->p2 = p2;
   530    532         }
   531    533         pOut->p3 = pIn->p3;
   532    534         pOut->p4type = P4_NOTUSED;
   533    535         pOut->p4.p = 0;
   534    536         pOut->p5 = 0;
   535         -#ifdef SQLITE_DEBUG
          537  +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
   536    538         pOut->zComment = 0;
          539  +#endif
          540  +#ifdef SQLITE_DEBUG
   537    541         if( p->db->flags & SQLITE_VdbeAddopTrace ){
   538    542           sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]);
   539    543         }
   540    544   #endif
   541    545       }
   542    546       p->nOp += nOp;
   543    547     }
................................................................................
   659    663   ** nOp entries. 
   660    664   */
   661    665   static void vdbeFreeOpArray(sqlite3 *db, Op *aOp, int nOp){
   662    666     if( aOp ){
   663    667       Op *pOp;
   664    668       for(pOp=aOp; pOp<&aOp[nOp]; pOp++){
   665    669         freeP4(db, pOp->p4type, pOp->p4.p);
   666         -#ifdef SQLITE_DEBUG
          670  +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
   667    671         sqlite3DbFree(db, pOp->zComment);
   668    672   #endif     
   669    673       }
   670    674     }
   671    675     sqlite3DbFree(db, aOp);
   672    676   }
   673    677   
................................................................................
   777    781     }else{
   778    782       if( n==0 ) n = sqlite3Strlen30(zP4);
   779    783       pOp->p4.z = sqlite3DbStrNDup(p->db, zP4, n);
   780    784       pOp->p4type = P4_DYNAMIC;
   781    785     }
   782    786   }
   783    787   
   784         -#ifndef NDEBUG
          788  +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
   785    789   /*
   786    790   ** Change the comment on the most recently coded instruction.  Or
   787    791   ** insert a No-op and add the comment to that new instruction.  This
   788    792   ** makes the code easier to read during debugging.  None of this happens
   789    793   ** in a production build.
   790    794   */
   791    795   static void vdbeVComment(Vdbe *p, const char *zFormat, va_list ap){
................................................................................
   852    856     if( p->db->mallocFailed ){
   853    857       return (VdbeOp*)&dummy;
   854    858     }else{
   855    859       return &p->aOp[addr];
   856    860     }
   857    861   }
   858    862   
   859         -#if defined(SQLITE_DEBUG)
          863  +#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS)
          864  +/*
          865  +** Return an integer value for one of the parameters to the opcode pOp
          866  +** determined by character c.
          867  +*/
          868  +static int translateP(char c, const Op *pOp){
          869  +  if( c=='1' ) return pOp->p1;
          870  +  if( c=='2' ) return pOp->p2;
          871  +  if( c=='3' ) return pOp->p3;
          872  +  if( c=='4' ) return pOp->p4.i;
          873  +  return pOp->p5;
          874  +}
          875  +
   860    876   /*
   861    877   ** Compute a string for the "comment" field of a VDBE opcode listing
   862    878   */
   863         -static int displayComment(Op *pOp, const char *zP4, char *zTemp, int nTemp){
          879  +static int displayComment(
          880  +  const Op *pOp,     /* The opcode to be commented */
          881  +  const char *zP4,   /* Previously obtained value for P4 */
          882  +  char *zTemp,       /* Write result here */
          883  +  int nTemp          /* Space available in zTemp[] */
          884  +){
   864    885     const char *zOpName;
   865    886     const char *zSynopsis;
   866    887     int nOpName;
   867    888     int ii, jj;
   868    889     zOpName = sqlite3OpcodeName(pOp->opcode);
   869    890     nOpName = sqlite3Strlen30(zOpName);
   870    891     if( zOpName[nOpName+1] ){
   871    892       int seenCom = 0;
          893  +    char c;
   872    894       zSynopsis = zOpName += nOpName + 1;
   873         -    for(ii=jj=0; jj<nTemp-1 && zSynopsis[ii]; ii++){
   874         -      if( zSynopsis[ii]=='P' ){
   875         -        int v;
   876         -        const char *zShow = 0;
   877         -        ii++;
   878         -        switch( zSynopsis[ii] ){
   879         -          case '1': v = pOp->p1;  break;
   880         -          case '2': v = pOp->p2;  break;
   881         -          case '3': v = pOp->p3;  break;
   882         -          case '5': v = pOp->p5;  break;
   883         -          case '4': zShow = zP4;  break;
   884         -          case 'X': zShow = pOp->zComment; seenCom = 1; break;
   885         -        }
   886         -        if( zShow ){
   887         -          sqlite3_snprintf(nTemp-jj, zTemp+jj, "%s", zShow);
          895  +    for(ii=jj=0; jj<nTemp-1 && (c = zSynopsis[ii])!=0; ii++){
          896  +      if( c=='P' ){
          897  +        c = zSynopsis[++ii];
          898  +        if( c=='4' ){
          899  +          sqlite3_snprintf(nTemp-jj, zTemp+jj, "%s", zP4);
          900  +        }else if( c=='X' ){
          901  +          sqlite3_snprintf(nTemp-jj, zTemp+jj, "%s", pOp->zComment);
          902  +          seenCom = 1;
   888    903           }else{
   889         -          sqlite3_snprintf(nTemp-jj, zTemp+jj, "%d", v);
          904  +          int v1 = translateP(c, pOp);
          905  +          int v2;
          906  +          sqlite3_snprintf(nTemp-jj, zTemp+jj, "%d", v1);
          907  +          if( strncmp(zSynopsis+ii+1, "@P", 2)==0 ){
          908  +            ii += 3;
          909  +            jj += sqlite3Strlen30(zTemp+jj);
          910  +            v2 = translateP(zSynopsis[ii], pOp);
          911  +            if( v2>1 ) sqlite3_snprintf(nTemp-jj, zTemp+jj, "..%d", v1+v2-1);
          912  +          }else if( strncmp(zSynopsis+ii+1, "..P3", 4)==0 && pOp->p3==0 ){
          913  +            ii += 4;
          914  +          }
   890    915           }
   891    916           jj += sqlite3Strlen30(zTemp+jj);
   892    917         }else{
   893         -        zTemp[jj++] = zSynopsis[ii];
          918  +        zTemp[jj++] = c;
   894    919         }
   895    920       }
   896    921       if( !seenCom && jj<nTemp-5 && pOp->zComment ){
   897    922         sqlite3_snprintf(nTemp-jj, zTemp+jj, "; %s", pOp->zComment);
   898    923         jj += sqlite3Strlen30(zTemp+jj);
   899    924       }
   900    925       if( jj<nTemp ) zTemp[jj] = 0;
................................................................................
  1103   1128   void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
  1104   1129     char *zP4;
  1105   1130     char zPtr[50];
  1106   1131     char zCom[100];
  1107   1132     static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-4s %.2X %s\n";
  1108   1133     if( pOut==0 ) pOut = stdout;
  1109   1134     zP4 = displayP4(pOp, zPtr, sizeof(zPtr));
  1110         -#ifdef SQLITE_DEBUG
         1135  +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
  1111   1136     displayComment(pOp, zP4, zCom, sizeof(zCom));
  1112   1137   #else
  1113   1138     zCom[0] = 0
  1114   1139   #endif
  1115   1140     fprintf(pOut, zFormat1, pc, 
  1116   1141         sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
  1117   1142         zCom
................................................................................
  1349   1374         pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
  1350   1375         pMem->n = 2;
  1351   1376         sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5);   /* P5 */
  1352   1377         pMem->type = SQLITE_TEXT;
  1353   1378         pMem->enc = SQLITE_UTF8;
  1354   1379         pMem++;
  1355   1380     
  1356         -#ifdef SQLITE_DEBUG
         1381  +#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
  1357   1382         if( sqlite3VdbeMemGrow(pMem, 500, 0) ){
  1358   1383           assert( p->db->mallocFailed );
  1359   1384           return SQLITE_ERROR;
  1360   1385         }
  1361   1386         pMem->flags = MEM_Dyn|MEM_Str|MEM_Term;
  1362   1387         pMem->n = displayComment(pOp, zP4, pMem->z, 500);
  1363   1388         pMem->type = SQLITE_TEXT;