/ Check-in [33a1924e]
Login

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

Overview
Comment:Experimental support for new sqlite3_bind_blob() and sqlite3_bind_text() interfaces that take an extra void* argument that is passed into the destructor in front of the object that is to be destroyed.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | custom-destructors
Files: files | file ages | folders
SHA3-256: 33a1924ebb754d8e4374dbedb310170867bdb8121e1bb1ff5215e0526c32c62d
User & Date: drh 2018-12-14 21:58:06
Context
2018-12-14
21:58
Experimental support for new sqlite3_bind_blob() and sqlite3_bind_text() interfaces that take an extra void* argument that is passed into the destructor in front of the object that is to be destroyed. Leaf check-in: 33a1924e user: drh tags: custom-destructors
18:11
Fix harmless compiler warnings. check-in: 27221c69 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/sqlite.h.in.

  4056   4056   **
  4057   4057   ** See also: [sqlite3_bind_parameter_count()],
  4058   4058   ** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()].
  4059   4059   */
  4060   4060   int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
  4061   4061   int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64,
  4062   4062                           void(*)(void*));
         4063  +int sqlite3_bind_blob64dx(sqlite3_stmt*, int, const void*, sqlite3_uint64,
         4064  +                          void(*)(void*,void*),void*);
  4063   4065   int sqlite3_bind_double(sqlite3_stmt*, int, double);
  4064   4066   int sqlite3_bind_int(sqlite3_stmt*, int, int);
  4065   4067   int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
  4066   4068   int sqlite3_bind_null(sqlite3_stmt*, int);
  4067   4069   int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
  4068   4070   int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
  4069   4071   int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
  4070   4072                            void(*)(void*), unsigned char encoding);
         4073  +int sqlite3_bind_text64dx(sqlite3_stmt*, int, const char*, sqlite3_uint64,
         4074  +                          void(*)(void*,void*),void*,unsigned char encoding);
  4071   4075   int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
  4072   4076   int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*,void(*)(void*));
  4073   4077   int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
  4074   4078   int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64);
  4075   4079   
  4076   4080   /*
  4077   4081   ** CAPI3REF: Number Of SQL Parameters
................................................................................
  5332   5336   ** If these routines are called from within the different thread
  5333   5337   ** than the one containing the application-defined function that received
  5334   5338   ** the [sqlite3_context] pointer, the results are undefined.
  5335   5339   */
  5336   5340   void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
  5337   5341   void sqlite3_result_blob64(sqlite3_context*,const void*,
  5338   5342                              sqlite3_uint64,void(*)(void*));
         5343  +void sqlite3_result_blob64dx(sqlite3_context*,const void*,
         5344  +                             sqlite3_uint64,void(*)(void*,void*),void*);
  5339   5345   void sqlite3_result_double(sqlite3_context*, double);
  5340   5346   void sqlite3_result_error(sqlite3_context*, const char*, int);
  5341   5347   void sqlite3_result_error16(sqlite3_context*, const void*, int);
  5342   5348   void sqlite3_result_error_toobig(sqlite3_context*);
  5343   5349   void sqlite3_result_error_nomem(sqlite3_context*);
  5344   5350   void sqlite3_result_error_code(sqlite3_context*, int);
  5345   5351   void sqlite3_result_int(sqlite3_context*, int);
  5346   5352   void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
  5347   5353   void sqlite3_result_null(sqlite3_context*);
  5348   5354   void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
  5349   5355   void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
  5350   5356                              void(*)(void*), unsigned char encoding);
         5357  +void sqlite3_result_text64dx(sqlite3_context*, const char*,sqlite3_uint64,
         5358  +                             void(*)(void*,void*),void*,unsigned char encoding);
  5351   5359   void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
  5352   5360   void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
  5353   5361   void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
  5354   5362   void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
  5355   5363   void sqlite3_result_pointer(sqlite3_context*, void*,const char*,void(*)(void*));
  5356   5364   void sqlite3_result_zeroblob(sqlite3_context*, int n);
  5357   5365   int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);

Changes to src/vdbe.c.

  6088   6088         goto no_mem;
  6089   6089       }
  6090   6090       sqlite3VdbeMemRelease(pRt);
  6091   6091       pRt->flags = MEM_Blob|MEM_Dyn;
  6092   6092       pRt->z = (char*)pFrame;
  6093   6093       pRt->n = nByte;
  6094   6094       pRt->xDel = sqlite3VdbeFrameMemDel;
         6095  +    pRt->pDelPtr = 0;
  6095   6096   
  6096   6097       pFrame->v = p;
  6097   6098       pFrame->nChildMem = nMem;
  6098   6099       pFrame->nChildCsr = pProgram->nCsr;
  6099   6100       pFrame->pc = (int)(pOp - aOp);
  6100   6101       pFrame->aMem = p->aMem;
  6101   6102       pFrame->nMem = p->nMem;

