]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Experimental support for new sqlite3_bind_blob() and sqlite3_bind_text() custom-destructors
authordrh <drh@noemail.net>
Fri, 14 Dec 2018 21:58:06 +0000 (21:58 +0000)
committerdrh <drh@noemail.net>
Fri, 14 Dec 2018 21:58:06 +0000 (21:58 +0000)
interfaces that take an extra void* argument that is passed into the
destructor in front of the object that is to be destroyed.

FossilOrigin-Name: 33a1924ebb754d8e4374dbedb310170867bdb8121e1bb1ff5215e0526c32c62d

manifest
manifest.uuid
src/sqlite.h.in
src/vdbe.c
src/vdbeInt.h
src/vdbeapi.c
src/vdbemem.c

index 176dca0a774c178e359e556822069fcfca034df1..1aae48af2c7f9da8d8c1eb48af87e3eeabd64338 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sharmless\scompiler\swarnings.
-D 2018-12-14T18:11:02.867
+C Experimental\ssupport\sfor\snew\ssqlite3_bind_blob()\sand\ssqlite3_bind_text()\ninterfaces\sthat\stake\san\sextra\svoid*\sargument\sthat\sis\spassed\sinto\sthe\ndestructor\sin\sfront\sof\sthe\sobject\sthat\sis\sto\sbe\sdestroyed.
+D 2018-12-14T21:58:06.283
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in d8b254f8bb81bab43c340d70d17dc3babab40fcc8a348c8255881f780a45fee6
@@ -509,7 +509,7 @@ F src/resolve.c 72fe8cae7326b979e7258ab4c531956951e1a5f3fe8644c646abaec1b2eb6d95
 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
 F src/select.c 8c7317d5ee920516a56b8b4ca79fbfca70a1f8b52d67e884c808ea3a016c04e3
 F src/shell.c.in e1790e0d3607fca70ce61e5a0c83885d82f33ebe362edfb1cb66342d12c182d0
-F src/sqlite.h.in 92fd656c26cc76de9fa8c5bf1a473066e3b5c6da345a447679f0f44de1aa4edd
+F src/sqlite.h.in d1a34a2ca2b6b1886bf0e3653a0e20d32d2d01bd8f049ede11bc3fb0f1af1996
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 960f1b86c3610fa23cb6a267572a97dcf286e77aa0dd3b9b23292ffaa1ea8683
 F src/sqliteInt.h 3dda7ba0ea00f591c18405e5061d10041e0fcd5934e2542f29f8c8cffd73c242
@@ -578,13 +578,13 @@ F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
 F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
 F src/vacuum.c 3ffe64ecfc94b7528c5d7bdb1c3a19d72fec63f2aa846e3b90f8de5dbbddf5aa
-F src/vdbe.c 55bafc424748d9ed505ab2680736e51d1bb05c01e9885cbb3b287b51dc8b47ec
+F src/vdbe.c 2f53edc41ca5be863513009fcfcf0a56c5f84d4e95e435ca7af18c2a849be630
 F src/vdbe.h 8990d668a89890a33326b0a29b992c4014b72f3b6cdcd9ee0e190593c247f9b0
-F src/vdbeInt.h 73f5051923f3f29779bfc374c0c68e23b8e5e3792def2e33e51b427edb890abd
-F src/vdbeapi.c 57a2d794a8833f269b878dbc24e955369bdb379af6c4e93ebc5ce1a20fa3daf4
+F src/vdbeInt.h fad23d9a89e38e522a453d29ff9a2da25531386ed64e6821ee5f0d9775d75e3f
+F src/vdbeapi.c b827ec57ed25c8d42011b7736026599bb7bfbaf99c64d99a622698bf93f110ab
 F src/vdbeaux.c f00d9b32a250b829a3c00140255a1c37a6463d726bb87ed6bbb80a1ce76a56bd
 F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
-F src/vdbemem.c 7b3305bc4a5139f4536ac9b5f61da0f915e49d2e3fdfa87dfdfa9d7aba8bc1e9
+F src/vdbemem.c a6b69d1f81b55941fc23232f5dee84401b1a91f783c905ff0e47292fd7b6e9a1
 F src/vdbesort.c 90aad5a92608f2dd771c96749beabdb562c9d881131a860a7a5bccf66dc3be7f
 F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392
 F src/vtab.c 70188a745dc4e57d26e942681ff4b2912b7c8249ad5de3f60f0677b4337bcfaa
