/ Check-in [521d72bd]
Login

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

Overview
Comment:Make no assumptions about the initial state of VDBE registers.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | uninit-vdbe-mem
Files: files | file ages | folders
SHA1: 521d72bdf67b4b1972331307345a18c231a6e1d6
User & Date: drh 2011-12-09 16:21:19
Context
2011-12-09
16:59
Previous check-in broke auto-increment. This check-in appears to fix it. check-in: 28ffd39c user: drh tags: uninit-vdbe-mem
16:21
Make no assumptions about the initial state of VDBE registers. check-in: 521d72bd user: drh tags: uninit-vdbe-mem
13:24
Modify the OP_Once opcode so that it works correctly in trigger sub-programs. This is a candidate fix for [7bbfb7d442]. check-in: 557c6905 user: dan tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/expr.c.

  1440   1440   */
  1441   1441   #ifndef SQLITE_OMIT_SUBQUERY
  1442   1442   int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
  1443   1443     Select *p;                            /* SELECT to the right of IN operator */
  1444   1444     int eType = 0;                        /* Type of RHS table. IN_INDEX_* */
  1445   1445     int iTab = pParse->nTab++;            /* Cursor of the RHS table */
  1446   1446     int mustBeUnique = (prNotFound==0);   /* True if RHS must be unique */
         1447  +  Vdbe *v = sqlite3GetVdbe(pParse);     /* Virtual machine being coded */
  1447   1448   
  1448   1449     assert( pX->op==TK_IN );
  1449   1450   
  1450   1451     /* Check to see if an existing table or index can be used to
  1451   1452     ** satisfy the query.  This is preferable to generating a new 
  1452   1453     ** ephemeral table.
  1453   1454     */
  1454   1455     p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0);
  1455   1456     if( ALWAYS(pParse->nErr==0) && isCandidateForInOpt(p) ){
  1456   1457       sqlite3 *db = pParse->db;              /* Database connection */
  1457         -    Vdbe *v = sqlite3GetVdbe(pParse);      /* Virtual machine being coded */
  1458   1458       Table *pTab;                           /* Table <table>. */
  1459   1459       Expr *pExpr;                           /* Expression <column> */
  1460   1460       int iCol;                              /* Index of column <column> */
  1461   1461       int iDb;                               /* Database idx for pTab */
  1462   1462   
  1463   1463       assert( p );                        /* Because of isCandidateForInOpt(p) */
  1464   1464       assert( p->pEList!=0 );             /* Because of isCandidateForInOpt(p) */
................................................................................
  1517   1517                                  pKey,P4_KEYINFO_HANDOFF);
  1518   1518             VdbeComment((v, "%s", pIdx->zName));
  1519   1519             eType = IN_INDEX_INDEX;
  1520   1520   
  1521   1521             sqlite3VdbeJumpHere(v, iAddr);
  1522   1522             if( prNotFound && !pTab->aCol[iCol].notNull ){
  1523   1523               *prNotFound = ++pParse->nMem;
         1524  +            sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound);
  1524   1525             }
  1525   1526           }
  1526   1527         }
  1527   1528       }
  1528   1529     }
  1529   1530   
  1530   1531     if( eType==0 ){
................................................................................
  1532   1533       ** We will have to generate an ephemeral table to do the job.
  1533   1534       */
  1534   1535       double savedNQueryLoop = pParse->nQueryLoop;
  1535   1536       int rMayHaveNull = 0;
  1536   1537       eType = IN_INDEX_EPH;
  1537   1538       if( prNotFound ){
  1538   1539         *prNotFound = rMayHaveNull = ++pParse->nMem;
         1540  +      sqlite3VdbeAddOp2(v, OP_Null, 0, *prNotFound);
  1539   1541       }else{
  1540   1542         testcase( pParse->nQueryLoop>(double)1 );
  1541   1543         pParse->nQueryLoop = (double)1;
  1542   1544         if( pX->pLeft->iColumn<0 && !ExprHasAnyProperty(pX, EP_xIsSelect) ){
  1543   1545           eType = IN_INDEX_ROWID;
  1544   1546         }
  1545   1547       }

Changes to src/insert.c.

   236    236     assert( v );   /* We failed long ago if this is not so */
   237    237     for(p = pParse->pAinc; p; p = p->pNext){
   238    238       pDb = &db->aDb[p->iDb];
   239    239       memId = p->regCtr;
   240    240       assert( sqlite3SchemaMutexHeld(db, 0, pDb->pSchema) );
   241    241       sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead);
   242    242       addr = sqlite3VdbeCurrentAddr(v);
          243  +    sqlite3VdbeAddOp2(v, OP_Null, 0, memId+1);
   243    244       sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, p->pTab->zName, 0);
   244    245       sqlite3VdbeAddOp2(v, OP_Rewind, 0, addr+9);
   245    246       sqlite3VdbeAddOp3(v, OP_Column, 0, 0, memId);
   246    247       sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId);
   247    248       sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL);
   248    249       sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1);
   249    250       sqlite3VdbeAddOp3(v, OP_Column, 0, 1, memId);

