/ Check-in [88ceb588]
Login

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

Overview
Comment:Improvements to the way sqlite3VdbeAddOpList() works, resulting in a slightly smaller and faster binary.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 88ceb588bcdb3ca86d0c58cfdeb61b5fe070872f
User & Date: drh 2016-01-16 20:50:21
Context
2016-01-16
21:06
Add extra tests to cover untested branches in fts5. check-in: 61deab04 user: dan tags: trunk
20:50
Improvements to the way sqlite3VdbeAddOpList() works, resulting in a slightly smaller and faster binary. check-in: 88ceb588 user: drh tags: trunk
18:58
Add further tests for fts5. Fix some problems with detail=col mode and auxiliary functions. check-in: de77d602 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pragma.c.

   426    426         { OP_Integer,     0, 2,        0},
   427    427         { OP_Subtract,    1, 2,        1},
   428    428         { OP_IfPos,       1, 8,        0},
   429    429         { OP_Integer,     0, 1,        0},                         /* 6 */
   430    430         { OP_Noop,        0, 0,        0},
   431    431         { OP_ResultRow,   1, 1,        0},
   432    432       };
   433         -    int addr;
          433  +    VdbeOp *aOp;
   434    434       sqlite3VdbeUsesBtree(v, iDb);
   435    435       if( !zRight ){
   436    436         setOneColumnName(v, "cache_size");
   437    437         pParse->nMem += 2;
   438         -      addr = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize,iLn);
   439         -      sqlite3VdbeChangeP1(v, addr, iDb);
   440         -      sqlite3VdbeChangeP1(v, addr+1, iDb);
   441         -      sqlite3VdbeChangeP1(v, addr+6, SQLITE_DEFAULT_CACHE_SIZE);
          438  +      sqlite3VdbeVerifyAvailableSpace(v, ArraySize(getCacheSize));
          439  +      aOp = sqlite3VdbeAddOpList(v, ArraySize(getCacheSize), getCacheSize, iLn);
          440  +      assert( aOp!=0 );
          441  +      aOp[0].p1 = iDb;
          442  +      aOp[1].p1 = iDb;
          443  +      aOp[6].p1 = SQLITE_DEFAULT_CACHE_SIZE;
   442    444       }else{
   443    445         int size = sqlite3AbsInt32(sqlite3Atoi(zRight));
   444    446         sqlite3BeginWriteOperation(pParse, 0, iDb);
   445    447         sqlite3VdbeAddOp2(v, OP_Integer, size, 1);
   446    448         sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_DEFAULT_CACHE_SIZE, 1);
   447    449         assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
   448    450         pDb->pSchema->cache_size = size;
................................................................................
   680    682             { OP_Transaction,    0,         1,                 0},    /* 0 */
   681    683             { OP_ReadCookie,     0,         1,         BTREE_LARGEST_ROOT_PAGE},
   682    684             { OP_If,             1,         0,                 0},    /* 2 */
   683    685             { OP_Halt,           SQLITE_OK, OE_Abort,          0},    /* 3 */
   684    686             { OP_Integer,        0,         1,                 0},    /* 4 */
   685    687             { OP_SetCookie,      0,         BTREE_INCR_VACUUM, 1},    /* 5 */
   686    688           };
   687         -        int iAddr;
   688         -        iAddr = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6, iLn);
   689         -        sqlite3VdbeChangeP1(v, iAddr, iDb);
   690         -        sqlite3VdbeChangeP1(v, iAddr+1, iDb);
   691         -        sqlite3VdbeChangeP2(v, iAddr+2, iAddr+4);
   692         -        sqlite3VdbeChangeP1(v, iAddr+4, eAuto-1);
   693         -        sqlite3VdbeChangeP1(v, iAddr+5, iDb);
          689  +        VdbeOp *aOp;
          690  +        int iAddr = sqlite3VdbeCurrentAddr(v);
          691  +        sqlite3VdbeVerifyAvailableSpace(v, ArraySize(setMeta6));
          692  +        aOp = sqlite3VdbeAddOpList(v, ArraySize(setMeta6), setMeta6, iLn);
          693  +        assert( aOp!=0 );
          694  +        aOp[0].p1 = iDb;
          695  +        aOp[1].p1 = iDb;
          696  +        aOp[2].p2 = iAddr+4;
          697  +        aOp[4].p1 = eAuto - 1;
          698  +        aOp[5].p1 = iDb;
   694    699           sqlite3VdbeUsesBtree(v, iDb);
   695    700         }
   696    701       }
   697    702       break;
   698    703     }
   699    704   #endif
   700    705   