@@ -1787,7 +1787,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 395599116d801324f0763e59bc5e2fc8622aa5b7572e0c1c9a982efbb3cc8280
-R df4c1da54dfb761eed985ced81211d04
+P 27221c69901d2b4546167639c4a3c8f54b2e18820f1346870fa26b7c919027db
+R 41b906f86f0b7e0783c9fe4763c1bfdc
+T *branch * custom-destructors
+T *sym-custom-destructors *
+T -sym-trunk *
 U drh
-Z 41e7a1dc9bc588455770787287d46c8d
+Z 860de7e20e51ed31fca490688a77e304
index 3ffd7af8ce543962ea4b0b24fc1454f39411b48b..a9639f4bbc09719af122b4be498ef408009b7603 100644 (file)
@@ -1 +1 @@
-27221c69901d2b4546167639c4a3c8f54b2e18820f1346870fa26b7c919027db
\ No newline at end of file
+33a1924ebb754d8e4374dbedb310170867bdb8121e1bb1ff5215e0526c32c62d
\ No newline at end of file
index 08d499037ab16d0f449919122f12ba4218f17aaf..5f6a4fa20eeadd4fd2752b1bb0ee6387825be8de 100644 (file)
@@ -4060,6 +4060,8 @@ typedef struct sqlite3_context sqlite3_context;
 int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
 int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64,
                         void(*)(void*));
+int sqlite3_bind_blob64dx(sqlite3_stmt*, int, const void*, sqlite3_uint64,
+                          void(*)(void*,void*),void*);
 int sqlite3_bind_double(sqlite3_stmt*, int, double);
 int sqlite3_bind_int(sqlite3_stmt*, int, int);
 int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
@@ -4068,6 +4070,8 @@ int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
 int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
 int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
                          void(*)(void*), unsigned char encoding);
+int sqlite3_bind_text64dx(sqlite3_stmt*, int, const char*, sqlite3_uint64,
+                          void(*)(void*,void*),void*,unsigned char encoding);
 int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
 int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*,void(*)(void*));
 int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
@@ -5336,6 +5340,8 @@ typedef void (*sqlite3_destructor_type)(void*);
 void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
 void sqlite3_result_blob64(sqlite3_context*,const void*,
                            sqlite3_uint64,void(*)(void*));
+void sqlite3_result_blob64dx(sqlite3_context*,const void*,
+                             sqlite3_uint64,void(*)(void*,void*),void*);
 void sqlite3_result_double(sqlite3_context*, double);
 void sqlite3_result_error(sqlite3_context*, const char*, int);
 void sqlite3_result_error16(sqlite3_context*, const void*, int);
@@ -5348,6 +5354,8 @@ void sqlite3_result_null(sqlite3_context*);
 void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
 void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
                            void(*)(void*), unsigned char encoding);
+void sqlite3_result_text64dx(sqlite3_context*, const char*,sqlite3_uint64,
+                             void(*)(void*,void*),void*,unsigned char encoding);
 void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
 void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
 void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
