/ Check-in [49ebc219]
Login

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

Overview
Comment:Refactor the sqlite3BtreeKey() and sqlite3BtreeData() internal interfaces into sqlite3BtreePayload() and sqlite3BtreePayloadChecked(), respectively. This is a continuation of the optimization started by check-in [2d831074cf]. The result is a slightly smaller and faster binary.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 49ebc219faea30eaa61def4a3fba2817b9c58a86
User & Date: drh 2016-11-25 19:18:28
Context
2016-11-25
19:32
Remove the OP_RowKey opcode. Use OP_RowData in its place. check-in: 6ac7b07a user: drh tags: trunk
19:18
Refactor the sqlite3BtreeKey() and sqlite3BtreeData() internal interfaces into sqlite3BtreePayload() and sqlite3BtreePayloadChecked(), respectively. This is a continuation of the optimization started by check-in [2d831074cf]. The result is a slightly smaller and faster binary. check-in: 49ebc219 user: drh tags: trunk
17:03
Small performance increase and size reduction in the OP_Column opcode. check-in: a9498407 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

   628    628       pCur->nKey = sqlite3BtreeIntegerKey(pCur);
   629    629     }else{
   630    630       /* For an index btree, save the complete key content */
   631    631       void *pKey;
   632    632       pCur->nKey = sqlite3BtreePayloadSize(pCur);
   633    633       pKey = sqlite3Malloc( pCur->nKey );
   634    634       if( pKey ){
   635         -      rc = sqlite3BtreeKey(pCur, 0, (int)pCur->nKey, pKey);
          635  +      rc = sqlite3BtreePayload(pCur, 0, (int)pCur->nKey, pKey);
   636    636         if( rc==SQLITE_OK ){
   637    637           pCur->pKey = pKey;
   638    638         }else{
   639    639           sqlite3_free(pKey);
   640    640         }
   641    641       }else{
   642    642         rc = SQLITE_NOMEM_BKPT;
................................................................................
  4647   4647     if( rc==SQLITE_OK && amt>0 ){
  4648   4648       return SQLITE_CORRUPT_BKPT;
  4649   4649     }
  4650   4650     return rc;
  4651   4651   }
  4652   4652   
  4653   4653   /*
  4654         -** Read part of the key associated with cursor pCur.  Exactly
  4655         -** "amt" bytes will be transferred into pBuf[].  The transfer
         4654  +** Read part of the payload for the row at which that cursor pCur is currently
         4655  +** pointing.  "amt" bytes will be transferred into pBuf[].  The transfer
  4656   4656   ** begins at "offset".
  4657   4657   **
  4658         -** The caller must ensure that pCur is pointing to a valid row
  4659         -** in the table.
         4658  +** pCur can be pointing to either a table or an index b-tree.
         4659  +** If pointing to a table btree, then the content section is read.  If
         4660  +** pCur is pointing to an index b-tree then the key section is read.
         4661  +**
         4662  +** For sqlite3BtreePayload(), the caller must ensure that pCur is pointing
         4663  +** to a valid row in the table.  For sqlite3BtreePayloadChecked(), the
         4664  +** cursor might be invalid or might need to be restored before being read.
  4660   4665   **
  4661   4666   ** Return SQLITE_OK on success or an error code if anything goes
  4662   4667   ** wrong.  An error is returned if "offset+amt" is larger than
  4663   4668   ** the available payload.
  4664   4669   */
  4665         -int sqlite3BtreeKey(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
         4670  +int sqlite3BtreePayload(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
  4666   4671     assert( cursorHoldsMutex(pCur) );
  4667   4672     assert( pCur->eState==CURSOR_VALID );
  4668   4673     assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] );
  4669   4674     assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
  4670   4675     return accessPayload(pCur, offset, amt, (unsigned char*)pBuf, 0);
  4671   4676   }
  4672         -
  4673         -/*
  4674         -** Read part of the data associated with cursor pCur.  Exactly
  4675         -** "amt" bytes will be transfered into pBuf[].  The transfer
  4676         -** begins at "offset".
  4677         -**
  4678         -** Return SQLITE_OK on success or an error code if anything goes
  4679         -** wrong.  An error is returned if "offset+amt" is larger than
  4680         -** the available payload.
  4681         -*/
  4682         -int sqlite3BtreeData(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
  4683         -  int rc;
  4684         -
  4685   4677   #ifndef SQLITE_OMIT_INCRBLOB
         4678  +int sqlite3BtreePayloadChecked(BtCursor *pCur, u32 offset, u32 amt, void *pBuf){
         4679  +  int rc;
  4686   4680     if ( pCur->eState==CURSOR_INVALID ){
  4687   4681       return SQLITE_ABORT;
  4688   4682     }
  4689         -#endif
  4690         -
  4691   4683     assert( cursorOwnsBtShared(pCur) );
  4692   4684     rc = restoreCursorPosition(pCur);
  4693   4685     if( rc==SQLITE_OK ){
  4694   4686       assert( pCur->eState==CURSOR_VALID );
  4695   4687       assert( pCur->iPage>=0 && pCur->apPage[pCur->iPage] );
  4696   4688       assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
  4697   4689       rc = accessPayload(pCur, offset, amt, pBuf, 0);
  4698   4690     }
  4699   4691     return rc;
  4700   4692   }
         4693  +#endif /* SQLITE_OMIT_INCRBLOB */
  4701   4694   
  4702   4695   /*
  4703   4696   ** Return a pointer to payload information from the entry that the 
  4704   4697   ** pCur cursor is pointing to.  The pointer is to the beginning of
  4705   4698   ** the key if index btrees (pPage->intKey==0) and is the data for
  4706   4699   ** table btrees (pPage->intKey==1). The number of bytes of available
  4707   4700   ** key/data is written into *pAmt.  If *pAmt==0, then the value

Changes to src/btree.h.

   285    285                          int bias, int seekResult);
   286    286   int sqlite3BtreeFirst(BtCursor*, int *pRes);
   287    287   int sqlite3BtreeLast(BtCursor*, int *pRes);
   288    288   int sqlite3BtreeNext(BtCursor*, int *pRes);
   289    289   int sqlite3BtreeEof(BtCursor*);
   290    290   int sqlite3BtreePrevious(BtCursor*, int *pRes);
   291    291   i64 sqlite3BtreeIntegerKey(BtCursor*);
   292         -int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*);
          292  +int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*);
   293    293   const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt);
   294    294   u32 sqlite3BtreePayloadSize(BtCursor*);
   295         -int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*);
   296    295   
   297    296   char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
   298    297   struct Pager *sqlite3BtreePager(Btree*);
   299    298   
   300    299   #ifndef SQLITE_OMIT_INCRBLOB
          300  +int sqlite3BtreePayloadChecked(BtCursor*, u32 offset, u32 amt, void*);
   301    301   int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
   302    302   void sqlite3BtreeIncrblobCursor(BtCursor *);
   303    303   #endif
   304    304   void sqlite3BtreeClearCursor(BtCursor *);
   305    305   int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
   306    306   int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask);
   307    307   int sqlite3BtreeIsReadonly(Btree *pBt);

Changes to src/vdbe.c.

  2545   2545       /* If there is more header available for parsing in the record, try
  2546   2546       ** to extract additional fields up through the p2+1-th field 
  2547   2547       */
  2548   2548       if( pC->iHdrOffset<aOffset[0] ){
  2549   2549         /* Make sure zData points to enough of the record to cover the header. */
  2550   2550         if( pC->aRow==0 ){
  2551   2551           memset(&sMem, 0, sizeof(sMem));
  2552         -        rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, 0, aOffset[0],
  2553         -                                     !pC->isTable, &sMem);
         2552  +        rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, 0, aOffset[0], &sMem);
  2554   2553           if( rc!=SQLITE_OK ) goto abort_due_to_error;
  2555   2554           zData = (u8*)sMem.z;
  2556   2555         }else{
  2557   2556           zData = pC->aRow;
  2558   2557         }
  2559   2558     
  2560   2559         /* Fill in pC->aType[i] and aOffset[i] values through the p2-th field. */