................................................................................
  1392   1397     /* Pragma "quick_check" is reduced version of 
  1393   1398     ** integrity_check designed to detect most database corruption
  1394   1399     ** without most of the overhead of a full integrity-check.
  1395   1400     */
  1396   1401     case PragTyp_INTEGRITY_CHECK: {
  1397   1402       int i, j, addr, mxErr;
  1398   1403   
  1399         -    /* Code that appears at the end of the integrity check.  If no error
  1400         -    ** messages have been generated, output OK.  Otherwise output the
  1401         -    ** error message
  1402         -    */
  1403         -    static const int iLn = VDBE_OFFSET_LINENO(2);
  1404         -    static const VdbeOpList endCode[] = {
  1405         -      { OP_AddImm,      1, 0,        0},    /* 0 */
  1406         -      { OP_If,          1, 0,        0},    /* 1 */
  1407         -      { OP_String8,     0, 3,        0},    /* 2 */
  1408         -      { OP_ResultRow,   3, 1,        0},
  1409         -    };
  1410         -
  1411   1404       int isQuick = (sqlite3Tolower(zLeft[0])=='q');
  1412   1405   
  1413   1406       /* If the PRAGMA command was of the form "PRAGMA <db>.integrity_check",
  1414   1407       ** then iDb is set to the index of the database identified by <db>.
  1415   1408       ** In this case, the integrity of database iDb only is verified by
  1416   1409       ** the VDBE created below.
  1417   1410       **
................................................................................
  1600   1593             sqlite3VdbeLoadString(v, 3, pIdx->zName);
  1601   1594             sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7);
  1602   1595             sqlite3VdbeAddOp2(v, OP_ResultRow, 7, 1);
  1603   1596           }
  1604   1597   #endif /* SQLITE_OMIT_BTREECOUNT */
  1605   1598         } 
  1606   1599       }
  1607         -    addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
  1608         -    sqlite3VdbeChangeP2(v, addr, -mxErr);
  1609         -    sqlite3VdbeJumpHere(v, addr+1);
  1610         -    sqlite3VdbeChangeP4(v, addr+2, "ok", P4_STATIC);
         1600  +    {
         1601  +      static const int iLn = VDBE_OFFSET_LINENO(2);
         1602  +      static const VdbeOpList endCode[] = {
         1603  +        { OP_AddImm,      1, 0,        0},    /* 0 */
         1604  +        { OP_If,          1, 0,        0},    /* 1 */
         1605  +        { OP_String8,     0, 3,        0},    /* 2 */
         1606  +        { OP_ResultRow,   3, 1,        0},
         1607  +      };
         1608  +      VdbeOp *aOp;
         1609  +
         1610  +      aOp = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
         1611  +      if( aOp ){
         1612  +        aOp[0].p2 = -mxErr;
         1613  +        aOp[1].p2 = sqlite3VdbeCurrentAddr(v);
         1614  +        aOp[2].p4type = P4_STATIC;
         1615  +        aOp[2].p4.z = "ok";
         1616  +      }
         1617  +    }
  1611   1618     }
  1612   1619     break;
  1613   1620   #endif /* SQLITE_OMIT_INTEGRITY_CHECK */
  1614   1621   
  1615   1622   #ifndef SQLITE_OMIT_UTF16
  1616   1623     /*
  1617   1624     **   PRAGMA encoding
................................................................................
  1720   1727       if( zRight && (pPragma->mPragFlag & PragFlag_ReadOnly)==0 ){
  1721   1728         /* Write the specified cookie value */
  1722   1729         static const VdbeOpList setCookie[] = {
  1723   1730           { OP_Transaction,    0,  1,  0},    /* 0 */
  1724   1731           { OP_Integer,        0,  1,  0},    /* 1 */
  1725   1732           { OP_SetCookie,      0,  0,  1},    /* 2 */
  1726   1733         };
  1727         -      int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0);
  1728         -      sqlite3VdbeChangeP1(v, addr, iDb);
  1729         -      sqlite3VdbeChangeP1(v, addr+1, sqlite3Atoi(zRight));
  1730         -      sqlite3VdbeChangeP1(v, addr+2, iDb);
  1731         -      sqlite3VdbeChangeP2(v, addr+2, iCookie);
         1734  +      VdbeOp *aOp;
         1735  +      sqlite3VdbeVerifyAvailableSpace(v, ArraySize(setCookie));
         1736  +      aOp = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie, 0);
         1737  +      assert( aOp!=0 );
         1738  +      aOp[0].p1 = iDb;
         1739  +      aOp[1].p1 = sqlite3Atoi(zRight);
         1740  +      aOp[2].p1 = iDb;
         1741  +      aOp[2].p2 = iCookie;
  1732   1742       }else{
  1733   1743         /* Read the specified cookie value */
  1734   1744         static const VdbeOpList readCookie[] = {
  1735   1745           { OP_Transaction,     0,  0,  0},    /* 0 */
  1736   1746           { OP_ReadCookie,      0,  1,  0},    /* 1 */
  1737   1747           { OP_ResultRow,       1,  1,  0}
  1738   1748         };
  1739         -      int addr = sqlite3VdbeAddOpList(v, ArraySize(readCookie), readCookie, 0);
  1740         -      sqlite3VdbeChangeP1(v, addr, iDb);
  1741         -      sqlite3VdbeChangeP1(v, addr+1, iDb);
  1742         -      sqlite3VdbeChangeP3(v, addr+1, iCookie);
         1749  +      VdbeOp *aOp;
         1750  +      sqlite3VdbeVerifyAvailableSpace(v, ArraySize(readCookie));
         1751  +      aOp = sqlite3VdbeAddOpList(v, ArraySize(readCookie),readCookie,0);
         1752  +      assert( aOp!=0 );
         1753  +      aOp[0].p1 = iDb;
         1754  +      aOp[1].p1 = iDb;
         1755  +      aOp[1].p3 = iCookie;
  1743   1756         sqlite3VdbeSetNumCols(v, 1);
  1744   1757         sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLeft, SQLITE_TRANSIENT);
  1745   1758       }
  1746   1759     }
  1747   1760     break;
  1748   1761   #endif /* SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS */
  1749   1762   

