/ Check-in [5a00d24b]
Login

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

Overview
Comment:Merge performance enhancements into trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 5a00d24b279424d257781ec3f1227e72a5d56f57
User & Date: drh 2011-08-29 03:08:47
Context
2011-08-29
11:56
Back out [05c9832e5f6eb] since it was causing a performance regression with no obvious benefit. check-in: 639cc85a user: drh tags: trunk
03:08
Merge performance enhancements into trunk. check-in: 5a00d24b user: drh tags: trunk
02:49
About a 1% overall performance improvement by using a macro to avoid no-op calls to sqlite3MemReleaseExternal(). Closed-Leaf check-in: ff71d20a user: drh tags: experimental
2011-08-26
20:55
Fix several harmless compiler warnings and a documentation bug. check-in: 5454d0fe user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

  3475   3475     assert( wrFlag==0 || p->inTrans==TRANS_WRITE );
  3476   3476     assert( pBt->pPage1 && pBt->pPage1->aData );
  3477   3477   
  3478   3478     if( NEVER(wrFlag && pBt->readOnly) ){
  3479   3479       return SQLITE_READONLY;
  3480   3480     }
  3481   3481     if( iTable==1 && btreePagecount(pBt)==0 ){
  3482         -    return SQLITE_EMPTY;
         3482  +    assert( wrFlag==0 );
         3483  +    iTable = 0;
  3483   3484     }
  3484   3485   
  3485   3486     /* Now that no other errors can occur, finish filling in the BtCursor
  3486   3487     ** variables and link the cursor into the BtShared list.  */
  3487   3488     pCur->pgnoRoot = (Pgno)iTable;
  3488   3489     pCur->iPage = -1;
  3489   3490     pCur->pKeyInfo = pKeyInfo;
................................................................................
  4229   4230   
  4230   4231     if( pCur->iPage>=0 ){
  4231   4232       int i;
  4232   4233       for(i=1; i<=pCur->iPage; i++){
  4233   4234         releasePage(pCur->apPage[i]);
  4234   4235       }
  4235   4236       pCur->iPage = 0;
         4237  +  }else if( pCur->pgnoRoot==0 ){
         4238  +    pCur->eState = CURSOR_INVALID;
         4239  +    return SQLITE_OK;
  4236   4240     }else{
  4237   4241       rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->apPage[0]);
  4238   4242       if( rc!=SQLITE_OK ){
  4239   4243         pCur->eState = CURSOR_INVALID;
  4240   4244         return rc;
  4241   4245       }
  4242   4246       pCur->iPage = 0;
................................................................................
  4338   4342     int rc;
  4339   4343   
  4340   4344     assert( cursorHoldsMutex(pCur) );
  4341   4345     assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
  4342   4346     rc = moveToRoot(pCur);
  4343   4347     if( rc==SQLITE_OK ){
  4344   4348       if( pCur->eState==CURSOR_INVALID ){
  4345         -      assert( pCur->apPage[pCur->iPage]->nCell==0 );
         4349  +      assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
  4346   4350         *pRes = 1;
  4347   4351       }else{
  4348   4352         assert( pCur->apPage[pCur->iPage]->nCell>0 );
  4349   4353         *pRes = 0;
  4350   4354         rc = moveToLeftmost(pCur);
  4351   4355       }
  4352   4356     }
