/ Check-in [d2efea16]
Login

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

Overview
Comment:Performance improvement to SQL function calls in the VDBE.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | toTypeFuncs
Files: files | file ages | folders
SHA1: d2efea1682a7e708000c1f5d36370aaf1199b3be
User & Date: drh 2013-08-19 23:18:12
References
2013-08-20
03:13
Performance optimizations in the VDBE and especially to the OP_Next and related opcodes and in the sqlite3BtreeNext() and sqlite3BtreePrevious() routines. This is a cherrypick of [6f99b54aedeb], [d2efea1682a7], and [d78c5d89de4b]. check-in: 7f72fc4f user: drh tags: trunk
Context
2013-08-20
03:13
Performance optimizations in the VDBE and especially to the OP_Next and related opcodes and in the sqlite3BtreeNext() and sqlite3BtreePrevious() routines. This is a cherrypick of [6f99b54aedeb], [d2efea1682a7], and [d78c5d89de4b]. check-in: 7f72fc4f user: drh tags: trunk
00:42
Performance optimizations in the VDBE and especially to the OP_Next and related opcodes. check-in: d78c5d89 user: drh tags: toTypeFuncs
2013-08-19
23:18
Performance improvement to SQL function calls in the VDBE. check-in: d2efea16 user: drh tags: toTypeFuncs
22:22
Additional performance improvements in sqlite3BtreeNext() and sqlite3BtreePrevious(). check-in: 6f99b54a user: drh tags: toTypeFuncs
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/vdbe.c.

  1445   1445     /* The output cell may already have a buffer allocated. Move
  1446   1446     ** the pointer to ctx.s so in case the user-function can use
  1447   1447     ** the already allocated buffer instead of allocating a new one.
  1448   1448     */
  1449   1449     sqlite3VdbeMemMove(&ctx.s, pOut);
  1450   1450     MemSetTypeFlag(&ctx.s, MEM_Null);
  1451   1451   
  1452         -  ctx.isError = 0;
         1452  +  ctx.fErrorOrAux = 0;
  1453   1453     if( ctx.pFunc->flags & SQLITE_FUNC_NEEDCOLL ){
  1454   1454       assert( pOp>aOp );
  1455   1455       assert( pOp[-1].p4type==P4_COLLSEQ );
  1456   1456       assert( pOp[-1].opcode==OP_CollSeq );
  1457   1457       ctx.pColl = pOp[-1].p4.pColl;
  1458   1458     }
  1459   1459     db->lastRowid = lastRowid;
  1460   1460     (*ctx.pFunc->xFunc)(&ctx, n, apVal); /* IMP: R-24505-23230 */
  1461   1461     lastRowid = db->lastRowid;
  1462   1462   
  1463         -  /* If any auxiliary data functions have been called by this user function,
  1464         -  ** immediately call the destructor for any non-static values.
  1465         -  */
  1466         -  sqlite3VdbeDeleteAuxData(p, pc, pOp->p1);
  1467         -
  1468   1463     if( db->mallocFailed ){
  1469   1464       /* Even though a malloc() has failed, the implementation of the
  1470   1465       ** user function may have called an sqlite3_result_XXX() function
  1471   1466       ** to return a value. The following call releases any resources
  1472   1467       ** associated with such a value.
  1473   1468       */
  1474   1469       sqlite3VdbeMemRelease(&ctx.s);
  1475   1470       goto no_mem;
  1476   1471     }
  1477   1472   
  1478   1473     /* If the function returned an error, throw an exception */
  1479         -  if( ctx.isError ){
  1480         -    sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s));
  1481         -    rc = ctx.isError;
         1474  +  if( ctx.fErrorOrAux ){
         1475  +    if( ctx.isError ){
         1476  +      sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(&ctx.s));
         1477  +      rc = ctx.isError;
         1478  +    }
         1479  +    sqlite3VdbeDeleteAuxData(p, pc, pOp->p1);
  1482   1480     }
  1483   1481   
  1484   1482     /* Copy the result of the function into register P3 */
  1485   1483     sqlite3VdbeChangeEncoding(&ctx.s, encoding);
  1486   1484     sqlite3VdbeMemMove(pOut, &ctx.s);
  1487   1485     if( sqlite3VdbeMemTooBig(pOut) ){
  1488   1486       goto too_big;

Changes to src/vdbeInt.h.

   262    262   ** (Mem) which are only defined there.
   263    263   */
   264    264   struct sqlite3_context {
   265    265     FuncDef *pFunc;       /* Pointer to function information.  MUST BE FIRST */
   266    266     Mem s;                /* The return value is stored here */
   267    267     Mem *pMem;            /* Memory cell used to store aggregate context */
   268    268     CollSeq *pColl;       /* Collating sequence */
   269         -  int isError;          /* Error code returned by the function. */
   270         -  int skipFlag;         /* Skip skip accumulator loading if true */
          269  +  Vdbe *pVdbe;          /* The VM that owns this context */
   271    270     int iOp;              /* Instruction number of OP_Function */
   272         -  Vdbe *pVdbe;          /* The VM that owns this context */
          271  +  int isError;          /* Error code returned by the function. */
          272  +  u8 skipFlag;          /* Skip skip accumulator loading if true */
          273  +  u8 fErrorOrAux;       /* isError!=0 or pVdbe->pAuxData modified */
   273    274   };
   274    275   
   275    276   /*
   276    277   ** An Explain object accumulates indented output which is helpful
   277    278   ** in describing recursive data structures.
   278    279   */
   279    280   struct Explain {

Changes to src/vdbeapi.c.

   207    207   void sqlite3_result_double(sqlite3_context *pCtx, double rVal){
   208    208     assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
   209    209     sqlite3VdbeMemSetDouble(&pCtx->s, rVal);
   210    210   }
   211    211   void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){
   212    212     assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
   213    213     pCtx->isError = SQLITE_ERROR;
          214  +  pCtx->fErrorOrAux = 1;
   214    215     sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF8, SQLITE_TRANSIENT);
   215    216   }
   216    217   #ifndef SQLITE_OMIT_UTF16
   217    218   void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){
   218    219     assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
   219    220     pCtx->isError = SQLITE_ERROR;
          221  +  pCtx->fErrorOrAux = 1;
   220    222     sqlite3VdbeMemSetStr(&pCtx->s, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT);
   221    223   }
   222    224   #endif
   223    225   void sqlite3_result_int(sqlite3_context *pCtx, int iVal){
   224    226     assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
   225    227     sqlite3VdbeMemSetInt64(&pCtx->s, (i64)iVal);
   226    228   }