Changes to src/vdbe.h.

   176    176   int sqlite3VdbeGoto(Vdbe*,int);
   177    177   int sqlite3VdbeLoadString(Vdbe*,int,const char*);
   178    178   void sqlite3VdbeMultiLoad(Vdbe*,int,const char*,...);
   179    179   int sqlite3VdbeAddOp3(Vdbe*,int,int,int,int);
   180    180   int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
   181    181   int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int);
   182    182   int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
   183         -int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno);
          183  +#ifdef SQLITE_DEBUG
          184  +  void sqlite3VdbeVerifyAvailableSpace(Vdbe *p, int N);
          185  +#else
          186  +# define sqlite3VdbeVerifyAvailableSpace(A,B)
          187  +#endif
          188  +VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno);
   184    189   void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
   185    190   void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8);
   186    191   void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
   187    192   void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
   188    193   void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
   189    194   void sqlite3VdbeChangeP5(Vdbe*, u8 P5);
   190    195   void sqlite3VdbeJumpHere(Vdbe*, int addr);
   191         -void sqlite3VdbeChangeToNoop(Vdbe*, int addr);
          196  +int sqlite3VdbeChangeToNoop(Vdbe*, int addr);
   192    197   int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op);
   193    198   void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
   194    199   void sqlite3VdbeSetP4KeyInfo(Parse*, Index*);
   195    200   void sqlite3VdbeUsesBtree(Vdbe*, int);
   196    201   VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
   197    202   int sqlite3VdbeMakeLabel(Vdbe*);
   198    203   void sqlite3VdbeRunOnlyOnce(Vdbe*);