Changes to src/select.c.

  1943   1943     addr = sqlite3VdbeCurrentAddr(v);
  1944   1944     iContinue = sqlite3VdbeMakeLabel(v);
  1945   1945   
  1946   1946     /* Suppress duplicates for UNION, EXCEPT, and INTERSECT 
  1947   1947     */
  1948   1948     if( regPrev ){
  1949   1949       int j1, j2;
  1950         -    j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev);
         1950  +    j1 = sqlite3VdbeAddOp1(v, OP_JumpOnce, pParse->nOnce++);
  1951   1951       j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iMem, regPrev+1, pIn->nMem,
  1952   1952                                 (char*)pKeyInfo, p4type);
  1953   1953       sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2);
  1954   1954       sqlite3VdbeJumpHere(v, j1);
  1955   1955       sqlite3ExprCodeCopy(pParse, pIn->iMem, regPrev+1, pIn->nMem);
  1956         -    sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev);
  1957   1956     }
  1958   1957     if( pParse->db->mallocFailed ) return 0;
  1959   1958   
  1960   1959     /* Suppress the the first OFFSET entries if there is an OFFSET clause
  1961   1960     */
  1962   1961     codeOffset(v, p, iContinue);
  1963   1962   
................................................................................
  4150   4149         pParse->nMem += pGroupBy->nExpr;
  4151   4150         iBMem = pParse->nMem + 1;
  4152   4151         pParse->nMem += pGroupBy->nExpr;
  4153   4152         sqlite3VdbeAddOp2(v, OP_Integer, 0, iAbortFlag);
  4154   4153         VdbeComment((v, "clear abort flag"));
  4155   4154         sqlite3VdbeAddOp2(v, OP_Integer, 0, iUseFlag);
  4156   4155         VdbeComment((v, "indicate accumulator empty"));
         4156  +      sqlite3VdbeAddOp3(v, OP_Null, 0, iAMem, iAMem+pGroupBy->nExpr-1);
  4157   4157   
  4158   4158         /* Begin a loop that will extract all source rows in GROUP BY order.
  4159   4159         ** This might involve two separate loops with an OP_Sort in between, or
  4160   4160         ** it might be a single loop that uses an index to extract information
  4161   4161         ** in the right order to begin with.
  4162   4162         */
  4163   4163         sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);

Changes to src/update.c.

   122    122   #endif
   123    123     int newmask;           /* Mask of NEW.* columns accessed by BEFORE triggers */
   124    124   
   125    125     /* Register Allocations */
   126    126     int regRowCount = 0;   /* A count of rows changed */
   127    127     int regOldRowid;       /* The old rowid */
   128    128     int regNewRowid;       /* The new rowid */
   129         -  int regNew;
   130         -  int regOld = 0;
          129  +  int regNew;            /* Content of the NEW.* table in triggers */
          130  +  int regOld = 0;        /* Content of OLD.* table in triggers */
   131    131     int regRowSet = 0;     /* Rowset of rows to be updated */
   132    132   
   133    133     memset(&sContext, 0, sizeof(sContext));
   134    134     db = pParse->db;
   135    135     if( pParse->nErr || db->mallocFailed ){
   136    136       goto update_cleanup;
   137    137     }