................................................................................
  4377   4381   #endif
  4378   4382       return SQLITE_OK;
  4379   4383     }
  4380   4384   
  4381   4385     rc = moveToRoot(pCur);
  4382   4386     if( rc==SQLITE_OK ){
  4383   4387       if( CURSOR_INVALID==pCur->eState ){
  4384         -      assert( pCur->apPage[pCur->iPage]->nCell==0 );
         4388  +      assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
  4385   4389         *pRes = 1;
  4386   4390       }else{
  4387   4391         assert( pCur->eState==CURSOR_VALID );
  4388   4392         *pRes = 0;
  4389   4393         rc = moveToRightmost(pCur);
  4390   4394         pCur->atLast = rc==SQLITE_OK ?1:0;
  4391   4395       }
................................................................................
  4450   4454       }
  4451   4455     }
  4452   4456   
  4453   4457     rc = moveToRoot(pCur);
  4454   4458     if( rc ){
  4455   4459       return rc;
  4456   4460     }
  4457         -  assert( pCur->apPage[pCur->iPage] );
  4458         -  assert( pCur->apPage[pCur->iPage]->isInit );
  4459         -  assert( pCur->apPage[pCur->iPage]->nCell>0 || pCur->eState==CURSOR_INVALID );
         4461  +  assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage] );
         4462  +  assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->isInit );
         4463  +  assert( pCur->eState==CURSOR_INVALID || pCur->apPage[pCur->iPage]->nCell>0 );
  4460   4464     if( pCur->eState==CURSOR_INVALID ){
  4461   4465       *pRes = -1;
  4462         -    assert( pCur->apPage[pCur->iPage]->nCell==0 );
         4466  +    assert( pCur->pgnoRoot==0 || pCur->apPage[pCur->iPage]->nCell==0 );
  4463   4467       return SQLITE_OK;
  4464   4468     }
  4465   4469     assert( pCur->apPage[0]->intKey || pIdxKey );
  4466   4470     for(;;){
  4467   4471       int lwr, upr, idx;
  4468   4472       Pgno chldPg;
  4469   4473       MemPage *pPage = pCur->apPage[pCur->iPage];
................................................................................
  7372   7376   ** SQLITE_OK is returned if the operation is successfully executed. 
  7373   7377   ** Otherwise, if an error is encountered (i.e. an IO error or database
  7374   7378   ** corruption) an SQLite error code is returned.
  7375   7379   */
  7376   7380   int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
  7377   7381     i64 nEntry = 0;                      /* Value to return in *pnEntry */
  7378   7382     int rc;                              /* Return code */
         7383  +
         7384  +  if( pCur->pgnoRoot==0 ){
         7385  +    *pnEntry = 0;
         7386  +    return SQLITE_OK;
         7387  +  }
  7379   7388     rc = moveToRoot(pCur);
  7380   7389   
  7381   7390     /* Unless an error occurs, the following loop runs one iteration for each
  7382   7391     ** page in the B-Tree structure (not including overflow pages). 
  7383   7392     */
  7384   7393     while( rc==SQLITE_OK ){
  7385   7394       int iIdx;                          /* Index of child node in parent */

Changes to src/vdbe.c.

   669    669       */
   670    670       assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] );
   671    671       if( pOp->opflags & OPFLG_OUT2_PRERELEASE ){
   672    672         assert( pOp->p2>0 );
   673    673         assert( pOp->p2<=p->nMem );
   674    674         pOut = &aMem[pOp->p2];
   675    675         memAboutToChange(p, pOut);
   676         -      sqlite3VdbeMemReleaseExternal(pOut);
          676  +      MemReleaseExt(pOut);
   677    677         pOut->flags = MEM_Int;
   678    678       }
   679    679   
   680    680       /* Sanity checking on other operands */
   681    681   #ifdef SQLITE_DEBUG
   682    682       if( (pOp->opflags & OPFLG_IN1)!=0 ){
   683    683         assert( pOp->p1>0 );
................................................................................
  2114   2114     Mem sMem;          /* For storing the record being decoded */
  2115   2115     u8 *zIdx;          /* Index into header */
  2116   2116     u8 *zEndHdr;       /* Pointer to first byte after the header */
  2117   2117     u32 offset;        /* Offset into the data */
  2118   2118     u32 szField;       /* Number of bytes in the content of a field */
  2119   2119     int szHdr;         /* Size of the header size field at start of record */
  2120   2120     int avail;         /* Number of bytes of available data */
         2121  +  u32 t;             /* A type code from the record header */
  2121   2122     Mem *pReg;         /* PseudoTable input register */
  2122   2123   
  2123   2124   
  2124   2125     p1 = pOp->p1;
  2125   2126     p2 = pOp->p2;
  2126   2127     pC = 0;
  2127   2128     memset(&sMem, 0, sizeof(sMem));
  2128   2129     assert( p1<p->nCursor );
  2129   2130     assert( pOp->p3>0 && pOp->p3<=p->nMem );
  2130   2131     pDest = &aMem[pOp->p3];
  2131   2132     memAboutToChange(p, pDest);
  2132         -  MemSetTypeFlag(pDest, MEM_Null);
  2133   2133     zRec = 0;
  2134   2134   
  2135   2135     /* This block sets the variable payloadSize to be the total number of
  2136   2136     ** bytes in the record.
  2137   2137     **
  2138   2138     ** zRec is set to be the complete text of the record if it is available.
  2139   2139     ** The complete record text is always available for pseudo-tables
................................................................................
  2169   2169         assert( (payloadSize64 & SQLITE_MAX_U32)==(u64)payloadSize64 );
  2170   2170         payloadSize = (u32)payloadSize64;
  2171   2171       }else{
  2172   2172         assert( sqlite3BtreeCursorIsValid(pCrsr) );
  2173   2173         rc = sqlite3BtreeDataSize(pCrsr, &payloadSize);
  2174   2174         assert( rc==SQLITE_OK );   /* DataSize() cannot fail */
  2175   2175       }
  2176         -  }else if( pC->pseudoTableReg>0 ){
         2176  +  }else if( ALWAYS(pC->pseudoTableReg>0) ){
  2177   2177       pReg = &aMem[pC->pseudoTableReg];
  2178   2178       assert( pReg->flags & MEM_Blob );
  2179   2179       assert( memIsValid(pReg) );
  2180   2180       payloadSize = pReg->n;
  2181   2181       zRec = pReg->z;
  2182   2182       pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr;
  2183   2183       assert( payloadSize==0 || zRec!=0 );
  2184   2184     }else{
  2185   2185       /* Consider the row to be NULL */
  2186   2186       payloadSize = 0;
  2187   2187     }
  2188   2188   
  2189         -  /* If payloadSize is 0, then just store a NULL */
         2189  +  /* If payloadSize is 0, then just store a NULL.  This can happen because of
         2190  +  ** nullRow or because of a corrupt database. */
  2190   2191     if( payloadSize==0 ){
  2191         -    assert( pDest->flags&MEM_Null );
         2192  +    MemSetTypeFlag(pDest, MEM_Null);
  2192   2193       goto op_column_out;
  2193   2194     }
  2194   2195     assert( db->aLimit[SQLITE_LIMIT_LENGTH]>=0 );
  2195   2196     if( payloadSize > (u32)db->aLimit[SQLITE_LIMIT_LENGTH] ){
  2196   2197       goto too_big;
  2197   2198     }
  2198   2199   