Changes to src/vdbeaux.c.

   246    246     va_list ap;
   247    247     int i;
   248    248     char c;
   249    249     va_start(ap, zTypes);
   250    250     for(i=0; (c = zTypes[i])!=0; i++){
   251    251       if( c=='s' ){
   252    252         const char *z = va_arg(ap, const char*);
   253         -      int addr = sqlite3VdbeAddOp2(p, z==0 ? OP_Null : OP_String8, 0, iDest++);
   254         -      if( z ) sqlite3VdbeChangeP4(p, addr, z, 0);
          253  +      sqlite3VdbeAddOp4(p, z==0 ? OP_Null : OP_String8, 0, iDest++, 0, z, 0);
   255    254       }else{
   256    255         assert( c=='i' );
   257    256         sqlite3VdbeAddOp2(p, OP_Integer, va_arg(ap, int), iDest++);
   258    257       }
   259    258     }
   260    259     va_end(ap);
   261    260   }
................................................................................
   602    601   ** Return the address of the next instruction to be inserted.
   603    602   */
   604    603   int sqlite3VdbeCurrentAddr(Vdbe *p){
   605    604     assert( p->magic==VDBE_MAGIC_INIT );
   606    605     return p->nOp;
   607    606   }
   608    607   
          608  +/*
          609  +** Verify that at least N opcode slots are available in p without
          610  +** having to malloc for more space.  This interface is used for
          611  +** testing only.
          612  +*/
          613  +#ifdef SQLITE_DEBUG
          614  +void sqlite3VdbeVerifyAvailableSpace(Vdbe *p, int N){
          615  +  assert( p->nOp + N <= p->pParse->nOpAlloc );
          616  +}
          617  +#endif
          618  +
   609    619   /*
   610    620   ** This function returns a pointer to the array of opcodes associated with
   611    621   ** the Vdbe passed as the first argument. It is the callers responsibility
   612    622   ** to arrange for the returned array to be eventually freed using the 
   613    623   ** vdbeFreeOpArray() function.
   614    624   **
   615    625   ** Before returning, *pnOp is set to the number of entries in the returned
................................................................................
   627    637     resolveP2Values(p, pnMaxArg);
   628    638     *pnOp = p->nOp;
   629    639     p->aOp = 0;
   630    640     return aOp;
   631    641   }
   632    642   
   633    643   /*
   634         -** Add a whole list of operations to the operation stack.  Return the
   635         -** address of the first operation added.
          644  +** Add a whole list of operations to the operation stack.  Return a
          645  +** pointer to the first operation inserted.
   636    646   */
   637         -int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp, int iLineno){
   638         -  int addr, i;
   639         -  VdbeOp *pOut;
          647  +VdbeOp *sqlite3VdbeAddOpList(
          648  +  Vdbe *p,                     /* Add opcodes to the prepared statement */
          649  +  int nOp,                     /* Number of opcodes to add */
          650  +  VdbeOpList const *aOp,       /* The opcodes to be added */
          651  +  int iLineno                  /* Source-file line number of first opcode */
          652  +){
          653  +  int i;
          654  +  VdbeOp *pOut, *pFirst;
   640    655     assert( nOp>0 );
   641    656     assert( p->magic==VDBE_MAGIC_INIT );
   642    657     if( p->nOp + nOp > p->pParse->nOpAlloc && growOpArray(p, nOp) ){
   643    658       return 0;
   644    659     }
   645         -  addr = p->nOp;
   646         -  pOut = &p->aOp[addr];
          660  +  pFirst = pOut = &p->aOp[p->nOp];
   647    661     for(i=0; i<nOp; i++, aOp++, pOut++){
   648    662       pOut->opcode = aOp->opcode;
   649    663       pOut->p1 = aOp->p1;
   650    664       pOut->p2 = aOp->p2;
   651    665       assert( aOp->p2>=0 );
   652    666       pOut->p3 = aOp->p3;
   653    667       pOut->p4type = P4_NOTUSED;
................................................................................
   659    673   #ifdef SQLITE_VDBE_COVERAGE
   660    674       pOut->iSrcLine = iLineno+i;
   661    675   #else
   662    676       (void)iLineno;
   663    677   #endif
   664    678   #ifdef SQLITE_DEBUG
   665    679       if( p->db->flags & SQLITE_VdbeAddopTrace ){
   666         -      sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]);
          680  +      sqlite3VdbePrintOp(0, i+p->nOp, &p->aOp[i+p->nOp]);
   667    681       }
   668    682   #endif
   669    683     }
   670    684     p->nOp += nOp;
   671         -  return addr;
          685  +  return pFirst;
   672    686   }
   673    687   
   674    688   #if defined(SQLITE_ENABLE_STMT_SCANSTATUS)
   675    689   /*
   676    690   ** Add an entry to the array of counters managed by sqlite3_stmt_scanstatus().
   677    691   */
   678    692   void sqlite3VdbeScanStatus(
................................................................................
   822    836     p->pNext = pVdbe->pProgram;
   823    837     pVdbe->pProgram = p;
   824    838   }
   825    839   
   826    840   /*
   827    841   ** Change the opcode at addr into OP_Noop
   828    842   */
   829         -void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
   830         -  if( addr<p->nOp ){
   831         -    VdbeOp *pOp = &p->aOp[addr];
   832         -    sqlite3 *db = p->db;
   833         -    freeP4(db, pOp->p4type, pOp->p4.p);
   834         -    memset(pOp, 0, sizeof(pOp[0]));
   835         -    pOp->opcode = OP_Noop;
   836         -  }
          843  +int sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
          844  +  VdbeOp *pOp;
          845  +  if( p->db->mallocFailed ) return 0;
          846  +  assert( addr>=0 && addr<p->nOp );
          847  +  pOp = &p->aOp[addr];
          848  +  freeP4(p->db, pOp->p4type, pOp->p4.p);
          849  +  memset(pOp, 0, sizeof(pOp[0]));
          850  +  pOp->opcode = OP_Noop;
          851  +  return 1;
   837    852   }
   838    853   
   839    854   /*
   840    855   ** If the last opcode is "op" and it is not a jump destination,
   841    856   ** then remove it.  Return true if and only if an opcode was removed.
   842    857   */
   843    858   int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){
   844    859     if( (p->nOp-1)>(p->pParse->iFixedOp) && p->aOp[p->nOp-1].opcode==op ){
   845         -    sqlite3VdbeChangeToNoop(p, p->nOp-1);
   846         -    return 1;
          860  +    return sqlite3VdbeChangeToNoop(p, p->nOp-1);
   847    861     }else{
   848    862       return 0;
   849    863     }
   850    864   }
   851    865   
   852    866   /*
   853    867   ** Change the value of the P4 operand for a specific instruction.

Changes to src/vdbeblob.c.

   111    111     const char *zColumn,    /* The column containing the blob */
   112    112     sqlite_int64 iRow,      /* The row containing the glob */
   113    113     int flags,              /* True -> read/write access, false -> read-only */
   114    114     sqlite3_blob **ppBlob   /* Handle for accessing the blob returned here */
   115    115   ){
   116    116     int nAttempt = 0;
   117    117     int iCol;               /* Index of zColumn in row-record */
   118         -
   119         -  /* This VDBE program seeks a btree cursor to the identified 
   120         -  ** db/table/row entry. The reason for using a vdbe program instead
   121         -  ** of writing code to use the b-tree layer directly is that the
   122         -  ** vdbe program will take advantage of the various transaction,
   123         -  ** locking and error handling infrastructure built into the vdbe.
   124         -  **
   125         -  ** After seeking the cursor, the vdbe executes an OP_ResultRow.
   126         -  ** Code external to the Vdbe then "borrows" the b-tree cursor and
   127         -  ** uses it to implement the blob_read(), blob_write() and 
   128         -  ** blob_bytes() functions.
   129         -  **
   130         -  ** The sqlite3_blob_close() function finalizes the vdbe program,
   131         -  ** which closes the b-tree cursor and (possibly) commits the 
   132         -  ** transaction.
   133         -  */
   134         -  static const int iLn = VDBE_OFFSET_LINENO(4);
   135         -  static const VdbeOpList openBlob[] = {
   136         -    /* {OP_Transaction, 0, 0, 0},  // 0: Inserted separately */
   137         -    {OP_TableLock, 0, 0, 0},       /* 1: Acquire a read or write lock */
   138         -    /* One of the following two instructions is replaced by an OP_Noop. */
   139         -    {OP_OpenRead, 0, 0, 0},        /* 2: Open cursor 0 for reading */
   140         -    {OP_OpenWrite, 0, 0, 0},       /* 3: Open cursor 0 for read/write */
   141         -    {OP_Variable, 1, 1, 1},        /* 4: Push the rowid to the stack */
   142         -    {OP_NotExists, 0, 10, 1},      /* 5: Seek the cursor */
   143         -    {OP_Column, 0, 0, 1},          /* 6  */
   144         -    {OP_ResultRow, 1, 0, 0},       /* 7  */
   145         -    {OP_Goto, 0, 4, 0},            /* 8  */
   146         -    {OP_Close, 0, 0, 0},           /* 9  */
   147         -    {OP_Halt, 0, 0, 0},            /* 10 */
   148         -  };
   149         -
   150    118     int rc = SQLITE_OK;
   151    119     char *zErr = 0;
   152    120     Table *pTab;
   153    121     Parse *pParse = 0;
   154    122     Incrblob *pBlob = 0;
   155    123   
   156    124   #ifdef SQLITE_ENABLE_API_ARMOR
................................................................................
   261    229           goto blob_open_out;
   262    230         }
   263    231       }
   264    232   
   265    233       pBlob->pStmt = (sqlite3_stmt *)sqlite3VdbeCreate(pParse);
   266    234       assert( pBlob->pStmt || db->mallocFailed );
   267    235       if( pBlob->pStmt ){
          236  +      
          237  +      /* This VDBE program seeks a btree cursor to the identified 
          238  +      ** db/table/row entry. The reason for using a vdbe program instead
          239  +      ** of writing code to use the b-tree layer directly is that the
          240  +      ** vdbe program will take advantage of the various transaction,
          241  +      ** locking and error handling infrastructure built into the vdbe.
          242  +      **
          243  +      ** After seeking the cursor, the vdbe executes an OP_ResultRow.
          244  +      ** Code external to the Vdbe then "borrows" the b-tree cursor and
          245  +      ** uses it to implement the blob_read(), blob_write() and 
          246  +      ** blob_bytes() functions.
          247  +      **
          248  +      ** The sqlite3_blob_close() function finalizes the vdbe program,
          249  +      ** which closes the b-tree cursor and (possibly) commits the 
          250  +      ** transaction.
          251  +      */
          252  +      static const int iLn = VDBE_OFFSET_LINENO(3);
          253  +      static const VdbeOpList openBlob[] = {
          254  +        /* {OP_Transaction, 0, 0, 0},  // inserted separately */
          255  +        {OP_TableLock, 0, 0, 0},       /* 0: Acquire a read or write lock */
          256  +        {OP_OpenRead, 0, 0, 0},        /* 1: Open cursor 0 for reading */
          257  +        {OP_OpenWrite, 0, 0, 0},       /* 2: Open cursor 0 for read/write */
          258  +        {OP_Variable, 1, 1, 1},        /* 3: Push the rowid to the stack */
          259  +        {OP_NotExists, 0, 10, 1},      /* 4: Seek the cursor */
          260  +        {OP_Column, 0, 0, 1},          /* 5  */
          261  +        {OP_ResultRow, 1, 0, 0},       /* 6  */
          262  +        {OP_Goto, 0, 4, 0},            /* 7  */
          263  +        {OP_Close, 0, 0, 0},           /* 8  */
          264  +        {OP_Halt, 0, 0, 0},            /* 9 */
          265  +      };
   268    266         Vdbe *v = (Vdbe *)pBlob->pStmt;
   269    267         int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
   270         -
          268  +      VdbeOp *aOp;
   271    269   
   272    270         sqlite3VdbeAddOp4Int(v, OP_Transaction, iDb, flags, 
   273    271                              pTab->pSchema->schema_cookie,
   274    272                              pTab->pSchema->iGeneration);
   275    273         sqlite3VdbeChangeP5(v, 1);     
   276         -      sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn);
          274  +      aOp = sqlite3VdbeAddOpList(v, ArraySize(openBlob), openBlob, iLn);
   277    275   
   278    276         /* Make sure a mutex is held on the table to be accessed */
   279    277         sqlite3VdbeUsesBtree(v, iDb); 
   280    278   
   281         -      /* Configure the OP_TableLock instruction */
          279  +      if( db->mallocFailed==0 ){
          280  +        assert( aOp!=0 );
          281  +        /* Configure the OP_TableLock instruction */
   282    282   #ifdef SQLITE_OMIT_SHARED_CACHE
   283         -      sqlite3VdbeChangeToNoop(v, 1);
          283  +        aOp[0].opcode = OP_Noop;
   284    284   #else
   285         -      sqlite3VdbeChangeP1(v, 1, iDb);
   286         -      sqlite3VdbeChangeP2(v, 1, pTab->tnum);
   287         -      sqlite3VdbeChangeP3(v, 1, flags);
   288         -      sqlite3VdbeChangeP4(v, 1, pTab->zName, P4_TRANSIENT);
          285  +        aOp[0].p1 = iDb;
          286  +        aOp[0].p2 = pTab->tnum;
          287  +        aOp[0].p3 = flags;
          288  +        sqlite3VdbeChangeP4(v, 1, pTab->zName, P4_TRANSIENT);
          289  +      }
          290  +      if( db->mallocFailed==0 ){
   289    291   #endif
   290    292   
   291         -      /* Remove either the OP_OpenWrite or OpenRead. Set the P2 
   292         -      ** parameter of the other to pTab->tnum.  */
   293         -      sqlite3VdbeChangeToNoop(v, 3 - flags);
   294         -      sqlite3VdbeChangeP2(v, 2 + flags, pTab->tnum);
   295         -      sqlite3VdbeChangeP3(v, 2 + flags, iDb);
          293  +        /* Remove either the OP_OpenWrite or OpenRead. Set the P2 
          294  +        ** parameter of the other to pTab->tnum.  */
          295  +        aOp[2-flags].opcode = OP_Noop;
          296  +        aOp[1+flags].p2 = pTab->tnum;
          297  +        aOp[1+flags].p3 = iDb;   
   296    298   
   297         -      /* Configure the number of columns. Configure the cursor to
   298         -      ** think that the table has one more column than it really
   299         -      ** does. An OP_Column to retrieve this imaginary column will
   300         -      ** always return an SQL NULL. This is useful because it means
   301         -      ** we can invoke OP_Column to fill in the vdbe cursors type 
   302         -      ** and offset cache without causing any IO.
   303         -      */
   304         -      sqlite3VdbeChangeP4(v, 2+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32);
   305         -      sqlite3VdbeChangeP2(v, 6, pTab->nCol);
   306         -      if( !db->mallocFailed ){
          299  +        /* Configure the number of columns. Configure the cursor to
          300  +        ** think that the table has one more column than it really
          301  +        ** does. An OP_Column to retrieve this imaginary column will
          302  +        ** always return an SQL NULL. This is useful because it means
          303  +        ** we can invoke OP_Column to fill in the vdbe cursors type 
          304  +        ** and offset cache without causing any IO.
          305  +        */
          306  +        aOp[1+flags].p4type = P4_INT32;
          307  +        aOp[1+flags].p4.i = pTab->nCol+1;
          308  +        aOp[5].p2 = pTab->nCol;
          309  +
   307    310           pParse->nVar = 1;
   308    311           pParse->nMem = 1;
   309    312           pParse->nTab = 1;
   310    313           sqlite3VdbeMakeReady(v, pParse);
   311    314         }
   312    315       }
   313    316