................................................................................
   272    272       pWhere = 0;
   273    273       pTabList = 0;
   274    274       goto update_cleanup;
   275    275     }
   276    276   #endif
   277    277   
   278    278     /* Allocate required registers. */
          279  +  regRowSet = ++pParse->nMem;
   279    280     regOldRowid = regNewRowid = ++pParse->nMem;
   280    281     if( pTrigger || hasFK ){
   281    282       regOld = pParse->nMem + 1;
   282    283       pParse->nMem += pTab->nCol;
   283    284     }
   284    285     if( chngRowid || pTrigger || hasFK ){
   285    286       regNewRowid = ++pParse->nMem;
................................................................................
   306    307     */
   307    308     if( sqlite3ResolveExprNames(&sNC, pWhere) ){
   308    309       goto update_cleanup;
   309    310     }
   310    311   
   311    312     /* Begin the database scan
   312    313     */
   313         -  sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
          314  +  sqlite3VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldRowid);
   314    315     pWInfo = sqlite3WhereBegin(
   315    316         pParse, pTabList, pWhere, 0, 0, WHERE_ONEPASS_DESIRED
   316    317     );
   317    318     if( pWInfo==0 ) goto update_cleanup;
   318    319     okOnePass = pWInfo->okOnePass;
   319    320   
   320    321     /* Remember the rowid of every item to be updated.
   321    322     */
   322    323     sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regOldRowid);
   323    324     if( !okOnePass ){
   324         -    regRowSet = ++pParse->nMem;
   325    325       sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
   326    326     }
   327    327   
   328    328     /* End the database scan loop.
   329    329     */
   330    330     sqlite3WhereEnd(pWInfo);
   331    331   