................................................................................
  2659   2658         **    2. the length(X) function if X is a blob, and
  2660   2659         **    3. if the content length is zero.
  2661   2660         ** So we might as well use bogus content rather than reading
  2662   2661         ** content from disk. */
  2663   2662         static u8 aZero[8];  /* This is the bogus content */
  2664   2663         sqlite3VdbeSerialGet(aZero, t, pDest);
  2665   2664       }else{
  2666         -      rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, aOffset[p2], len,
  2667         -                                   !pC->isTable, pDest);
         2665  +      rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, aOffset[p2], len, pDest);
  2668   2666         if( rc!=SQLITE_OK ) goto abort_due_to_error;
  2669   2667         sqlite3VdbeSerialGet((const u8*)pDest->z, t, pDest);
  2670   2668         pDest->flags &= ~MEM_Ephem;
  2671   2669       }
  2672   2670     }
  2673   2671   
  2674   2672   op_column_out:
................................................................................
  4701   4699     }
  4702   4700     testcase( n==0 );
  4703   4701     if( sqlite3VdbeMemClearAndResize(pOut, MAX(n,32)) ){
  4704   4702       goto no_mem;
  4705   4703     }
  4706   4704     pOut->n = n;
  4707   4705     MemSetTypeFlag(pOut, MEM_Blob);
  4708         -  if( pC->isTable==0 ){
  4709         -    rc = sqlite3BtreeKey(pCrsr, 0, n, pOut->z);
  4710         -  }else{
  4711         -    rc = sqlite3BtreeData(pCrsr, 0, n, pOut->z);
  4712         -  }
         4706  +  rc = sqlite3BtreePayload(pCrsr, 0, n, pOut->z);
  4713   4707     if( rc ) goto abort_due_to_error;
  4714   4708     pOut->enc = SQLITE_UTF8;  /* In case the blob is ever cast to text */
  4715   4709     UPDATE_MAX_BLOBSIZE(pOut);
  4716   4710     REGISTER_TRACE(pOp->p2, pOut);
  4717   4711     break;
  4718   4712   }
  4719   4713   