Changes to src/vdbeInt.h.

   211    211     char *z;            /* String or BLOB value */
   212    212     /* ShallowCopy only needs to copy the information above */
   213    213     char *zMalloc;      /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */
   214    214     int szMalloc;       /* Size of the zMalloc allocation */
   215    215     u32 uTemp;          /* Transient storage for serial_type in OP_MakeRecord */
   216    216     sqlite3 *db;        /* The associated database connection */
   217    217     void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */
          218  +  void *pDelPtr;      /* Context information for the delete */
   218    219   #ifdef SQLITE_DEBUG
   219    220     Mem *pScopyFrom;    /* This Mem is a shallow copy of pScopyFrom */
   220    221     u16 mScopyFlags;    /* flags value immediately after the shallow copy */
   221    222   #endif
   222    223   };
   223    224   
   224    225   /*

Changes to src/vdbeapi.c.

   317    317   ** on value P is not going to be used and need to be destroyed.
   318    318   */
   319    319   static void setResultStrOrError(
   320    320     sqlite3_context *pCtx,  /* Function context */
   321    321     const char *z,          /* String pointer */
   322    322     int n,                  /* Bytes in string, or negative */
   323    323     u8 enc,                 /* Encoding of z.  0 for BLOBs */
   324         -  void (*xDel)(void*)     /* Destructor function */
          324  +  void (*xDel)(void*),    /* Destructor function */
          325  +  void *pDelPtr           /* Context for the destructor */
   325    326   ){
   326    327     if( sqlite3VdbeMemSetStr(pCtx->pOut, z, n, enc, xDel)==SQLITE_TOOBIG ){
   327    328       sqlite3_result_error_toobig(pCtx);
          329  +  }else{
          330  +    pCtx->pOut->pDelPtr = pDelPtr;
   328    331     }
   329    332   }
   330    333   static int invokeValueDestructor(
   331    334     const void *p,             /* Value to destroy */
   332    335     void (*xDel)(void*),       /* The destructor */
          336  +  void *pDelPtr,             /* Destructor context */
   333    337     sqlite3_context *pCtx      /* Set a SQLITE_TOOBIG error if no NULL */
   334    338   ){
   335    339     assert( xDel!=SQLITE_DYNAMIC );
   336    340     if( xDel==0 ){
   337    341       /* noop */
   338    342     }else if( xDel==SQLITE_TRANSIENT ){
   339    343       /* noop */
          344  +  }else if( pDelPtr ){
          345  +    (*(void(*)(void*,void*))xDel)(pDelPtr,(void*)p);
   340    346     }else{
   341    347       xDel((void*)p);
   342    348     }
   343    349     if( pCtx ) sqlite3_result_error_toobig(pCtx);
   344    350     return SQLITE_TOOBIG;
   345    351   }
   346    352   void sqlite3_result_blob(
................................................................................
   347    353     sqlite3_context *pCtx, 
   348    354     const void *z, 
   349    355     int n, 
   350    356     void (*xDel)(void *)
   351    357   ){
   352    358     assert( n>=0 );
   353    359     assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
   354         -  setResultStrOrError(pCtx, z, n, 0, xDel);
          360  +  setResultStrOrError(pCtx, z, n, 0, xDel, 0);
   355    361   }
   356    362   void sqlite3_result_blob64(
   357    363     sqlite3_context *pCtx, 
   358    364     const void *z, 
   359    365     sqlite3_uint64 n,
   360    366     void (*xDel)(void *)
   361    367   ){
   362    368     assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
   363    369     assert( xDel!=SQLITE_DYNAMIC );
   364    370     if( n>0x7fffffff ){
   365         -    (void)invokeValueDestructor(z, xDel, pCtx);
          371  +    (void)invokeValueDestructor(z, xDel, 0, pCtx);
   366    372     }else{
   367         -    setResultStrOrError(pCtx, z, (int)n, 0, xDel);
          373  +    setResultStrOrError(pCtx, z, (int)n, 0, xDel, 0);
          374  +  }
          375  +}
          376  +void sqlite3_result_blob64dx(
          377  +  sqlite3_context *pCtx, 
          378  +  const void *z, 
          379  +  sqlite3_uint64 n,
          380  +  void (*xDel)(void*,void*),
          381  +  void *pDelPtr
          382  +){
          383  +  assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
          384  +  assert( ((void(*)(void*))xDel)!=SQLITE_DYNAMIC );
          385  +  if( n>0x7fffffff ){
          386  +    (void)invokeValueDestructor(z, (void(*)(void*))xDel, pDelPtr, pCtx);
          387  +  }else{
          388  +    setResultStrOrError(pCtx, z, (int)n, 0,
          389  +                        (void(*)(void*))xDel, pDelPtr);
   368    390     }
   369    391   }
   370    392   void sqlite3_result_double(sqlite3_context *pCtx, double rVal){
   371    393     assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
   372    394     sqlite3VdbeMemSetDouble(pCtx->pOut, rVal);
   373    395   }
   374    396   void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){
................................................................................
   416    438   void sqlite3_result_text(
   417    439     sqlite3_context *pCtx, 
   418    440     const char *z, 
   419    441     int n,
   420    442     void (*xDel)(void *)
   421    443   ){
   422    444     assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
   423         -  setResultStrOrError(pCtx, z, n, SQLITE_UTF8, xDel);
          445  +  setResultStrOrError(pCtx, z, n, SQLITE_UTF8, xDel, 0);
   424    446   }
   425    447   void sqlite3_result_text64(
   426    448     sqlite3_context *pCtx, 
   427    449     const char *z, 
   428    450     sqlite3_uint64 n,
   429    451     void (*xDel)(void *),
   430    452     unsigned char enc
   431    453   ){
   432    454     assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
   433    455     assert( xDel!=SQLITE_DYNAMIC );
   434    456     if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
   435    457     if( n>0x7fffffff ){
   436         -    (void)invokeValueDestructor(z, xDel, pCtx);
          458  +    (void)invokeValueDestructor(z, xDel, 0, pCtx);
   437    459     }else{
   438         -    setResultStrOrError(pCtx, z, (int)n, enc, xDel);
          460  +    setResultStrOrError(pCtx, z, (int)n, enc, xDel, 0);
   439    461     }
   440    462   }
   441    463   #ifndef SQLITE_OMIT_UTF16
   442    464   void sqlite3_result_text16(
   443    465     sqlite3_context *pCtx, 
   444    466     const void *z, 
   445    467     int n, 
   446    468     void (*xDel)(void *)
   447    469   ){
   448    470     assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
   449         -  setResultStrOrError(pCtx, z, n, SQLITE_UTF16NATIVE, xDel);
          471  +  setResultStrOrError(pCtx, z, n, SQLITE_UTF16NATIVE, xDel, 0);
   450    472   }
   451    473   void sqlite3_result_text16be(
   452    474     sqlite3_context *pCtx, 
   453    475     const void *z, 
   454    476     int n, 
   455    477     void (*xDel)(void *)
   456    478   ){
   457    479     assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
   458         -  setResultStrOrError(pCtx, z, n, SQLITE_UTF16BE, xDel);
          480  +  setResultStrOrError(pCtx, z, n, SQLITE_UTF16BE, xDel, 0);
   459    481   }
   460    482   void sqlite3_result_text16le(
   461    483     sqlite3_context *pCtx, 
   462    484     const void *z, 
   463    485     int n, 
   464    486     void (*xDel)(void *)
   465    487   ){
   466    488     assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
   467         -  setResultStrOrError(pCtx, z, n, SQLITE_UTF16LE, xDel);
          489  +  setResultStrOrError(pCtx, z, n, SQLITE_UTF16LE, xDel, 0);
   468    490   }
   469    491   #endif /* SQLITE_OMIT_UTF16 */
   470    492   void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){
   471    493     assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
   472    494     sqlite3VdbeMemCopy(pCtx->pOut, pValue);
   473    495   }
   474    496   void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){
................................................................................
   968    990           /* .n          = */ (int)0,
   969    991           /* .z          = */ (char*)0,
   970    992           /* .zMalloc    = */ (char*)0,
   971    993           /* .szMalloc   = */ (int)0,
   972    994           /* .uTemp      = */ (u32)0,
   973    995           /* .db         = */ (sqlite3*)0,
   974    996           /* .xDel       = */ (void(*)(void*))0,
          997  +        /* .pDelPtr    = */ (void*)0,
   975    998   #ifdef SQLITE_DEBUG
   976    999           /* .pScopyFrom = */ (Mem*)0,
   977   1000           /* .mScopyFlags= */ 0,
   978   1001   #endif
   979   1002         };
   980   1003     return &nullMem;
   981   1004   }