................................................................................
   421    421     ** the database after the BEFORE triggers are fired anyway (as the trigger 
   422    422     ** may have modified them). So not loading those that are not going to
   423    423     ** be used eliminates some redundant opcodes.
   424    424     */
   425    425     newmask = sqlite3TriggerColmask(
   426    426         pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
   427    427     );
          428  +  sqlite3VdbeAddOp3(v, OP_Null, 0, regNew, regNew+pTab->nCol-1);
   428    429     for(i=0; i<pTab->nCol; i++){
   429    430       if( i==pTab->iPKey ){
   430         -      sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
          431  +      /*sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);*/
   431    432       }else{
   432    433         j = aXRef[i];
   433    434         if( j>=0 ){
   434    435           sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
   435    436         }else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask&(1<<i)) ){
   436    437           /* This branch loads the value of a column that will not be changed 
   437    438           ** into a register. This is done if there are no BEFORE triggers, or

Changes to src/vdbe.c.

   760    760   }
   761    761   
   762    762   /* Opcode:  Gosub P1 P2 * * *
   763    763   **
   764    764   ** Write the current address onto register P1
   765    765   ** and then jump to address P2.
   766    766   */
   767         -case OP_Gosub: {            /* jump, in1 */
          767  +case OP_Gosub: {            /* jump */
          768  +  assert( pOp->p1>0 && pOp->p1<=p->nMem );
   768    769     pIn1 = &aMem[pOp->p1];
   769    770     assert( (pIn1->flags & MEM_Dyn)==0 );
   770    771     memAboutToChange(p, pIn1);
   771    772     pIn1->flags = MEM_Int;
   772    773     pIn1->u.i = pc;
   773    774     REGISTER_TRACE(pOp->p1, pIn1);
   774    775     pc = pOp->p2 - 1;
................................................................................
   957    958     pOut->z = pOp->p4.z;
   958    959     pOut->n = pOp->p1;
   959    960     pOut->enc = encoding;
   960    961     UPDATE_MAX_BLOBSIZE(pOut);
   961    962     break;
   962    963   }
   963    964   
   964         -/* Opcode: Null * P2 * * *
          965  +/* Opcode: Null * P2 P3 * *
   965    966   **
   966         -** Write a NULL into register P2.
          967  +** Write a NULL into registers P2.  If P3 greater than P2, then also write
          968  +** NULL into register P3 and ever register in between P2 and P3.  If P3
          969  +** is less than P2 (typically P3 is zero) then only register P2 is
          970  +** set to NULL
   967    971   */
   968    972   case OP_Null: {           /* out2-prerelease */
          973  +  int cnt;
          974  +  cnt = pOp->p3-pOp->p2;
          975  +  assert( pOp->p3<=p->nMem );
   969    976     pOut->flags = MEM_Null;
          977  +  while( cnt>0 ){
          978  +    pOut++;
          979  +    memAboutToChange(p, pOut);
          980  +    MemReleaseExt(pOut);
          981  +    pOut->flags = MEM_Null;
          982  +    cnt--;
          983  +  }
   970    984     break;
   971    985   }
   972    986   
   973    987   
   974    988   /* Opcode: Blob P1 P2 * P4
   975    989   **
   976    990   ** P4 points to a blob of data P1 bytes long.  Store this
................................................................................
  2021   2035     break;
  2022   2036   }
  2023   2037   
  2024   2038   /* Opcode: Once P1 P2 * * *
  2025   2039   **
  2026   2040   ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise,
  2027   2041   ** set the flag and fall through to the next instruction.
         2042  +**
         2043  +** See also: JumpOnce
  2028   2044   */
  2029   2045   case OP_Once: {             /* jump */
  2030   2046     assert( pOp->p1<p->nOnceFlag );
  2031   2047     if( p->aOnceFlag[pOp->p1] ){
  2032   2048       pc = pOp->p2-1;
  2033   2049     }else{
  2034   2050       p->aOnceFlag[pOp->p1] = 1;
  2035   2051     }
  2036   2052     break;
  2037   2053   }
         2054  +
         2055  +/* Opcode: JumpOnce P1 P2 * * *
         2056  +**
         2057  +** Check if OP_Once flag P1 is clear. If so, set the flag and
         2058  +** jump to instruction P2. Otherwise fall through.
         2059  +**
         2060  +** See also: Once
         2061  +*/
         2062  +case OP_JumpOnce: {         /* jump */
         2063  +  assert( pOp->p1<p->nOnceFlag );
         2064  +  if( !p->aOnceFlag[pOp->p1] ){
         2065  +    pc = pOp->p2-1;
         2066  +    p->aOnceFlag[pOp->p1] = 1;
         2067  +  }
         2068  +  break;
         2069  +}
  2038   2070   
  2039   2071   /* Opcode: If P1 P2 P3 * *
  2040   2072   **
  2041   2073   ** Jump to P2 if the value in register P1 is true.  The value
  2042   2074   ** is considered true if it is numeric and non-zero.  If the value
  2043         -** in P1 is NULL then take the jump if P3 is true.
         2075  +** in P1 is NULL then take the jump if P3 is non-zero.
  2044   2076   */
  2045   2077   /* Opcode: IfNot P1 P2 P3 * *
  2046   2078   **
  2047   2079   ** Jump to P2 if the value in register P1 is False.  The value
  2048         -** is considered true if it has a numeric value of zero.  If the value
  2049         -** in P1 is NULL then take the jump if P3 is true.
         2080  +** is considered false if it has a numeric value of zero.  If the value
         2081  +** in P1 is NULL then take the jump if P3 is zero.
  2050   2082   */
  2051   2083   case OP_If:                 /* jump, in1 */
  2052   2084   case OP_IfNot: {            /* jump, in1 */
  2053   2085     int c;
  2054   2086     pIn1 = &aMem[pOp->p1];
  2055   2087     if( pIn1->flags & MEM_Null ){
  2056   2088       c = pOp->p3;
................................................................................
  5065   5097     Mem *pEnd;              /* Last memory cell in new array */
  5066   5098     VdbeFrame *pFrame;      /* New vdbe frame to execute in */
  5067   5099     SubProgram *pProgram;   /* Sub-program to execute */
  5068   5100     void *t;                /* Token identifying trigger */
  5069   5101   
  5070   5102     pProgram = pOp->p4.pProgram;
  5071   5103     pRt = &aMem[pOp->p3];
  5072         -  assert( memIsValid(pRt) );
         5104  +  /*assert( memIsValid(pRt) );*/
  5073   5105     assert( pProgram->nOp>0 );
  5074   5106     
  5075   5107     /* If the p5 flag is clear, then recursive invocation of triggers is 
  5076   5108     ** disabled for backwards compatibility (p5 is set if this sub-program
  5077   5109     ** is really a trigger, not a foreign key action, and the flag set
  5078   5110     ** and cleared by the "PRAGMA recursive_triggers" command is clear).
  5079   5111     ** 
................................................................................
  5242   5274     VdbeFrame *pFrame;
  5243   5275     if( p->pFrame ){
  5244   5276       for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
  5245   5277       pIn1 = &pFrame->aMem[pOp->p1];
  5246   5278     }else{
  5247   5279       pIn1 = &aMem[pOp->p1];
  5248   5280     }
  5249         -  assert( memIsValid(pIn1) );
         5281  +  /*assert( memIsValid(pIn1) );  FIXME */
  5250   5282     sqlite3VdbeMemIntegerify(pIn1);
  5251   5283     pIn2 = &aMem[pOp->p2];
  5252   5284     sqlite3VdbeMemIntegerify(pIn2);
  5253   5285     if( pIn1->u.i<pIn2->u.i){
  5254   5286       pIn1->u.i = pIn2->u.i;
  5255   5287     }
  5256   5288     break;

Changes to src/vdbeaux.c.

   909    909       }
   910    910       case P4_REAL: {
   911    911         sqlite3_snprintf(nTemp, zTemp, "%.16g", *pOp->p4.pReal);
   912    912         break;
   913    913       }
   914    914       case P4_MEM: {
   915    915         Mem *pMem = pOp->p4.pMem;
   916         -      assert( (pMem->flags & MEM_Null)==0 );
   917    916         if( pMem->flags & MEM_Str ){
   918    917           zP4 = pMem->z;
   919    918         }else if( pMem->flags & MEM_Int ){
   920    919           sqlite3_snprintf(nTemp, zTemp, "%lld", pMem->u.i);
   921    920         }else if( pMem->flags & MEM_Real ){
   922    921           sqlite3_snprintf(nTemp, zTemp, "%.16g", pMem->r);
          922  +      }else if( pMem->flags & MEM_Null ){
          923  +        sqlite3_snprintf(nTemp, zTemp, "NULL");
   923    924         }else{
   924    925           assert( pMem->flags & MEM_Blob );
   925    926           zP4 = "(blob)";
   926    927         }
   927    928         break;
   928    929       }
   929    930   #ifndef SQLITE_OMIT_VIRTUALTABLE
................................................................................
  1090   1091         if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){
  1091   1092           sqlite3VdbeMemRelease(p);
  1092   1093         }else if( p->zMalloc ){
  1093   1094           sqlite3DbFree(db, p->zMalloc);
  1094   1095           p->zMalloc = 0;
  1095   1096         }
  1096   1097   
  1097         -      p->flags = MEM_Null;
         1098  +      p->flags = MEM_Invalid;
  1098   1099       }
  1099   1100       db->mallocFailed = malloc_failed;
  1100   1101     }
  1101   1102   }
  1102   1103   
  1103   1104   /*
  1104   1105   ** Delete a VdbeFrame object and its contents. VdbeFrame objects are
................................................................................
  1528   1529       nByte = 0;
  1529   1530       p->aMem = allocSpace(p->aMem, nMem*sizeof(Mem), &zCsr, zEnd, &nByte);
  1530   1531       p->aVar = allocSpace(p->aVar, nVar*sizeof(Mem), &zCsr, zEnd, &nByte);
  1531   1532       p->apArg = allocSpace(p->apArg, nArg*sizeof(Mem*), &zCsr, zEnd, &nByte);
  1532   1533       p->azVar = allocSpace(p->azVar, nVar*sizeof(char*), &zCsr, zEnd, &nByte);
  1533   1534       p->apCsr = allocSpace(p->apCsr, nCursor*sizeof(VdbeCursor*),
  1534   1535                             &zCsr, zEnd, &nByte);
  1535         -    p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce*sizeof(u8), 
  1536         -                          &zCsr, zEnd, &nByte);
         1536  +    p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, &zCsr, zEnd, &nByte);
  1537   1537       if( nByte ){
  1538   1538         p->pFree = sqlite3DbMallocZero(db, nByte);
  1539   1539       }
  1540   1540       zCsr = p->pFree;
  1541   1541       zEnd = &zCsr[nByte];
  1542   1542     }while( nByte && !db->mallocFailed );
  1543   1543   
................................................................................
  1555   1555       memcpy(p->azVar, pParse->azVar, p->nzVar*sizeof(p->azVar[0]));
  1556   1556       memset(pParse->azVar, 0, pParse->nzVar*sizeof(pParse->azVar[0]));
  1557   1557     }
  1558   1558     if( p->aMem ){
  1559   1559       p->aMem--;                      /* aMem[] goes from 1..nMem */
  1560   1560       p->nMem = nMem;                 /*       not from 0..nMem-1 */
  1561   1561       for(n=1; n<=nMem; n++){
  1562         -      p->aMem[n].flags = MEM_Null;
         1562  +      p->aMem[n].flags = MEM_Invalid;
  1563   1563         p->aMem[n].db = db;
  1564   1564       }
  1565   1565     }
         1566  +  if( p->aOnceFlag ) memset(p->aOnceFlag, 0, p->nOnceFlag);
  1566   1567     p->explain = pParse->explain;
  1567   1568     sqlite3VdbeRewind(p);
  1568   1569   }
  1569   1570   
  1570   1571   /*
  1571   1572   ** Close a VDBE cursor and release all the resources that cursor 
  1572   1573   ** happens to hold.
................................................................................
  1645   1646       releaseMemArray(&p->aMem[1], p->nMem);
  1646   1647     }
  1647   1648     while( p->pDelFrame ){
  1648   1649       VdbeFrame *pDel = p->pDelFrame;
  1649   1650       p->pDelFrame = pDel->pParent;
  1650   1651       sqlite3VdbeFrameDelete(pDel);
  1651   1652     }
  1652         -  memset(p->aOnceFlag, 0, p->nOnceFlag);
  1653   1653   }
  1654   1654   
  1655   1655   /*
  1656   1656   ** Clean up the VM after execution.
  1657   1657   **
  1658   1658   ** This routine will automatically close any cursors, lists, and/or
  1659   1659   ** sorters that were left open.  It also deletes the values of
................................................................................
  1662   1662   static void Cleanup(Vdbe *p){
  1663   1663     sqlite3 *db = p->db;
  1664   1664   
  1665   1665   #ifdef SQLITE_DEBUG
  1666   1666     /* Execute assert() statements to ensure that the Vdbe.apCsr[] and 
  1667   1667     ** Vdbe.aMem[] arrays have already been cleaned up.  */
  1668   1668     int i;
  1669         -  for(i=0; i<p->nCursor; i++) assert( p->apCsr==0 || p->apCsr[i]==0 );
  1670         -  for(i=1; i<=p->nMem; i++) assert( p->aMem==0 || p->aMem[i].flags==MEM_Null );
         1669  +  if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
         1670  +  if( p->aMem ){
         1671  +    for(i=1; i<=p->nMem; i++) assert( p->aMem[i].flags==MEM_Invalid );
         1672  +  }
  1671   1673   #endif
  1672   1674   
  1673   1675     sqlite3DbFree(db, p->zErrMsg);
  1674   1676     p->zErrMsg = 0;
  1675   1677     p->pResultSet = 0;
  1676   1678   }
  1677   1679   
................................................................................
  2131   2133     ** state.  We need to rollback the statement transaction, if there is
  2132   2134     ** one, or the complete transaction if there is no statement transaction.
  2133   2135     */
  2134   2136   
  2135   2137     if( p->db->mallocFailed ){
  2136   2138       p->rc = SQLITE_NOMEM;
  2137   2139     }
         2140  +  if( p->aOnceFlag ) memset(p->aOnceFlag, 0, p->nOnceFlag);
  2138   2141     closeAllCursors(p);
  2139   2142     if( p->magic!=VDBE_MAGIC_RUN ){
  2140   2143       return SQLITE_OK;
  2141   2144     }
  2142   2145     checkActiveVdbeCnt(db);
  2143   2146   
  2144   2147     /* No commit or rollback needed if the program never started */