................................................................................
   276    278   }
   277    279   void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){
   278    280     assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
   279    281     sqlite3VdbeMemSetZeroBlob(&pCtx->s, n);
   280    282   }
   281    283   void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
   282    284     pCtx->isError = errCode;
          285  +  pCtx->fErrorOrAux = 1;
   283    286     if( pCtx->s.flags & MEM_Null ){
   284    287       sqlite3VdbeMemSetStr(&pCtx->s, sqlite3ErrStr(errCode), -1, 
   285    288                            SQLITE_UTF8, SQLITE_STATIC);
   286    289     }
   287    290   }
   288    291   
   289    292   /* Force an SQLITE_TOOBIG error. */
   290    293   void sqlite3_result_error_toobig(sqlite3_context *pCtx){
   291    294     assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
   292    295     pCtx->isError = SQLITE_TOOBIG;
          296  +  pCtx->fErrorOrAux = 1;
   293    297     sqlite3VdbeMemSetStr(&pCtx->s, "string or blob too big", -1, 
   294    298                          SQLITE_UTF8, SQLITE_STATIC);
   295    299   }
   296    300   
   297    301   /* An SQLITE_NOMEM error. */
   298    302   void sqlite3_result_error_nomem(sqlite3_context *pCtx){
   299    303     assert( sqlite3_mutex_held(pCtx->s.db->mutex) );
   300    304     sqlite3VdbeMemSetNull(&pCtx->s);
   301    305     pCtx->isError = SQLITE_NOMEM;
          306  +  pCtx->fErrorOrAux = 1;
   302    307     pCtx->s.db->mallocFailed = 1;
   303    308   }
   304    309   
   305    310   /*
   306    311   ** This function is called after a transaction has been committed. It 
   307    312   ** invokes callbacks registered with sqlite3_wal_hook() as required.
   308    313   */
................................................................................
   617    622     if( pAuxData==0 ){
   618    623       pAuxData = sqlite3DbMallocZero(pVdbe->db, sizeof(AuxData));
   619    624       if( !pAuxData ) goto failed;
   620    625       pAuxData->iOp = pCtx->iOp;
   621    626       pAuxData->iArg = iArg;
   622    627       pAuxData->pNext = pVdbe->pAuxData;
   623    628       pVdbe->pAuxData = pAuxData;
          629  +    if( pCtx->fErrorOrAux==0 ){
          630  +      pCtx->isError = 0;
          631  +      pCtx->fErrorOrAux = 1;
          632  +    }
   624    633     }else if( pAuxData->xDelete ){
   625    634       pAuxData->xDelete(pAuxData->pAux);
   626    635     }
   627    636   
   628    637     pAuxData->pAux = pAux;
   629    638     pAuxData->xDelete = xDelete;
   630    639     return;