................................................................................
  2291   2292       ** arrays.  aType[i] will contain the type integer for the i-th
  2292   2293       ** column and aOffset[i] will contain the offset from the beginning
  2293   2294       ** of the record to the start of the data for the i-th column
  2294   2295       */
  2295   2296       for(i=0; i<nField; i++){
  2296   2297         if( zIdx<zEndHdr ){
  2297   2298           aOffset[i] = offset;
  2298         -        zIdx += getVarint32(zIdx, aType[i]);
  2299         -        szField = sqlite3VdbeSerialTypeLen(aType[i]);
         2299  +        if( zIdx[0]<0x80 ){
         2300  +          t = zIdx[0];
         2301  +          zIdx++;
         2302  +        }else{
         2303  +          zIdx += sqlite3GetVarint32(zIdx, &t);
         2304  +        }
         2305  +        aType[i] = t;
         2306  +        szField = sqlite3VdbeSerialTypeLen(t);
  2300   2307           offset += szField;
  2301   2308           if( offset<szField ){  /* True if offset overflows */
  2302   2309             zIdx = &zEndHdr[1];  /* Forces SQLITE_CORRUPT return below */
  2303   2310             break;
  2304   2311           }
  2305   2312         }else{
  2306   2313           /* If i is less that nField, then there are less fields in this
................................................................................
  2333   2340     ** then there are not enough fields in the record to satisfy the
  2334   2341     ** request.  In this case, set the value NULL or to P4 if P4 is
  2335   2342     ** a pointer to a Mem object.
  2336   2343     */
  2337   2344     if( aOffset[p2] ){
  2338   2345       assert( rc==SQLITE_OK );
  2339   2346       if( zRec ){
  2340         -      sqlite3VdbeMemReleaseExternal(pDest);
         2347  +      MemReleaseExt(pDest);
  2341   2348         sqlite3VdbeSerialGet((u8 *)&zRec[aOffset[p2]], aType[p2], pDest);
  2342   2349       }else{
  2343   2350         len = sqlite3VdbeSerialTypeLen(aType[p2]);
  2344   2351         sqlite3VdbeMemMove(&sMem, pDest);
  2345   2352         rc = sqlite3VdbeMemFromBtree(pCrsr, aOffset[p2], len, pC->isIndex, &sMem);
  2346   2353         if( rc!=SQLITE_OK ){
  2347   2354           goto op_column_out;
................................................................................
  2350   2357         sqlite3VdbeSerialGet((u8*)zData, aType[p2], pDest);
  2351   2358       }
  2352   2359       pDest->enc = encoding;
  2353   2360     }else{
  2354   2361       if( pOp->p4type==P4_MEM ){
  2355   2362         sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static);
  2356   2363       }else{
  2357         -      assert( pDest->flags&MEM_Null );
         2364  +      MemSetTypeFlag(pDest, MEM_Null);
  2358   2365       }
  2359   2366     }
  2360   2367   
  2361   2368     /* If we dynamically allocated space to hold the data (in the
  2362   2369     ** sqlite3VdbeMemFromBtree() call above) then transfer control of that
  2363   2370     ** dynamically allocated space over to the pDest structure.
  2364   2371     ** This prevents a memory copy.
................................................................................
  2546   2553   */
  2547   2554   #ifndef SQLITE_OMIT_BTREECOUNT
  2548   2555   case OP_Count: {         /* out2-prerelease */
  2549   2556     i64 nEntry;
  2550   2557     BtCursor *pCrsr;
  2551   2558   
  2552   2559     pCrsr = p->apCsr[pOp->p1]->pCursor;
  2553         -  if( pCrsr ){
         2560  +  if( ALWAYS(pCrsr) ){
  2554   2561       rc = sqlite3BtreeCount(pCrsr, &nEntry);
  2555   2562     }else{
  2556   2563       nEntry = 0;
  2557   2564     }
  2558   2565     pOut->u.i = nEntry;
  2559   2566     break;
  2560   2567   }
................................................................................
  3108   3115     pCur = allocateCursor(p, pOp->p1, nField, iDb, 1);
  3109   3116     if( pCur==0 ) goto no_mem;
  3110   3117     pCur->nullRow = 1;
  3111   3118     pCur->isOrdered = 1;
  3112   3119     rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor);
  3113   3120     pCur->pKeyInfo = pKeyInfo;
  3114   3121   
  3115         -  /* Since it performs no memory allocation or IO, the only values that
  3116         -  ** sqlite3BtreeCursor() may return are SQLITE_EMPTY and SQLITE_OK. 
  3117         -  ** SQLITE_EMPTY is only returned when attempting to open the table
  3118         -  ** rooted at page 1 of a zero-byte database.  */
  3119         -  assert( rc==SQLITE_EMPTY || rc==SQLITE_OK );
  3120         -  if( rc==SQLITE_EMPTY ){
  3121         -    pCur->pCursor = 0;
  3122         -    rc = SQLITE_OK;
  3123         -  }
         3122  +  /* Since it performs no memory allocation or IO, the only value that
         3123  +  ** sqlite3BtreeCursor() may return is SQLITE_OK. */
         3124  +  assert( rc==SQLITE_OK );
  3124   3125   
  3125   3126     /* Set the VdbeCursor.isTable and isIndex variables. Previous versions of
  3126   3127     ** SQLite used to check if the root-page flags were sane at this point
  3127   3128     ** and report database corruption if they were not, but this check has
  3128   3129     ** since moved into the btree layer.  */  
  3129   3130     pCur->isTable = pOp->p4type!=P4_KEYINFO;
  3130   3131     pCur->isIndex = !pCur->isTable;
................................................................................
  3329   3330     pC = p->apCsr[pOp->p1];
  3330   3331     assert( pC!=0 );
  3331   3332     assert( pC->pseudoTableReg==0 );
  3332   3333     assert( OP_SeekLe == OP_SeekLt+1 );
  3333   3334     assert( OP_SeekGe == OP_SeekLt+2 );
  3334   3335     assert( OP_SeekGt == OP_SeekLt+3 );
  3335   3336     assert( pC->isOrdered );
  3336         -  if( pC->pCursor!=0 ){
         3337  +  if( ALWAYS(pC->pCursor!=0) ){
  3337   3338       oc = pOp->opcode;
  3338   3339       pC->nullRow = 0;
  3339   3340       if( pC->isTable ){
  3340   3341         /* The input value in P3 might be of any type: integer, real, string,
  3341   3342         ** blob, or NULL.  But it needs to be an integer before we can do
  3342   3343         ** the seek, so covert it. */
  3343   3344         pIn3 = &aMem[pOp->p3];
................................................................................
  3687   3688     assert( pIn3->flags & MEM_Int );
  3688   3689     assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  3689   3690     pC = p->apCsr[pOp->p1];
  3690   3691     assert( pC!=0 );
  3691   3692     assert( pC->isTable );
  3692   3693     assert( pC->pseudoTableReg==0 );
  3693   3694     pCrsr = pC->pCursor;
  3694         -  if( pCrsr!=0 ){
         3695  +  if( ALWAYS(pCrsr!=0) ){
  3695   3696       res = 0;
  3696   3697       iKey = pIn3->u.i;
  3697   3698       rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
  3698   3699       pC->lastRowid = pIn3->u.i;
  3699   3700       pC->rowidIsValid = res==0 ?1:0;
  3700   3701       pC->nullRow = 0;
  3701   3702       pC->cacheStatus = CACHE_STALE;
................................................................................
  4214   4215     VdbeCursor *pC;
  4215   4216   
  4216   4217     assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  4217   4218     pC = p->apCsr[pOp->p1];
  4218   4219     assert( pC!=0 );
  4219   4220     pC->nullRow = 1;
  4220   4221     pC->rowidIsValid = 0;
         4222  +  assert( pC->pCursor || pC->pVtabCursor );
  4221   4223     if( pC->pCursor ){
  4222   4224       sqlite3BtreeClearCursor(pC->pCursor);
  4223   4225     }
  4224   4226     break;
  4225   4227   }
  4226   4228   
  4227   4229   /* Opcode: Last P1 P2 * * *
................................................................................
  4237   4239     BtCursor *pCrsr;
  4238   4240     int res;
  4239   4241   
  4240   4242     assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  4241   4243     pC = p->apCsr[pOp->p1];
  4242   4244     assert( pC!=0 );
  4243   4245     pCrsr = pC->pCursor;
  4244         -  if( pCrsr==0 ){
         4246  +  if( NEVER(pCrsr==0) ){
  4245   4247       res = 1;
  4246   4248     }else{
  4247   4249       rc = sqlite3BtreeLast(pCrsr, &res);
  4248   4250     }
  4249   4251     pC->nullRow = (u8)res;
  4250   4252     pC->deferredMoveto = 0;
  4251   4253     pC->rowidIsValid = 0;
................................................................................
  4292   4294   
  4293   4295     assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  4294   4296     pC = p->apCsr[pOp->p1];
  4295   4297     assert( pC!=0 );
  4296   4298     res = 1;
  4297   4299     if( isSorter(pC) ){
  4298   4300       rc = sqlite3VdbeSorterRewind(db, pC, &res);
  4299         -  }else if( (pCrsr = pC->pCursor)!=0 ){
         4301  +  }else{
         4302  +    pCrsr = pC->pCursor;
         4303  +    assert( pCrsr );
  4300   4304       rc = sqlite3BtreeFirst(pCrsr, &res);
  4301   4305       pC->atFirst = res==0 ?1:0;
  4302   4306       pC->deferredMoveto = 0;
  4303   4307       pC->cacheStatus = CACHE_STALE;
  4304   4308       pC->rowidIsValid = 0;
  4305   4309     }
  4306   4310     pC->nullRow = (u8)res;
................................................................................
  4307   4311     assert( pOp->p2>0 && pOp->p2<p->nOp );
  4308   4312     if( res ){
  4309   4313       pc = pOp->p2 - 1;
  4310   4314     }
  4311   4315     break;
  4312   4316   }
  4313   4317   
  4314         -/* Opcode: Next P1 P2 * * P5
         4318  +/* Opcode: Next P1 P2 * P4 P5
  4315   4319   **
  4316   4320   ** Advance cursor P1 so that it points to the next key/data pair in its
  4317   4321   ** table or index.  If there are no more key/value pairs then fall through
  4318   4322   ** to the following instruction.  But if the cursor advance was successful,
  4319   4323   ** jump immediately to P2.
  4320   4324   **
  4321   4325   ** The P1 cursor must be for a real table, not a pseudo-table.
         4326  +**
         4327  +** P4 is always of type P4_ADVANCE. The function pointer points to
         4328  +** sqlite3BtreeNext().
  4322   4329   **
  4323   4330   ** If P5 is positive and the jump is taken, then event counter
  4324   4331   ** number P5-1 in the prepared statement is incremented.
  4325   4332   **
  4326   4333   ** See also: Prev
  4327   4334   */
  4328   4335   /* Opcode: Prev P1 P2 * * P5
................................................................................
  4329   4336   **
  4330   4337   ** Back up cursor P1 so that it points to the previous key/data pair in its
  4331   4338   ** table or index.  If there is no previous key/value pairs then fall through
  4332   4339   ** to the following instruction.  But if the cursor backup was successful,
  4333   4340   ** jump immediately to P2.
  4334   4341   **
  4335   4342   ** The P1 cursor must be for a real table, not a pseudo-table.
         4343  +**
         4344  +** P4 is always of type P4_ADVANCE. The function pointer points to
         4345  +** sqlite3BtreePrevious().
  4336   4346   **
  4337   4347   ** If P5 is positive and the jump is taken, then event counter
  4338   4348   ** number P5-1 in the prepared statement is incremented.
  4339   4349   */
  4340   4350   case OP_Prev:          /* jump */
  4341   4351   case OP_Next: {        /* jump */
  4342   4352     VdbeCursor *pC;
  4343         -  BtCursor *pCrsr;
  4344   4353     int res;
  4345   4354   
  4346   4355     CHECK_FOR_INTERRUPT;
  4347   4356     assert( pOp->p1>=0 && pOp->p1<p->nCursor );
  4348   4357     assert( pOp->p5<=ArraySize(p->aCounter) );
  4349   4358     pC = p->apCsr[pOp->p1];
  4350   4359     if( pC==0 ){
  4351   4360       break;  /* See ticket #2273 */
  4352   4361     }
  4353   4362     if( isSorter(pC) ){
  4354   4363       assert( pOp->opcode==OP_Next );
  4355   4364       rc = sqlite3VdbeSorterNext(db, pC, &res);
  4356   4365     }else{
  4357         -    pCrsr = pC->pCursor;
  4358         -    if( pCrsr==0 ){
  4359         -      pC->nullRow = 1;
  4360         -      break;
  4361         -    }
  4362   4366       res = 1;
  4363   4367       assert( pC->deferredMoveto==0 );
  4364         -    rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(pCrsr, &res) :
  4365         -                                sqlite3BtreePrevious(pCrsr, &res);
         4368  +    assert( pC->pCursor );
         4369  +    assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
         4370  +    assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
         4371  +    rc = pOp->p4.xAdvance(pC->pCursor, &res);
  4366   4372     }
  4367   4373     pC->nullRow = (u8)res;
  4368   4374     pC->cacheStatus = CACHE_STALE;
  4369   4375     if( res==0 ){
  4370   4376       pc = pOp->p2 - 1;
  4371   4377       if( pOp->p5 ) p->aCounter[pOp->p5-1]++;
  4372   4378   #ifdef SQLITE_TEST

Changes to src/vdbe.h.

    57     57       VdbeFunc *pVdbeFunc;   /* Used when p4type is P4_VDBEFUNC */
    58     58       CollSeq *pColl;        /* Used when p4type is P4_COLLSEQ */
    59     59       Mem *pMem;             /* Used when p4type is P4_MEM */
    60     60       VTable *pVtab;         /* Used when p4type is P4_VTAB */
    61     61       KeyInfo *pKeyInfo;     /* Used when p4type is P4_KEYINFO */
    62     62       int *ai;               /* Used when p4type is P4_INTARRAY */
    63     63       SubProgram *pProgram;  /* Used when p4type is P4_SUBPROGRAM */
           64  +    int (*xAdvance)(BtCursor *, int *);
    64     65     } p4;
    65     66   #ifdef SQLITE_DEBUG
    66     67     char *zComment;          /* Comment to improve readability */
    67     68   #endif
    68     69   #ifdef VDBE_PROFILE
    69     70     int cnt;                 /* Number of times this instruction was executed */
    70     71     u64 cycles;              /* Total time spent executing this instruction */
................................................................................
   112    113   #define P4_VTAB     (-10) /* P4 is a pointer to an sqlite3_vtab structure */
   113    114   #define P4_MPRINTF  (-11) /* P4 is a string obtained from sqlite3_mprintf() */
   114    115   #define P4_REAL     (-12) /* P4 is a 64-bit floating point value */
   115    116   #define P4_INT64    (-13) /* P4 is a 64-bit signed integer */
   116    117   #define P4_INT32    (-14) /* P4 is a 32-bit signed integer */
   117    118   #define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
   118    119   #define P4_SUBPROGRAM  (-18) /* P4 is a pointer to a SubProgram structure */
          120  +#define P4_ADVANCE  (-19) /* P4 is a pointer to BtreeNext() or BtreePrev() */
   119    121   
   120    122   /* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure
   121    123   ** is made.  That copy is freed when the Vdbe is finalized.  But if the
   122    124   ** argument is P4_KEYINFO_HANDOFF, the passed in pointer is used.  It still
   123    125   ** gets freed when the Vdbe is finalized so it still should be obtained
   124    126   ** from a single sqliteMalloc().  But no copy is made and the calling
   125    127   ** function should *not* try to free the KeyInfo.

Changes to src/vdbeInt.h.

   380    380   double sqlite3VdbeRealValue(Mem*);
   381    381   void sqlite3VdbeIntegerAffinity(Mem*);
   382    382   int sqlite3VdbeMemRealify(Mem*);
   383    383   int sqlite3VdbeMemNumerify(Mem*);
   384    384   int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
   385    385   void sqlite3VdbeMemRelease(Mem *p);
   386    386   void sqlite3VdbeMemReleaseExternal(Mem *p);
          387  +#define MemReleaseExt(X)  \
          388  +  if((X)->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame)) \
          389  +    sqlite3VdbeMemReleaseExternal(X);
   387    390   int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
   388    391   const char *sqlite3OpcodeName(int);
   389    392   int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
   390    393   int sqlite3VdbeCloseStatement(Vdbe *, int);
   391    394   void sqlite3VdbeFrameDelete(VdbeFrame*);
   392    395   int sqlite3VdbeFrameRestore(VdbeFrame *);
   393    396   void sqlite3VdbeMemStoreType(Mem *pMem);

Changes to src/vdbeaux.c.

   429    429       }else if( opcode==OP_VFilter ){
   430    430         int n;
   431    431         assert( p->nOp - i >= 3 );
   432    432         assert( pOp[-1].opcode==OP_Integer );
   433    433         n = pOp[-1].p1;
   434    434         if( n>nMaxArgs ) nMaxArgs = n;
   435    435   #endif
          436  +    }else if( opcode==OP_Next ){
          437  +      pOp->p4.xAdvance = sqlite3BtreeNext;
          438  +      pOp->p4type = P4_ADVANCE;
          439  +    }else if( opcode==OP_Prev ){
          440  +      pOp->p4.xAdvance = sqlite3BtreePrevious;
          441  +      pOp->p4type = P4_ADVANCE;
   436    442       }
   437    443   
   438    444       if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
   439    445         assert( -1-pOp->p2<p->nLabel );
   440    446         pOp->p2 = aLabel[-1-pOp->p2];
   441    447       }
   442    448     }
................................................................................
   934    940       case P4_INTARRAY: {
   935    941         sqlite3_snprintf(nTemp, zTemp, "intarray");
   936    942         break;
   937    943       }
   938    944       case P4_SUBPROGRAM: {
   939    945         sqlite3_snprintf(nTemp, zTemp, "program");
   940    946         break;
          947  +    }
          948  +    case P4_ADVANCE: {
          949  +      zTemp[0] = 0;
          950  +      break;
   941    951       }
   942    952       default: {
   943    953         zP4 = pOp->p4.z;
   944    954         if( zP4==0 ){
   945    955           zP4 = zTemp;
   946    956           zTemp[0] = 0;
   947    957         }

Changes to src/vdbemem.c.

   267    267   /*
   268    268   ** If the memory cell contains a string value that must be freed by
   269    269   ** invoking an external callback, free it now. Calling this function
   270    270   ** does not free any Mem.zMalloc buffer.
   271    271   */
   272    272   void sqlite3VdbeMemReleaseExternal(Mem *p){
   273    273     assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );
   274         -  testcase( p->flags & MEM_Agg );
   275         -  testcase( p->flags & MEM_Dyn );
   276         -  testcase( p->flags & MEM_RowSet );
   277         -  testcase( p->flags & MEM_Frame );
   278         -  if( p->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame) ){
   279         -    if( p->flags&MEM_Agg ){
   280         -      sqlite3VdbeMemFinalize(p, p->u.pDef);
   281         -      assert( (p->flags & MEM_Agg)==0 );
   282         -      sqlite3VdbeMemRelease(p);
   283         -    }else if( p->flags&MEM_Dyn && p->xDel ){
   284         -      assert( (p->flags&MEM_RowSet)==0 );
   285         -      p->xDel((void *)p->z);
   286         -      p->xDel = 0;
   287         -    }else if( p->flags&MEM_RowSet ){
   288         -      sqlite3RowSetClear(p->u.pRowSet);
   289         -    }else if( p->flags&MEM_Frame ){
   290         -      sqlite3VdbeMemSetNull(p);
   291         -    }
          274  +  if( p->flags&MEM_Agg ){
          275  +    sqlite3VdbeMemFinalize(p, p->u.pDef);
          276  +    assert( (p->flags & MEM_Agg)==0 );
          277  +    sqlite3VdbeMemRelease(p);
          278  +  }else if( p->flags&MEM_Dyn && p->xDel ){
          279  +    assert( (p->flags&MEM_RowSet)==0 );
          280  +    p->xDel((void *)p->z);
          281  +    p->xDel = 0;
          282  +  }else if( p->flags&MEM_RowSet ){
          283  +    sqlite3RowSetClear(p->u.pRowSet);
          284  +  }else if( p->flags&MEM_Frame ){
          285  +    sqlite3VdbeMemSetNull(p);
   292    286     }
   293    287   }
   294    288   
   295    289   /*
   296    290   ** Release any memory held by the Mem. This may leave the Mem in an
   297    291   ** inconsistent state, for example with (Mem.z==0) and
   298    292   ** (Mem.type==SQLITE_TEXT).
   299    293   */
   300    294   void sqlite3VdbeMemRelease(Mem *p){
   301         -  sqlite3VdbeMemReleaseExternal(p);
          295  +  MemReleaseExt(p);
   302    296     sqlite3DbFree(p->db, p->zMalloc);
   303    297     p->z = 0;
   304    298     p->zMalloc = 0;
   305    299     p->xDel = 0;
   306    300   }
   307    301   
   308    302   /*
................................................................................
   616    610   ** Make an shallow copy of pFrom into pTo.  Prior contents of
   617    611   ** pTo are freed.  The pFrom->z field is not duplicated.  If
   618    612   ** pFrom->z is used, then pTo->z points to the same thing as pFrom->z
   619    613   ** and flags gets srcType (either MEM_Ephem or MEM_Static).
   620    614   */
   621    615   void sqlite3VdbeMemShallowCopy(Mem *pTo, const Mem *pFrom, int srcType){
   622    616     assert( (pFrom->flags & MEM_RowSet)==0 );
   623         -  sqlite3VdbeMemReleaseExternal(pTo);
          617  +  MemReleaseExt(pTo);
   624    618     memcpy(pTo, pFrom, MEMCELLSIZE);
   625    619     pTo->xDel = 0;
   626    620     if( (pFrom->flags&MEM_Static)==0 ){
   627    621       pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Ephem);
   628    622       assert( srcType==MEM_Ephem || srcType==MEM_Static );
   629    623       pTo->flags |= srcType;
   630    624     }
................................................................................
   634    628   ** Make a full copy of pFrom into pTo.  Prior contents of pTo are
   635    629   ** freed before the copy is made.
   636    630   */
   637    631   int sqlite3VdbeMemCopy(Mem *pTo, const Mem *pFrom){
   638    632     int rc = SQLITE_OK;
   639    633   
   640    634     assert( (pFrom->flags & MEM_RowSet)==0 );
   641         -  sqlite3VdbeMemReleaseExternal(pTo);
          635  +  MemReleaseExt(pTo);
   642    636     memcpy(pTo, pFrom, MEMCELLSIZE);
   643    637     pTo->flags &= ~MEM_Dyn;
   644    638   
   645    639     if( pTo->flags&(MEM_Str|MEM_Blob) ){
   646    640       if( 0==(pFrom->flags&MEM_Static) ){
   647    641         pTo->flags |= MEM_Ephem;
   648    642         rc = sqlite3VdbeMemMakeWriteable(pTo);