/ Check-in [d6b0c392]
Login

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

Overview
Comment:Enhanced display of register ranges in the auxiliary comments added to EXPLAIN.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: d6b0c39281d0751ecec04d7c19d9d2931d133e8e
User & Date: drh 2013-10-30 00:25:03
Context
2013-10-30
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
00:25
Enhanced display of register ranges in the auxiliary comments added to EXPLAIN. check-in: d6b0c392 user: drh tags: trunk
2013-10-29
20:40
Automatically generated comments on many VDBE opcodes when in SQLITE_DEBUG mode. Comments derive from the "Synopsis:" field added to each opcode definition in vdbe.c. check-in: 5f310c6a user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

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: {
................................................................................
  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   /* Opcode: NotFound P1 P2 P3 P4 *
  3672         -** Synopsis: key=r[P3] N=P4
         3672  +** Synopsis: key=r[P3@P4]
  3673   3673   **
  3674   3674   ** If P4==0 then register P3 holds a blob constructed by MakeRecord.  If
  3675   3675   ** P4>0 then register P3 is the first of P4 registers that form an unpacked
  3676   3676   ** record.
  3677   3677   ** 
  3678   3678   ** Cursor P1 is on an index btree.  If the record identified by P3 and P4
  3679   3679   ** is not the prefix of any entry in P1 then a jump is made to P2.  If P1 
................................................................................
  4635   4635         }
  4636   4636       }
  4637   4637     }
  4638   4638     break;
  4639   4639   }
  4640   4640   
  4641   4641   /* Opcode: IdxDelete P1 P2 P3 * *
  4642         -** Synopsis: key=r[P2]..
         4642  +** Synopsis: key=r[P2@P3]
  4643   4643   **
  4644   4644   ** The content of P3 registers starting at register P2 form
  4645   4645   ** an unpacked index key. This opcode removes that entry from the 
  4646   4646   ** index opened by cursor P1.
  4647   4647   */
  4648   4648   case OP_IdxDelete: {
  4649   4649     VdbeCursor *pC;
................................................................................
  4708   4708         pOut->flags = MEM_Int;
  4709   4709       }
  4710   4710     }
  4711   4711     break;
  4712   4712   }
  4713   4713   
  4714   4714   /* Opcode: IdxGE P1 P2 P3 P4 P5
  4715         -** Synopsis: key=r[P3] N=P4
         4715  +** Synopsis: key=r[P3@P4]
  4716   4716   **
  4717   4717   ** The P4 register values beginning with P3 form an unpacked index 
  4718   4718   ** key that omits the ROWID.  Compare this key value against the index 
  4719   4719   ** that P1 is currently pointing to, ignoring the ROWID on the P1 index.
  4720   4720   **
  4721   4721   ** If the P1 index entry is greater than or equal to the key value
  4722   4722   ** then jump to P2.  Otherwise fall through to the next instruction.
................................................................................
  4723   4723   **
  4724   4724   ** If P5 is non-zero then the key value is increased by an epsilon 
  4725   4725   ** prior to the comparison.  This make the opcode work like IdxGT except
  4726   4726   ** that if the key from register P3 is a prefix of the key in the cursor,
  4727   4727   ** the result is false whereas it would be true with IdxGT.
  4728   4728   */
  4729   4729   /* Opcode: IdxLT P1 P2 P3 P4 P5
  4730         -** Synopsis: key=r[P3] N=P4
         4730  +** Synopsis: key=r[P3@P4]
  4731   4731   **
  4732   4732   ** The P4 register values beginning with P3 form an unpacked index 
  4733   4733   ** key that omits the ROWID.  Compare this key value against the index 
  4734   4734   ** that P1 is currently pointing to, ignoring the ROWID on the P1 index.
  4735   4735   **
  4736   4736   ** If the P1 index entry is less than the key value then jump to P2.
  4737   4737   ** Otherwise fall through to the next instruction.
................................................................................
  5466   5466     if( pIn1->u.i==0 ){
  5467   5467        pc = pOp->p2 - 1;
  5468   5468     }
  5469   5469     break;
  5470   5470   }
  5471   5471   
  5472   5472   /* Opcode: AggStep * P2 P3 P4 P5
  5473         -** Synopsis: accum=r[P3] step(r[P2]..) N=P5
         5473  +** Synopsis: accum=r[P3] step(r[P2@P5])
  5474   5474   **
  5475   5475   ** Execute the step function for an aggregate.  The
  5476   5476   ** function has P5 arguments.   P4 is a pointer to the FuncDef
  5477   5477   ** structure that specifies the function.  Use register
  5478   5478   ** P3 as the accumulator.
  5479   5479   **
  5480   5480   ** The P5 arguments are taken from register P2 and its
................................................................................
  6084   6084     }
  6085   6085     break;
  6086   6086   }
  6087   6087   #endif
  6088   6088   
  6089   6089   #ifndef SQLITE_OMIT_VIRTUALTABLE
  6090   6090   /* Opcode: VUpdate P1 P2 P3 P4 *
  6091         -** Synopsis: data=r[P3] N=P2
         6091  +** Synopsis: data=r[P3@P2]
  6092   6092   **
  6093   6093   ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
  6094   6094   ** This opcode invokes the corresponding xUpdate method. P2 values
  6095   6095   ** are contiguous memory cells starting at P3 to pass to the xUpdate 
  6096   6096   ** invocation. The value in register (P3+P2-1) corresponds to the 
  6097   6097   ** p2th element of the argv array passed to xUpdate.
  6098   6098   **

Changes to src/vdbeaux.c.

   851    851       return (VdbeOp*)&dummy;
   852    852     }else{
   853    853       return &p->aOp[addr];
   854    854     }
   855    855   }
   856    856   
   857    857   #if defined(SQLITE_DEBUG)
          858  +/*
          859  +** Return an integer value for one of the parameters to the opcode pOp
          860  +** determined by character c.
          861  +*/
          862  +static int translateP(char c, const Op *pOp){
          863  +  if( c=='1' ) return pOp->p1;
          864  +  if( c=='2' ) return pOp->p2;
          865  +  if( c=='3' ) return pOp->p3;
          866  +  if( c=='4' ) return pOp->p4.i;
          867  +  return pOp->p5;
          868  +}
          869  +
   858    870   /*
   859    871   ** Compute a string for the "comment" field of a VDBE opcode listing
   860    872   */
   861         -static int displayComment(Op *pOp, const char *zP4, char *zTemp, int nTemp){
          873  +static int displayComment(
          874  +  const Op *pOp,     /* The opcode to be commented */
          875  +  const char *zP4,   /* Previously obtained value for P4 */
          876  +  char *zTemp,       /* Write result here */
          877  +  int nTemp          /* Space available in zTemp[] */
          878  +){
   862    879     const char *zOpName;
   863    880     const char *zSynopsis;
   864    881     int nOpName;
   865    882     int ii, jj;
   866    883     zOpName = sqlite3OpcodeName(pOp->opcode);
   867    884     nOpName = sqlite3Strlen30(zOpName);
   868    885     if( zOpName[nOpName+1] ){
   869    886       int seenCom = 0;
          887  +    char c;
   870    888       zSynopsis = zOpName += nOpName + 1;
   871         -    for(ii=jj=0; jj<nTemp-1 && zSynopsis[ii]; ii++){
   872         -      if( zSynopsis[ii]=='P' ){
   873         -        int v;
   874         -        const char *zShow = 0;
   875         -        ii++;
   876         -        switch( zSynopsis[ii] ){
   877         -          case '1': v = pOp->p1;  break;
   878         -          case '2': v = pOp->p2;  break;
   879         -          case '3': v = pOp->p3;  break;
   880         -          case '5': v = pOp->p5;  break;
   881         -          case '4': zShow = zP4;  break;
   882         -          case 'X': zShow = pOp->zComment; seenCom = 1; break;
   883         -        }
   884         -        if( zShow ){
   885         -          sqlite3_snprintf(nTemp-jj, zTemp+jj, "%s", zShow);
          889  +    for(ii=jj=0; jj<nTemp-1 && (c = zSynopsis[ii])!=0; ii++){
          890  +      if( c=='P' ){
          891  +        c = zSynopsis[++ii];
          892  +        if( c=='4' ){
          893  +          sqlite3_snprintf(nTemp-jj, zTemp+jj, "%s", zP4);
          894  +        }else if( c=='X' ){
          895  +          sqlite3_snprintf(nTemp-jj, zTemp+jj, "%s", pOp->zComment);
          896  +          seenCom = 1;
   886    897           }else{
   887         -          sqlite3_snprintf(nTemp-jj, zTemp+jj, "%d", v);
          898  +          int v1 = translateP(c, pOp);
          899  +          int v2;
          900  +          sqlite3_snprintf(nTemp-jj, zTemp+jj, "%d", v1);
          901  +          if( strncmp(zSynopsis+ii+1, "@P", 2)==0 ){
          902  +            ii += 3;
          903  +            jj += sqlite3Strlen30(zTemp+jj);
          904  +            v2 = translateP(zSynopsis[ii], pOp);
          905  +            if( v2>1 ) sqlite3_snprintf(nTemp-jj, zTemp+jj, "..%d", v1+v2-1);
          906  +          }else if( strncmp(zSynopsis+ii+1, "..P3", 4)==0 && pOp->p3==0 ){
          907  +            ii += 4;
          908  +          }
   888    909           }
   889    910           jj += sqlite3Strlen30(zTemp+jj);
   890    911         }else{
   891         -        zTemp[jj++] = zSynopsis[ii];
          912  +        zTemp[jj++] = c;
   892    913         }
   893    914       }
   894    915       if( !seenCom && jj<nTemp-5 && pOp->zComment ){
   895    916         sqlite3_snprintf(nTemp-jj, zTemp+jj, "; %s", pOp->zComment);
   896    917         jj += sqlite3Strlen30(zTemp+jj);
   897    918       }
   898    919       if( jj<nTemp ) zTemp[jj] = 0;