................................................................................
  1309   1332   */
  1310   1333   static int bindText(
  1311   1334     sqlite3_stmt *pStmt,   /* The statement to bind against */
  1312   1335     int i,                 /* Index of the parameter to bind */
  1313   1336     const void *zData,     /* Pointer to the data to be bound */
  1314   1337     int nData,             /* Number of bytes of data to be bound */
  1315   1338     void (*xDel)(void*),   /* Destructor for the data */
         1339  +  void *pDelPtr,         /* Destructor context */
  1316   1340     u8 encoding            /* Encoding for the data */
  1317   1341   ){
  1318   1342     Vdbe *p = (Vdbe *)pStmt;
  1319   1343     Mem *pVar;
  1320   1344     int rc;
  1321   1345   
  1322   1346     rc = vdbeUnbind(p, i);
  1323   1347     if( rc==SQLITE_OK ){
  1324   1348       if( zData!=0 ){
  1325   1349         pVar = &p->aVar[i-1];
  1326   1350         rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
  1327         -      if( rc==SQLITE_OK && encoding!=0 ){
  1328         -        rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
         1351  +      if( rc==SQLITE_OK ){
         1352  +        pVar->pDelPtr = pDelPtr;
         1353  +        if( encoding!=0 ){
         1354  +          rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
         1355  +        }
  1329   1356         }
  1330   1357         if( rc ){
  1331   1358           sqlite3Error(p->db, rc);
  1332   1359           rc = sqlite3ApiExit(p->db, rc);
  1333   1360         }
  1334   1361       }
  1335   1362       sqlite3_mutex_leave(p->db->mutex);
................................................................................
  1349   1376     const void *zData, 
  1350   1377     int nData, 
  1351   1378     void (*xDel)(void*)
  1352   1379   ){
  1353   1380   #ifdef SQLITE_ENABLE_API_ARMOR
  1354   1381     if( nData<0 ) return SQLITE_MISUSE_BKPT;
  1355   1382   #endif
  1356         -  return bindText(pStmt, i, zData, nData, xDel, 0);
         1383  +  return bindText(pStmt, i, zData, nData, xDel, 0, 0);
  1357   1384   }
  1358   1385   int sqlite3_bind_blob64(
  1359   1386     sqlite3_stmt *pStmt, 
  1360   1387     int i, 
  1361   1388     const void *zData, 
  1362   1389     sqlite3_uint64 nData, 
  1363   1390     void (*xDel)(void*)
  1364   1391   ){
  1365   1392     assert( xDel!=SQLITE_DYNAMIC );
  1366   1393     if( nData>0x7fffffff ){
  1367         -    return invokeValueDestructor(zData, xDel, 0);
         1394  +    return invokeValueDestructor(zData, xDel, 0, 0);
         1395  +  }else{
         1396  +    return bindText(pStmt, i, zData, (int)nData, xDel, 0, 0);
         1397  +  }
         1398  +}
         1399  +int sqlite3_bind_blob64dx(
         1400  +  sqlite3_stmt *pStmt, 
         1401  +  int i, 
         1402  +  const void *zData, 
         1403  +  sqlite3_uint64 nData, 
         1404  +  void (*xDel)(void*,void*),
         1405  +  void *pDelPtr
         1406  +){
         1407  +  assert( (void(*)(void*))xDel!=SQLITE_DYNAMIC );
         1408  +  if( nData>0x7fffffff ){
         1409  +    return invokeValueDestructor(zData, (void(*)(void*))xDel, pDelPtr, 0);
  1368   1410     }else{
  1369         -    return bindText(pStmt, i, zData, (int)nData, xDel, 0);
         1411  +    return bindText(pStmt, i, zData, (int)nData,
         1412  +                    (void(*)(void*))xDel, pDelPtr, 0);
  1370   1413     }
  1371   1414   }
  1372   1415   int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
  1373   1416     int rc;
  1374   1417     Vdbe *p = (Vdbe *)pStmt;
  1375   1418     rc = vdbeUnbind(p, i);
  1376   1419     if( rc==SQLITE_OK ){
................................................................................
  1422   1465   int sqlite3_bind_text( 
  1423   1466     sqlite3_stmt *pStmt, 
  1424   1467     int i, 
  1425   1468     const char *zData, 
  1426   1469     int nData, 
  1427   1470     void (*xDel)(void*)
  1428   1471   ){
  1429         -  return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8);
         1472  +  return bindText(pStmt, i, zData, nData, xDel, 0, SQLITE_UTF8);
  1430   1473   }
  1431   1474   int sqlite3_bind_text64( 
  1432   1475     sqlite3_stmt *pStmt, 
  1433   1476     int i, 
  1434   1477     const char *zData, 
  1435   1478     sqlite3_uint64 nData, 
  1436   1479     void (*xDel)(void*),
  1437   1480     unsigned char enc
  1438   1481   ){
  1439   1482     assert( xDel!=SQLITE_DYNAMIC );
  1440   1483     if( nData>0x7fffffff ){
  1441         -    return invokeValueDestructor(zData, xDel, 0);
         1484  +    return invokeValueDestructor(zData, xDel, 0, 0);
         1485  +  }else{
         1486  +    if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
         1487  +    return bindText(pStmt, i, zData, (int)nData, xDel, 0, enc);
         1488  +  }
         1489  +}
         1490  +int sqlite3_bind_text64dx( 
         1491  +  sqlite3_stmt *pStmt, 
         1492  +  int i, 
         1493  +  const char *zData, 
         1494  +  sqlite3_uint64 nData, 
         1495  +  void (*xDel)(void*,void*),
         1496  +  void *pDelPtr,
         1497  +  unsigned char enc
         1498  +){
         1499  +  assert( (void(*)(void*))xDel!=SQLITE_DYNAMIC );
         1500  +  if( nData>0x7fffffff ){
         1501  +    return invokeValueDestructor(zData, (void(*)(void*))xDel, pDelPtr, 0);
  1442   1502     }else{
  1443   1503       if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
  1444         -    return bindText(pStmt, i, zData, (int)nData, xDel, enc);
         1504  +    return bindText(pStmt, i, zData, (int)nData, 
         1505  +                    (void(*)(void*))xDel, pDelPtr, enc);
  1445   1506     }
  1446   1507   }
  1447   1508   #ifndef SQLITE_OMIT_UTF16
  1448   1509   int sqlite3_bind_text16(
  1449   1510     sqlite3_stmt *pStmt, 
  1450   1511     int i, 
  1451   1512     const void *zData, 
  1452   1513     int nData, 
  1453   1514     void (*xDel)(void*)
  1454   1515   ){
  1455         -  return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE);
         1516  +  return bindText(pStmt, i, zData, nData, xDel, 0, SQLITE_UTF16NATIVE);
  1456   1517   }
  1457   1518   #endif /* SQLITE_OMIT_UTF16 */
  1458   1519   int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
  1459   1520     int rc;
  1460   1521     switch( sqlite3_value_type((sqlite3_value*)pValue) ){
  1461   1522       case SQLITE_INTEGER: {
  1462   1523         rc = sqlite3_bind_int64(pStmt, i, pValue->u.i);
................................................................................
  1471   1532           rc = sqlite3_bind_zeroblob(pStmt, i, pValue->u.nZero);
  1472   1533         }else{
  1473   1534           rc = sqlite3_bind_blob(pStmt, i, pValue->z, pValue->n,SQLITE_TRANSIENT);
  1474   1535         }
  1475   1536         break;
  1476   1537       }
  1477   1538       case SQLITE_TEXT: {
  1478         -      rc = bindText(pStmt,i,  pValue->z, pValue->n, SQLITE_TRANSIENT,
         1539  +      rc = bindText(pStmt,i,  pValue->z, pValue->n, SQLITE_TRANSIENT, 0,
  1479   1540                                 pValue->enc);
  1480   1541         break;
  1481   1542       }
  1482   1543       default: {
  1483   1544         rc = sqlite3_bind_null(pStmt, i);
  1484   1545         break;
  1485   1546       }

Changes to src/vdbemem.c.

   172    172     rc = sqlite3VdbeMemTranslate(pMem, (u8)desiredEnc);
   173    173     assert(rc==SQLITE_OK    || rc==SQLITE_NOMEM);
   174    174     assert(rc==SQLITE_OK    || pMem->enc!=desiredEnc);
   175    175     assert(rc==SQLITE_NOMEM || pMem->enc==desiredEnc);
   176    176     return rc;
   177    177   #endif
   178    178   }
          179  +
          180  +/*
          181  +** Invoke the destructor
          182  +*/
          183  +void sqlite3VdbeDestructor(Mem *pMem){
          184  +  assert( pMem->xDel!=0 );
          185  +  if( pMem->pDelPtr==0 ){
          186  +    pMem->xDel((void*)(pMem->z));
          187  +  }else{
          188  +    ((void(*)(void*,void*))(pMem->xDel))(pMem->pDelPtr, (void*)pMem->z);
          189  +  }
          190  +}
   179    191   
   180    192   /*
   181    193   ** Make sure pMem->z points to a writable allocation of at least 
   182    194   ** min(n,32) bytes.
   183    195   **
   184    196   ** If the bPreserve argument is true, then copy of the content of
   185    197   ** pMem->z into the new allocation.  pMem must be either a string or
................................................................................
   217    229   
   218    230     if( bPreserve && pMem->z ){
   219    231       assert( pMem->z!=pMem->zMalloc );
   220    232       memcpy(pMem->zMalloc, pMem->z, pMem->n);
   221    233     }
   222    234     if( (pMem->flags&MEM_Dyn)!=0 ){
   223    235       assert( pMem->xDel!=0 && pMem->xDel!=SQLITE_DYNAMIC );
   224         -    pMem->xDel((void *)(pMem->z));
          236  +    sqlite3VdbeDestructor(pMem);
   225    237     }
   226    238   
   227    239     pMem->z = pMem->zMalloc;
   228    240     pMem->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Static);
   229    241     return SQLITE_OK;
   230    242   }
   231    243   
................................................................................
   459    471     if( p->flags&MEM_Agg ){
   460    472       sqlite3VdbeMemFinalize(p, p->u.pDef);
   461    473       assert( (p->flags & MEM_Agg)==0 );
   462    474       testcase( p->flags & MEM_Dyn );
   463    475     }
   464    476     if( p->flags&MEM_Dyn ){
   465    477       assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 );
   466         -    p->xDel((void *)p->z);
          478  +    sqlite3VdbeDestructor(p);
   467    479     }
   468    480     p->flags = MEM_Null;
   469    481   }
   470    482   
   471    483   /*
   472    484   ** Release memory held by the Mem p, both external memory cleared
   473    485   ** by p->xDel and memory in p->zMalloc.
................................................................................
   836    848   ){
   837    849     assert( pMem->flags==MEM_Null );
   838    850     pMem->u.zPType = zPType ? zPType : "";
   839    851     pMem->z = pPtr;
   840    852     pMem->flags = MEM_Null|MEM_Dyn|MEM_Subtype|MEM_Term;
   841    853     pMem->eSubtype = 'p';
   842    854     pMem->xDel = xDestructor ? xDestructor : sqlite3NoopDestructor;
          855  +  pMem->pDelPtr = 0;
   843    856   }
   844    857   
   845    858   #ifndef SQLITE_OMIT_FLOATING_POINT
   846    859   /*
   847    860   ** Delete any previous value and set the value stored in *pMem to val,
   848    861   ** manifest type REAL.
   849    862   */
................................................................................
   881    894     assert( !sqlite3VdbeMemIsRowSet(pMem) );
   882    895     sqlite3VdbeMemRelease(pMem);
   883    896     p = sqlite3RowSetInit(db);
   884    897     if( p==0 ) return SQLITE_NOMEM;
   885    898     pMem->z = (char*)p;
   886    899     pMem->flags = MEM_Blob|MEM_Dyn;
   887    900     pMem->xDel = sqlite3RowSetDelete;
          901  +  pMem->pDelPtr = 0;
   888    902     return SQLITE_OK;
   889    903   }
   890    904   
   891    905   /*
   892    906   ** Return true if the Mem object contains a TEXT or BLOB that is
   893    907   ** too large - whose size exceeds SQLITE_MAX_LENGTH.
   894    908   */
................................................................................
  1077   1091       sqlite3VdbeMemRelease(pMem);
  1078   1092       pMem->zMalloc = pMem->z = (char *)z;
  1079   1093       pMem->szMalloc = sqlite3DbMallocSize(pMem->db, pMem->zMalloc);
  1080   1094     }else{
  1081   1095       sqlite3VdbeMemRelease(pMem);
  1082   1096       pMem->z = (char *)z;
  1083   1097       pMem->xDel = xDel;
         1098  +    pMem->pDelPtr = 0;
  1084   1099       flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn);
  1085   1100     }
  1086   1101   
  1087   1102     pMem->n = nByte;
  1088   1103     pMem->flags = flags;
  1089   1104     pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);
  1090   1105