index ebd599342a242a457b2efbf0956f31ab76c48836..752cd31999d70c551d6a566e221d958443b17aba 100644 (file)
@@ -6092,6 +6092,7 @@ case OP_Program: {        /* jump */
     pRt->z = (char*)pFrame;
     pRt->n = nByte;
     pRt->xDel = sqlite3VdbeFrameMemDel;
+    pRt->pDelPtr = 0;
 
     pFrame->v = p;
     pFrame->nChildMem = nMem;
index 70543526c1bc4342c1d9ed9e7c5ae6765ab8b582..f60da61023f1470e55b289a36614ac893585dabd 100644 (file)
@@ -215,6 +215,7 @@ struct sqlite3_value {
   u32 uTemp;          /* Transient storage for serial_type in OP_MakeRecord */
   sqlite3 *db;        /* The associated database connection */
   void (*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */
+  void *pDelPtr;      /* Context information for the delete */
 #ifdef SQLITE_DEBUG
   Mem *pScopyFrom;    /* This Mem is a shallow copy of pScopyFrom */
   u16 mScopyFlags;    /* flags value immediately after the shallow copy */
index 23b19273b614f3ab83f0e0f51751b2a7b16fa16b..ed80ffd800275f5fb905b6eb2ba401db9847999c 100644 (file)
@@ -321,15 +321,19 @@ static void setResultStrOrError(
   const char *z,          /* String pointer */
   int n,                  /* Bytes in string, or negative */
   u8 enc,                 /* Encoding of z.  0 for BLOBs */
-  void (*xDel)(void*)     /* Destructor function */
+  void (*xDel)(void*),    /* Destructor function */
+  void *pDelPtr           /* Context for the destructor */
 ){
   if( sqlite3VdbeMemSetStr(pCtx->pOut, z, n, enc, xDel)==SQLITE_TOOBIG ){
     sqlite3_result_error_toobig(pCtx);
+  }else{
+    pCtx->pOut->pDelPtr = pDelPtr;
   }
 }
 static int invokeValueDestructor(
   const void *p,             /* Value to destroy */
   void (*xDel)(void*),       /* The destructor */
+  void *pDelPtr,             /* Destructor context */
   sqlite3_context *pCtx      /* Set a SQLITE_TOOBIG error if no NULL */
 ){
   assert( xDel!=SQLITE_DYNAMIC );
@@ -337,6 +341,8 @@ static int invokeValueDestructor(
     /* noop */
   }else if( xDel==SQLITE_TRANSIENT ){
     /* noop */
+  }else if( pDelPtr ){
+    (*(void(*)(void*,void*))xDel)(pDelPtr,(void*)p);
   }else{
     xDel((void*)p);
   }
@@ -351,7 +357,7 @@ void sqlite3_result_blob(
 ){
   assert( n>=0 );
   assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
-  setResultStrOrError(pCtx, z, n, 0, xDel);
+  setResultStrOrError(pCtx, z, n, 0, xDel, 0);
 }
 void sqlite3_result_blob64(
   sqlite3_context *pCtx, 
@@ -362,9 +368,25 @@ void sqlite3_result_blob64(
   assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
   assert( xDel!=SQLITE_DYNAMIC );
   if( n>0x7fffffff ){
-    (void)invokeValueDestructor(z, xDel, pCtx);
+    (void)invokeValueDestructor(z, xDel, 0, pCtx);
   }else{
-    setResultStrOrError(pCtx, z, (int)n, 0, xDel);
+    setResultStrOrError(pCtx, z, (int)n, 0, xDel, 0);
+  }
+}
+void sqlite3_result_blob64dx(
+  sqlite3_context *pCtx, 
+  const void *z, 
+  sqlite3_uint64 n,
+  void (*xDel)(void*,void*),
+  void *pDelPtr
+){
+  assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
+  assert( ((void(*)(void*))xDel)!=SQLITE_DYNAMIC );
+  if( n>0x7fffffff ){
+    (void)invokeValueDestructor(z, (void(*)(void*))xDel, pDelPtr, pCtx);
+  }else{
+    setResultStrOrError(pCtx, z, (int)n, 0,
+                        (void(*)(void*))xDel, pDelPtr);
   }
 }
 void sqlite3_result_double(sqlite3_context *pCtx, double rVal){
@@ -420,7 +442,7 @@ void sqlite3_result_text(
   void (*xDel)(void *)
 ){
   assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
-  setResultStrOrError(pCtx, z, n, SQLITE_UTF8, xDel);
+  setResultStrOrError(pCtx, z, n, SQLITE_UTF8, xDel, 0);
 }
 void sqlite3_result_text64(
   sqlite3_context *pCtx, 
@@ -433,9 +455,9 @@ void sqlite3_result_text64(
   assert( xDel!=SQLITE_DYNAMIC );
   if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
   if( n>0x7fffffff ){
-    (void)invokeValueDestructor(z, xDel, pCtx);
+    (void)invokeValueDestructor(z, xDel, 0, pCtx);
   }else{
-    setResultStrOrError(pCtx, z, (int)n, enc, xDel);
+    setResultStrOrError(pCtx, z, (int)n, enc, xDel, 0);
   }
 }
 #ifndef SQLITE_OMIT_UTF16
@@ -446,7 +468,7 @@ void sqlite3_result_text16(
   void (*xDel)(void *)
 ){
   assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
-  setResultStrOrError(pCtx, z, n, SQLITE_UTF16NATIVE, xDel);
+  setResultStrOrError(pCtx, z, n, SQLITE_UTF16NATIVE, xDel, 0);
 }
 void sqlite3_result_text16be(
   sqlite3_context *pCtx, 
@@ -455,7 +477,7 @@ void sqlite3_result_text16be(
   void (*xDel)(void *)
 ){
   assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
-  setResultStrOrError(pCtx, z, n, SQLITE_UTF16BE, xDel);
+  setResultStrOrError(pCtx, z, n, SQLITE_UTF16BE, xDel, 0);
 }
 void sqlite3_result_text16le(
   sqlite3_context *pCtx, 
@@ -464,7 +486,7 @@ void sqlite3_result_text16le(
   void (*xDel)(void *)
 ){
   assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
-  setResultStrOrError(pCtx, z, n, SQLITE_UTF16LE, xDel);
+  setResultStrOrError(pCtx, z, n, SQLITE_UTF16LE, xDel, 0);
 }
 #endif /* SQLITE_OMIT_UTF16 */
 void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){
@@ -972,6 +994,7 @@ static const Mem *columnNullValue(void){
         /* .uTemp      = */ (u32)0,
         /* .db         = */ (sqlite3*)0,
         /* .xDel       = */ (void(*)(void*))0,
+        /* .pDelPtr    = */ (void*)0,
 #ifdef SQLITE_DEBUG
         /* .pScopyFrom = */ (Mem*)0,
         /* .mScopyFlags= */ 0,
@@ -1313,6 +1336,7 @@ static int bindText(
   const void *zData,     /* Pointer to the data to be bound */
   int nData,             /* Number of bytes of data to be bound */
   void (*xDel)(void*),   /* Destructor for the data */
+  void *pDelPtr,         /* Destructor context */
   u8 encoding            /* Encoding for the data */
 ){
   Vdbe *p = (Vdbe *)pStmt;
@@ -1324,8 +1348,11 @@ static int bindText(
     if( zData!=0 ){
       pVar = &p->aVar[i-1];
       rc = sqlite3VdbeMemSetStr(pVar, zData, nData, encoding, xDel);
-      if( rc==SQLITE_OK && encoding!=0 ){
-        rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
+      if( rc==SQLITE_OK ){
+        pVar->pDelPtr = pDelPtr;
+        if( encoding!=0 ){
+          rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
+        }
       }
       if( rc ){
         sqlite3Error(p->db, rc);
@@ -1353,7 +1380,7 @@ int sqlite3_bind_blob(
 #ifdef SQLITE_ENABLE_API_ARMOR
   if( nData<0 ) return SQLITE_MISUSE_BKPT;
 #endif
-  return bindText(pStmt, i, zData, nData, xDel, 0);
+  return bindText(pStmt, i, zData, nData, xDel, 0, 0);
 }
 int sqlite3_bind_blob64(
   sqlite3_stmt *pStmt, 
@@ -1364,9 +1391,25 @@ int sqlite3_bind_blob64(
 ){
   assert( xDel!=SQLITE_DYNAMIC );
   if( nData>0x7fffffff ){
-    return invokeValueDestructor(zData, xDel, 0);
+    return invokeValueDestructor(zData, xDel, 0, 0);
+  }else{
+    return bindText(pStmt, i, zData, (int)nData, xDel, 0, 0);
+  }
+}
+int sqlite3_bind_blob64dx(
+  sqlite3_stmt *pStmt, 
+  int i, 
+  const void *zData, 
+  sqlite3_uint64 nData, 
+  void (*xDel)(void*,void*),
+  void *pDelPtr
+){
+  assert( (void(*)(void*))xDel!=SQLITE_DYNAMIC );
+  if( nData>0x7fffffff ){
+    return invokeValueDestructor(zData, (void(*)(void*))xDel, pDelPtr, 0);
   }else{
-    return bindText(pStmt, i, zData, (int)nData, xDel, 0);
+    return bindText(pStmt, i, zData, (int)nData,
+                    (void(*)(void*))xDel, pDelPtr, 0);
   }
 }
 int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
@@ -1426,7 +1469,7 @@ int sqlite3_bind_text(
   int nData, 
   void (*xDel)(void*)
 ){
-  return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8);
+  return bindText(pStmt, i, zData, nData, xDel, 0, SQLITE_UTF8);
 }
 int sqlite3_bind_text64( 
   sqlite3_stmt *pStmt, 
@@ -1438,10 +1481,28 @@ int sqlite3_bind_text64(
 ){
   assert( xDel!=SQLITE_DYNAMIC );
   if( nData>0x7fffffff ){
-    return invokeValueDestructor(zData, xDel, 0);
+    return invokeValueDestructor(zData, xDel, 0, 0);
+  }else{
+    if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
+    return bindText(pStmt, i, zData, (int)nData, xDel, 0, enc);
+  }
+}
+int sqlite3_bind_text64dx( 
+  sqlite3_stmt *pStmt, 
+  int i, 
+  const char *zData, 
+  sqlite3_uint64 nData, 
+  void (*xDel)(void*,void*),
+  void *pDelPtr,
+  unsigned char enc
+){
+  assert( (void(*)(void*))xDel!=SQLITE_DYNAMIC );
+  if( nData>0x7fffffff ){
+    return invokeValueDestructor(zData, (void(*)(void*))xDel, pDelPtr, 0);
   }else{
     if( enc==SQLITE_UTF16 ) enc = SQLITE_UTF16NATIVE;
-    return bindText(pStmt, i, zData, (int)nData, xDel, enc);
+    return bindText(pStmt, i, zData, (int)nData, 
+                    (void(*)(void*))xDel, pDelPtr, enc);
   }
 }
 #ifndef SQLITE_OMIT_UTF16
@@ -1452,7 +1513,7 @@ int sqlite3_bind_text16(
   int nData, 
   void (*xDel)(void*)
 ){
-  return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE);
+  return bindText(pStmt, i, zData, nData, xDel, 0, SQLITE_UTF16NATIVE);
 }
 #endif /* SQLITE_OMIT_UTF16 */
 int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
@@ -1475,7 +1536,7 @@ int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
       break;
     }
     case SQLITE_TEXT: {
-      rc = bindText(pStmt,i,  pValue->z, pValue->n, SQLITE_TRANSIENT,
+      rc = bindText(pStmt,i,  pValue->z, pValue->n, SQLITE_TRANSIENT, 0,
                               pValue->enc);
       break;
     }
index db8feddfb273cd890e722dfb2104888c5a7e2a10..4b8580cad0650067faf9d1955da3ac4260e575bc 100644 (file)
@@ -177,6 +177,18 @@ int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
 #endif
 }
 
+/*
+** Invoke the destructor
+*/
+void sqlite3VdbeDestructor(Mem *pMem){
+  assert( pMem->xDel!=0 );
+  if( pMem->pDelPtr==0 ){
+    pMem->xDel((void*)(pMem->z));
+  }else{
+    ((void(*)(void*,void*))(pMem->xDel))(pMem->pDelPtr, (void*)pMem->z);
+  }
+}
+
 /*
 ** Make sure pMem->z points to a writable allocation of at least 
 ** min(n,32) bytes.
@@ -221,7 +233,7 @@ SQLITE_NOINLINE int sqlite3VdbeMemGrow(Mem *pMem, int n, int bPreserve){
   }
   if( (pMem->flags&MEM_Dyn)!=0 ){
     assert( pMem->xDel!=0 && pMem->xDel!=SQLITE_DYNAMIC );
-    pMem->xDel((void *)(pMem->z));
+    sqlite3VdbeDestructor(pMem);
   }
 
   pMem->z = pMem->zMalloc;
@@ -463,7 +475,7 @@ static SQLITE_NOINLINE void vdbeMemClearExternAndSetNull(Mem *p){
   }
   if( p->flags&MEM_Dyn ){
     assert( p->xDel!=SQLITE_DYNAMIC && p->xDel!=0 );
-    p->xDel((void *)p->z);
+    sqlite3VdbeDestructor(p);
   }
   p->flags = MEM_Null;
 }
@@ -840,6 +852,7 @@ void sqlite3VdbeMemSetPointer(
   pMem->flags = MEM_Null|MEM_Dyn|MEM_Subtype|MEM_Term;
   pMem->eSubtype = 'p';
   pMem->xDel = xDestructor ? xDestructor : sqlite3NoopDestructor;
+  pMem->pDelPtr = 0;
 }
 
 #ifndef SQLITE_OMIT_FLOATING_POINT
@@ -885,6 +898,7 @@ int sqlite3VdbeMemSetRowSet(Mem *pMem){
   pMem->z = (char*)p;
   pMem->flags = MEM_Blob|MEM_Dyn;
   pMem->xDel = sqlite3RowSetDelete;
+  pMem->pDelPtr = 0;
   return SQLITE_OK;
 }
 
@@ -1081,6 +1095,7 @@ int sqlite3VdbeMemSetStr(
     sqlite3VdbeMemRelease(pMem);
     pMem->z = (char *)z;
     pMem->xDel = xDel;
+    pMem->pDelPtr = 0;
     flags |= ((xDel==SQLITE_STATIC)?MEM_Static:MEM_Dyn);
   }