Changes to src/vdbeInt.h.

   483    483   i64 sqlite3VdbeIntValue(Mem*);
   484    484   int sqlite3VdbeMemIntegerify(Mem*);
   485    485   double sqlite3VdbeRealValue(Mem*);
   486    486   void sqlite3VdbeIntegerAffinity(Mem*);
   487    487   int sqlite3VdbeMemRealify(Mem*);
   488    488   int sqlite3VdbeMemNumerify(Mem*);
   489    489   void sqlite3VdbeMemCast(Mem*,u8,u8);
   490         -int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,int,Mem*);
          490  +int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*);
   491    491   void sqlite3VdbeMemRelease(Mem *p);
   492    492   int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
   493    493   const char *sqlite3OpcodeName(int);
   494    494   int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
   495    495   int sqlite3VdbeMemClearAndResize(Mem *pMem, int n);
   496    496   int sqlite3VdbeCloseStatement(Vdbe *, int);
   497    497   void sqlite3VdbeFrameDelete(VdbeFrame*);

Changes to src/vdbeapi.c.

  1691   1691     if( p->pUnpacked==0 ){
  1692   1692       u32 nRec;
  1693   1693       u8 *aRec;
  1694   1694   
  1695   1695       nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
  1696   1696       aRec = sqlite3DbMallocRaw(db, nRec);
  1697   1697       if( !aRec ) goto preupdate_old_out;
  1698         -    rc = sqlite3BtreeData(p->pCsr->uc.pCursor, 0, nRec, aRec);
         1698  +    rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
  1699   1699       if( rc==SQLITE_OK ){
  1700   1700         p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec);
  1701   1701         if( !p->pUnpacked ) rc = SQLITE_NOMEM;
  1702   1702       }
  1703   1703       if( rc!=SQLITE_OK ){
  1704   1704         sqlite3DbFree(db, aRec);
  1705   1705         goto preupdate_old_out;

Changes to src/vdbeaux.c.

  4361   4361     */
  4362   4362     assert( sqlite3BtreeCursorIsValid(pCur) );
  4363   4363     nCellKey = sqlite3BtreePayloadSize(pCur);
  4364   4364     assert( (nCellKey & SQLITE_MAX_U32)==(u64)nCellKey );
  4365   4365   
  4366   4366     /* Read in the complete content of the index entry */
  4367   4367     sqlite3VdbeMemInit(&m, db, 0);
  4368         -  rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, 1, &m);
         4368  +  rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m);
  4369   4369     if( rc ){
  4370   4370       return rc;
  4371   4371     }
  4372   4372   
  4373   4373     /* The index entry must begin with a header size */
  4374   4374     (void)getVarint32((u8*)m.z, szHdr);
  4375   4375     testcase( szHdr==3 );
................................................................................
  4441   4441     /* nCellKey will always be between 0 and 0xffffffff because of the way
  4442   4442     ** that btreeParseCellPtr() and sqlite3GetVarint32() are implemented */
  4443   4443     if( nCellKey<=0 || nCellKey>0x7fffffff ){
  4444   4444       *res = 0;
  4445   4445       return SQLITE_CORRUPT_BKPT;
  4446   4446     }
  4447   4447     sqlite3VdbeMemInit(&m, db, 0);
  4448         -  rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, 1, &m);
         4448  +  rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m);
  4449   4449     if( rc ){
  4450   4450       return rc;
  4451   4451     }
  4452   4452     *res = sqlite3VdbeRecordCompare(m.n, m.z, pUnpacked);
  4453   4453     sqlite3VdbeMemRelease(&m);
  4454   4454     return SQLITE_OK;
  4455   4455   }

Changes to src/vdbeblob.c.

   436    436     return rc;
   437    437   }
   438    438   
   439    439   /*
   440    440   ** Read data from a blob handle.
   441    441   */
   442    442   int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){
   443         -  return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreeData);
          443  +  return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreePayloadChecked);
   444    444   }
   445    445   
   446    446   /*
   447    447   ** Write data to a blob handle.
   448    448   */
   449    449   int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){
   450    450     return blobReadWrite(pBlob, (void *)z, n, iOffset, sqlite3BtreePutData);

Changes to src/vdbemem.c.

   930    930     }
   931    931   
   932    932     return SQLITE_OK;
   933    933   }
   934    934   
   935    935   /*
   936    936   ** Move data out of a btree key or data field and into a Mem structure.
   937         -** The data or key is taken from the entry that pCur is currently pointing
          937  +** The data is payload from the entry that pCur is currently pointing
   938    938   ** to.  offset and amt determine what portion of the data or key to retrieve.
   939         -** key is true to get the key or false to get data.  The result is written
   940         -** into the pMem element.
          939  +** The result is written into the pMem element.
   941    940   **
   942    941   ** The pMem object must have been initialized.  This routine will use
   943    942   ** pMem->zMalloc to hold the content from the btree, if possible.  New
   944    943   ** pMem->zMalloc space will be allocated if necessary.  The calling routine
   945    944   ** is responsible for making sure that the pMem object is eventually
   946    945   ** destroyed.
   947    946   **
................................................................................
   948    947   ** If this routine fails for any reason (malloc returns NULL or unable
   949    948   ** to read from the disk) then the pMem is left in an inconsistent state.
   950    949   */
   951    950   static SQLITE_NOINLINE int vdbeMemFromBtreeResize(
   952    951     BtCursor *pCur,   /* Cursor pointing at record to retrieve. */
   953    952     u32 offset,       /* Offset from the start of data to return bytes from. */
   954    953     u32 amt,          /* Number of bytes to return. */
   955         -  int key,          /* If true, retrieve from the btree key, not data. */
   956    954     Mem *pMem         /* OUT: Return data in this Mem structure. */
   957    955   ){
   958    956     int rc;
   959    957     pMem->flags = MEM_Null;
   960    958     if( SQLITE_OK==(rc = sqlite3VdbeMemClearAndResize(pMem, amt+2)) ){
   961         -    if( key ){
   962         -      rc = sqlite3BtreeKey(pCur, offset, amt, pMem->z);
   963         -    }else{
   964         -      rc = sqlite3BtreeData(pCur, offset, amt, pMem->z);
   965         -    }
          959  +    rc = sqlite3BtreePayload(pCur, offset, amt, pMem->z);
   966    960       if( rc==SQLITE_OK ){
   967    961         pMem->z[amt] = 0;
   968    962         pMem->z[amt+1] = 0;
   969    963         pMem->flags = MEM_Blob|MEM_Term;
   970    964         pMem->n = (int)amt;
   971    965       }else{
   972    966         sqlite3VdbeMemRelease(pMem);
................................................................................
   974    968     }
   975    969     return rc;
   976    970   }
   977    971   int sqlite3VdbeMemFromBtree(
   978    972     BtCursor *pCur,   /* Cursor pointing at record to retrieve. */
   979    973     u32 offset,       /* Offset from the start of data to return bytes from. */
   980    974     u32 amt,          /* Number of bytes to return. */
   981         -  int key,          /* If true, retrieve from the btree key, not data. */
   982    975     Mem *pMem         /* OUT: Return data in this Mem structure. */
   983    976   ){
   984    977     char *zData;        /* Data from the btree layer */
   985    978     u32 available = 0;  /* Number of bytes available on the local btree page */
   986    979     int rc = SQLITE_OK; /* Return code */
   987    980   
   988    981     assert( sqlite3BtreeCursorIsValid(pCur) );
................................................................................
   995    988     assert( zData!=0 );
   996    989   
   997    990     if( offset+amt<=available ){
   998    991       pMem->z = &zData[offset];
   999    992       pMem->flags = MEM_Blob|MEM_Ephem;
  1000    993       pMem->n = (int)amt;
  1001    994     }else{
  1002         -    rc = vdbeMemFromBtreeResize(pCur, offset, amt, key, pMem);
          995  +    rc = vdbeMemFromBtreeResize(pCur, offset, amt, pMem);
  1003    996     }
  1004    997   
  1005    998     return rc;
  1006    999   }
  1007   1000   
  1008   1001   /*
  1009   1002   ** The pVal argument is known to be a value other than NULL.