]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add a destructor argument to sqlite3_bind_pointer()
authordrh <drh@noemail.net>
Thu, 27 Jul 2017 03:48:02 +0000 (03:48 +0000)
committerdrh <drh@noemail.net>
Thu, 27 Jul 2017 03:48:02 +0000 (03:48 +0000)
and sqlite3_result_pointer().

FossilOrigin-Name: 3d9e841f6011480ebb8a6d860da72af7fa545983e08835ddef2cac96e5f5cd4b

14 files changed:
ext/fts3/fts3.c
ext/fts5/fts5_tcl.c
ext/fts5/fts5_test_mi.c
ext/misc/carray.c
ext/rtree/rtree.c
manifest
manifest.uuid
src/sqlite.h.in
src/sqlite3ext.h
src/vdbe.c
src/vdbeInt.h
src/vdbeapi.c
src/vdbeaux.c
src/vdbemem.c

index ca17888276b317f7d7b7e1e39e160c3cc15178b0..f5145426e01e2e926586bd705a9884ec5933a455 100644 (file)
@@ -3353,7 +3353,7 @@ static int fts3ColumnMethod(
   switch( iCol-p->nColumn ){
     case 0:
       /* The special 'table-name' column */
-      sqlite3_result_pointer(pCtx, pCsr, "fts3cursor");
+      sqlite3_result_pointer(pCtx, pCsr, "fts3cursor", 0);
       break;
 
     case 1:
index 99120e3d27490f774e915160b953f8cb2e5a1ed8..e8d4c32a4621bb56493567dfdc60038914ce043c 100644 (file)
@@ -104,7 +104,7 @@ static int SQLITE_TCLAPI f5tDbAndApi(
       Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
       return TCL_ERROR;
     }
-    sqlite3_bind_pointer(pStmt, 1, (void*)&pApi, "fts5_api_ptr");
+    sqlite3_bind_pointer(pStmt, 1, (void*)&pApi, "fts5_api_ptr", 0);
     sqlite3_step(pStmt);
 
     if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
index 49220b641077893dcb97856ed37b646f832c44df..481d09b2caeabddcf5a2374d1e1dd84dac2840b7 100644 (file)
@@ -75,7 +75,7 @@ static int fts5_api_from_db(sqlite3 *db, fts5_api **ppApi){
   *ppApi = 0;
   rc = sqlite3_prepare(db, "SELECT fts5(?1)", -1, &pStmt, 0);
   if( rc==SQLITE_OK ){
-    sqlite3_bind_pointer(pStmt, 1, (void*)ppApi, "fts5_api_ptr");
+    sqlite3_bind_pointer(pStmt, 1, (void*)ppApi, "fts5_api_ptr", 0);
     (void)sqlite3_step(pStmt);
     rc = sqlite3_finalize(pStmt);
   }
index b182ea1bcf22b30ef7dbb234540d7115143ac27d..b39904ae15348b3c2954cace6addd33adfbf8991 100644 (file)
@@ -24,7 +24,7 @@
 **
 **    static int aX[] = { 53, 9, 17, 2231, 4, 99 };
 **    int i = sqlite3_bind_parameter_index(pStmt, "$ptr");
-**    sqlite3_bind_value(pStmt, i, aX, "carray");
+**    sqlite3_bind_value(pStmt, i, aX, "carray", 0);
 **
 ** There is an optional third parameter to determine the datatype of
 ** the C-language array.  Allowed values of the third parameter are
@@ -377,7 +377,7 @@ static void inttoptrFunc(
     int i32 = i64 & 0xffffffff;
     memcpy(&p, &i32, sizeof(p));
   }
-  sqlite3_result_pointer(context, p, "carray");
+  sqlite3_result_pointer(context, p, "carray", 0);
 }
 #endif /* SQLITE_TEST */
 
index 9f7d528f647ab0f5a4299261eae3a2ff9da32745..d97cb454910bd7c725571a6a9925d4909759eac4 100644 (file)
@@ -339,14 +339,6 @@ struct RtreeGeomCallback {
   void *pContext;
 };
 
-
-/*
-** Value for the first field of every RtreeMatchArg object. The MATCH
-** operator tests that the first field of a blob operand matches this
-** value to avoid operating on invalid blobs (which could cause a segfault).
-*/
-#define RTREE_GEOMETRY_MAGIC 0x891245AB
-
 /*
 ** An instance of this structure (in the form of a BLOB) is returned by
 ** the SQL functions that sqlite3_rtree_geometry_callback() and
@@ -354,7 +346,7 @@ struct RtreeGeomCallback {
 ** operand to the MATCH operator of an R-Tree.
 */
 struct RtreeMatchArg {
-  u32 magic;                  /* Always RTREE_GEOMETRY_MAGIC */
+  u32 iSize;                  /* Size of this object */
   RtreeGeomCallback cb;       /* Info about the callback functions */
   int nParam;                 /* Number of parameters to the SQL function */
   sqlite3_value **apSqlParam; /* Original SQL parameter values */
@@ -1649,33 +1641,17 @@ static int findLeafNode(
 ** operator.
 */
 static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){
-  RtreeMatchArg *pBlob;              /* BLOB returned by geometry function */
+  RtreeMatchArg *pBlob, *pSrc;       /* BLOB returned by geometry function */
   sqlite3_rtree_query_info *pInfo;   /* Callback information */
-  int nBlob;                         /* Size of the geometry function blob */
-  int nExpected;                     /* Expected size of the BLOB */
-
-  /* Check that value is actually a blob. */
-  if( sqlite3_value_type(pValue)!=SQLITE_BLOB ) return SQLITE_ERROR;
 
-  /* Check that the blob is roughly the right size. */
-  nBlob = sqlite3_value_bytes(pValue);
-  if( nBlob<(int)sizeof(RtreeMatchArg) ){
-    return SQLITE_ERROR;
-  }
-
-  pInfo = (sqlite3_rtree_query_info*)sqlite3_malloc( sizeof(*pInfo)+nBlob );
+  pSrc = sqlite3_value_pointer(pValue, "RtreeMatchArg");
+  if( pSrc==0 ) return SQLITE_ERROR;
+  pInfo = (sqlite3_rtree_query_info*)
+                sqlite3_malloc64( sizeof(*pInfo)+pSrc->iSize );
   if( !pInfo ) return SQLITE_NOMEM;
   memset(pInfo, 0, sizeof(*pInfo));
   pBlob = (RtreeMatchArg*)&pInfo[1];
-
-  memcpy(pBlob, sqlite3_value_blob(pValue), nBlob);
-  nExpected = (int)(sizeof(RtreeMatchArg) +
-                    pBlob->nParam*sizeof(sqlite3_value*) +
-                    (pBlob->nParam-1)*sizeof(RtreeDValue));
-  if( pBlob->magic!=RTREE_GEOMETRY_MAGIC || nBlob!=nExpected ){
-    sqlite3_free(pInfo);
-    return SQLITE_ERROR;
-  }
+  memcpy(pBlob, pSrc, pSrc->iSize);
   pInfo->pContext = pBlob->cb.pContext;
   pInfo->nParam = pBlob->nParam;
   pInfo->aParam = pBlob->aParam;
@@ -3713,7 +3689,7 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
     sqlite3_result_error_nomem(ctx);
   }else{
     int i;
-    pBlob->magic = RTREE_GEOMETRY_MAGIC;
+    pBlob->iSize = nBlob;
     pBlob->cb = pGeomCtx[0];
     pBlob->apSqlParam = (sqlite3_value**)&pBlob->aParam[nArg];
     pBlob->nParam = nArg;
@@ -3730,7 +3706,7 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
       sqlite3_result_error_nomem(ctx);
       rtreeMatchArgFree(pBlob);
     }else{
-      sqlite3_result_blob(ctx, pBlob, nBlob, rtreeMatchArgFree);
+      sqlite3_result_pointer(ctx, pBlob, "RtreeMatchArg", rtreeMatchArgFree);
     }
   }
 }
index 7615139f58f81bc91a8b12139248118a773b6ebb..bb604c33be6d2386e00e96eaa49bf7e16031fcde 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Release\scandidate\s2\sfor\s3.20.0.
-D 2017-07-25T15:12:01.300
+C Add\sa\sdestructor\sargument\sto\ssqlite3_bind_pointer()\s\nand\ssqlite3_result_pointer().
+D 2017-07-27T03:48:02.500
 F Makefile.in d9873c9925917cca9990ee24be17eb9613a668012c85a343aef7e5536ae266e8
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc 02b469e9dcd5b7ee63fc1fb05babc174260ee4cfa4e0ef2e48c3c6801567a016
@@ -70,7 +70,7 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
 F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
 F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
 F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
-F ext/fts3/fts3.c dfda8bb464d229785e0528fcf7017b4f8e95656d40d28333dfc3f3363bbe229e
+F ext/fts3/fts3.c f1c58503bc81c3dab1a70b25e146878ae40fccc716fd7c9b817995b661bc896f
 F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
 F ext/fts3/fts3Int.h eb2502000148e80913b965db3e59f29251266d0a
 F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1
@@ -108,8 +108,8 @@ F ext/fts5/fts5_hash.c 32be400cf761868c9db33efe81a06eb19a17c5402ad477ee9efb51301
 F ext/fts5/fts5_index.c 2ce9d50ec5508b8205615aad69e1c9b2c77f017f21d4479e1fb2079c01fdd017
 F ext/fts5/fts5_main.c 24868f88ab2a865defbba7a92eebeb726cc991eb092b71b5f5508f180c72605b
 F ext/fts5/fts5_storage.c fb5ef3c27073f67ade2e1bea08405f9e43f68f5f3676ed0ab7013bce5ba10be6
-F ext/fts5/fts5_tcl.c 4fab0eaba3d8a82c36195c9268e68e64c9b7acbd9e6b054e84fcf2ee97672714
-F ext/fts5/fts5_test_mi.c 03cfc256bb2dfe0d0f9516daea894ea651a7105cd3bdcfbd6c1f4d3145634931
+F ext/fts5/fts5_tcl.c a7df39442ae674dde877cf06fe02ebb7658e69c179a4d223241c90df4f14b54e
+F ext/fts5/fts5_test_mi.c 65864ba1e5c34a61d409c4c587e0bbe0466eb4f8f478d85dc42a92caad1338e6
 F ext/fts5/fts5_test_tok.c ffd657dd67e7fcdb31bf63fb60b6d867299a581d0f46e97086abacd66c2a9b26
 F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8
 F ext/fts5/fts5_unicode2.c b450b209b157d598f7b9df9f837afb75a14c24bf
@@ -256,7 +256,7 @@ F ext/lsm1/test/lsm1_simple.test 3bb38951450cd1f12a6c294949334d6fbb109a3da38c48e
 F ext/misc/README.md 8e008c8d2b02e09096b31dfba033253ac27c6c06a18aa5826e299fa7601d90b2
 F ext/misc/amatch.c 6db4607cb17c54b853a2d7c7c36046d004853f65b9b733e6f019d543d5dfae87
 F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
-F ext/misc/carray.c 880684b2796ef6ad915094093297eede40db6c07f280c7f491c8eff72ea03ec7
+F ext/misc/carray.c ed96c218ea940b85c9a274c4d9c59fe9491c299147a38a8bba537687bd6c6005
 F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704
 F ext/misc/completion.c 52c3f01523e3e387eb321b4739a89d1fe47cbe6025aa1f2d8d3685e9e365df0f
 F ext/misc/compress.c 122faa92d25033d6c3f07c39231de074ab3d2e83
@@ -321,7 +321,7 @@ F ext/rbu/sqlite3rbu.c d1438580a451eebda3bfd42ef69b677512f00125285e0e4e789b6131a
 F ext/rbu/sqlite3rbu.h fc25e1fcd99b5c6d32b1b5b1c73122632e873ac89bd0be9bf646db362b7ce02c
 F ext/rbu/test_rbu.c ec18cfc69a104309df23c359e3c80306c9a6bdd1d2c53c8b70ae158e9832dcd6
 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
-F ext/rtree/rtree.c c5886d4ba7e7c66d0f9ee0b788d5532f8537ca04db19cec7f2f64dcf46e9be37
+F ext/rtree/rtree.c 4f1804b80ae06ddf7ff69192aacdceee283646dc6a328acb951f116147445212
 F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
 F ext/rtree/rtree1.test 4fdd60ae034e43f2fefc26492032d02e742e8b14d468b7c51d95a1e2fa47cf00
 F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
@@ -455,9 +455,9 @@ F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
 F src/select.c c6bf96a7f9d7d68f929de84738c599a30d0a725ab0b54420e70545743cd5ee7b
 F src/shell.c bd6a37cbe8bf64ef6a6a74fdc50f067d3148149b4ce2b4d03154663e66ded55f
 F src/shell.c.in b5725acacba95ccefa57b6d068f710e29ba8239c3aa704628a1902a1f729c175
-F src/sqlite.h.in 6832630003ce858f55c750181488f30aa167870110d843035e501729a6a1c4cf
+F src/sqlite.h.in 86a14aab0f03021bdc71e8a78091ca52931cdc3dc69633dacf9a511dfe9ee993
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
-F src/sqlite3ext.h 967154985ed2ae62f90d9029bb5b5071793d847f1696a2ebe9e8cc0b042ae60b
+F src/sqlite3ext.h 0f9f72b86a3792314f5db7a1dfbc2c82376bcd8d0919ceb80637bca126ec3c68
 F src/sqliteInt.h bd6be75bc43d38ada272ef0b3472bc44ef0cc15536bea22c349ca1a2812a19ce
 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
 F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
@@ -520,13 +520,13 @@ F src/update.c c443935c652af9365e033f756550b5032d02e1b06eb2cb890ed7511ae0c051dc
 F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
 F src/util.c fc081ec6f63448dcd80d3dfad35baecfa104823254a815b081a4d9fe76e1db23
 F src/vacuum.c 874c0f2f15ab2908748297d587d22d485ea96d55aaec91d4775dddb2e24d2ecf
-F src/vdbe.c 1e541ec7ff409bbabcc6b4f154957296fff5827c16c2ab0056348acae75685bf
+F src/vdbe.c d8437d81958fb9d1f3382586e5a2736258e72dc981631853ecfb66f5091ad90c
 F src/vdbe.h d50cadf12bcf9fb99117ef392ce1ea283aa429270481426b6e8b0280c101fd97
-F src/vdbeInt.h 19bd04a4211fe56c712ab35b48be77fd5a0579b851e9dea2cb8deade359b72b9
-F src/vdbeapi.c 52844a5a71712197be45f1c63d730c48a745c7457c959465cfb2b969af40a266
-F src/vdbeaux.c 3fe68bad02b33b09e08bdc0ad90d6b92b3d571f7864c3d047abca1bde050751c
+F src/vdbeInt.h 4f7034052871f5b358b8c733163505c2820868112494c73294084b20876591cd
+F src/vdbeapi.c 7fd45f2470bfc3b02313b4500c965b1848b827b736e3ff754b14861c9c13417f
+F src/vdbeaux.c 986c5cae1dcfda124e871a016274589f6b87ddfe4625f60ddf6a5cdb94f64517
 F src/vdbeblob.c 359891617358deefc85bef7bcf787fa6b77facb9
-F src/vdbemem.c fe8fce1cdc258320b465934039fe4b1230d63f81d6b81b1eac775b6eec00af0d
+F src/vdbemem.c 9d1dde677986b68a25b0f30190325ae173fa51d2991ccc7cffda984407cfc5d7
 F src/vdbesort.c f512c68d0bf7e0105316a5594c4329358c8ee9cae3b25138df041d97516c0372
 F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834
 F src/vtab.c 35b9bdc2b41de32a417141d12097bcc4e29a77ed7cdb8f836d1d2305d946b61b
@@ -1637,10 +1637,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 1ca707a4fb8db7aa85430413164265607ce727fc8a5afc3424b3abfb59921b39
-R 8215cf089e6d9a2d7dcbd4ee22b67db3
-T *branch * branch-3.20
-T *sym-branch-3.20 *
-T -sym-trunk *
+P f39cb76b3347baba22f2c329e74036710b64620414433a952de8d44da79ba8d9
+R f73e68c37e03cf44fd4c91b4fa2d5350
+T *branch * pointer-with-destructor
+T *sym-pointer-with-destructor *
+T -sym-branch-3.20 *
 U drh
-Z b5d895badf8b9b6a24951d6f900b8c5d
+Z d38f5fd0f536ce6fac398141bc9e08dd
index 1b810724b2895b0d60d00c90faae2b30b6378767..5c8402edf9bcb3ad9d434d98ac40f2238ecc5c0c 100644 (file)
@@ -1 +1 @@
-f39cb76b3347baba22f2c329e74036710b64620414433a952de8d44da79ba8d9
\ No newline at end of file
+3d9e841f6011480ebb8a6d860da72af7fa545983e08835ddef2cac96e5f5cd4b
\ No newline at end of file
index ea002b72068749bfd0459104926598687acb358b..93410d523fb8bad63593dba7dd70a506d0c2840c 100644 (file)
@@ -3883,17 +3883,18 @@ typedef struct sqlite3_context sqlite3_context;
 ** [sqlite3_blob_open | incremental BLOB I/O] routines.
 ** ^A negative value for the zeroblob results in a zero-length BLOB.
 **
-** ^The sqlite3_bind_pointer(S,I,P,T) routine causes the I-th parameter in
+** ^The sqlite3_bind_pointer(S,I,P,T,D) routine causes the I-th parameter in
 ** [prepared statement] S to have an SQL value of NULL, but to also be
-** associated with the pointer P of type T.
+** associated with the pointer P of type T.  ^D is either a NULL pointer or
+** a pointer to a destructor function that is called when P goes out of scope.
 ** ^The sqlite3_bind_pointer() routine can be used to pass
 ** host-language pointers into [application-defined SQL functions].
 ** ^A parameter that is initialized using [sqlite3_bind_pointer()] appears
 ** to be an ordinary SQL NULL value to everything other than
 ** [sqlite3_value_pointer()].  The T parameter should be a static string,
 ** preferably a string literal.  The procedure that invokes 
-** sqlite3_bind_pointer(S,I,P,T) continues to own the P and T pointers and
-** must guarantee that those pointers remain valid until after the last
+** sqlite3_bind_pointer(S,I,P,T,D) owns the T string and
+** must guarantee that it remains valid and unchanged until after the last
 ** access via [sqlite3_value_pointer()].  The sqlite3_bind_pointer() routine
 ** is part of the [pointer passing interface] added for SQLite 3.20.0.
 **
@@ -3930,7 +3931,7 @@ 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_value(sqlite3_stmt*, int, const sqlite3_value*);
-int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*);
+int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*,void(*)(void*));
 int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
 int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64);
 
@@ -4763,7 +4764,7 @@ SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
 ** extract UTF-16 strings as big-endian and little-endian respectively.
 **
 ** ^If [sqlite3_value] object V was initialized 
-** using [sqlite3_bind_pointer(S,I,P,X)] or [sqlite3_result_pointer(C,P,X)]
+** using [sqlite3_bind_pointer(S,I,P,X,D)] or [sqlite3_result_pointer(C,P,X,D)]
 ** and if X and Y are strings that compare equal according to strcmp(X,Y),
 ** then sqlite3_value_pointer(V,Y) will return the pointer P.  ^Otherwise,
 ** sqlite3_value_pointer(V,Y) returns a NULL.
@@ -5101,13 +5102,16 @@ typedef void (*sqlite3_destructor_type)(void*);
 ** [unprotected sqlite3_value] object is required, so either
 ** kind of [sqlite3_value] object can be used with this interface.
 **
-** ^The sqlite3_result_pointer(C,P,T) interface sets the result to an
+** ^The sqlite3_result_pointer(C,P,T,D) interface sets the result to an
 ** SQL NULL value, just like [sqlite3_result_null(C)], except that it
 ** also associates the host-language pointer P or type T with that 
 ** NULL value such that the pointer can be retrieved within an
 ** [application-defined SQL function] using [sqlite3_value_pointer()].
+** ^If the D parameter is not NULL, then it is a pointer to a destructor
+** for the P parameter.  ^The destructor D is invoked on P when the result
+** value goes out of scope.
 ** The T parameter should be a static string and preferably a string
-** literal. The procedure that invokes sqlite3_result_pointer(C,P,T)
+** literal. The procedure that invokes sqlite3_result_pointer(C,P,T,D)
 ** continues to own the P and T pointers and must guarantee that 
 ** those pointers remain valid until after the last access via
 ** [sqlite3_value_pointer()].  The sqlite3_result_pointer() routine
@@ -5136,7 +5140,7 @@ 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*));
 void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
-void sqlite3_result_pointer(sqlite3_context*, void*, const char*);
+void sqlite3_result_pointer(sqlite3_context*, void*,const char*,void(*)(void*));
 void sqlite3_result_zeroblob(sqlite3_context*, int n);
 int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);
 
index c585f17f2f9567901b065eb59fa1e0c646f4bb65..0f1712beedded9eeffc1653ff251a46cd06316e3 100644 (file)
@@ -289,8 +289,8 @@ struct sqlite3_api_routines {
                     sqlite3_stmt**,const char**);
   int (*prepare16_v3)(sqlite3*,const void*,int,unsigned int,
                       sqlite3_stmt**,const void**);
-  int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*);
-  void (*result_pointer)(sqlite3_context*,void*,const char*);
+  int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*));
+  void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*));
   void *(*value_pointer)(sqlite3_value*,const char*);
 };
 
index 3e6231e0d886ef922b8af3827dc011cfae098b87..7e105940f4600bc912e76899789bacfda2d00447 100644 (file)
@@ -416,7 +416,7 @@ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
       else *zCsr++ = z;
     }
     *(zCsr++) = ']';
-    if( f & MEM_Zero ){
+    if( (f & (MEM_Zero|MEM_Blob))==(MEM_Zero|MEM_Blob) ){
       sqlite3_snprintf(100, zCsr,"+%dz",pMem->u.nZero);
       zCsr += sqlite3Strlen30(zCsr);
     }
@@ -2735,7 +2735,7 @@ case OP_MakeRecord: {
   do{
     assert( memIsValid(pRec) );
     pRec->uTemp = serial_type = sqlite3VdbeSerialType(pRec, file_format, &len);
-    if( pRec->flags & MEM_Zero ){
+    if( (pRec->flags & MEM_Zero)!=0 && (pRec->flags & MEM_Blob)!=0 ){
       if( nData ){
         if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem;
       }else{
@@ -4411,7 +4411,7 @@ case OP_InsertInt: {
     x.nData = pData->n;
   }
   seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0);
-  if( pData->flags & MEM_Zero ){
+  if( (pData->flags & MEM_Zero)!=0 && (pData->flags & MEM_Blob)!=0 ){
     x.nZero = pData->u.nZero;
   }else{
     x.nZero = 0;
index 599fe704145688ff298fcafc762ace3b9faa8321..366496bf6a40ec7d3b1aff4862e2be58418abac4 100644 (file)
@@ -189,8 +189,8 @@ struct sqlite3_value {
   union MemValue {
     double r;           /* Real value used when MEM_Real is set in flags */
     i64 i;              /* Integer value used when MEM_Int is set in flags */
-    int nZero;          /* Used when bit MEM_Zero is set in flags */
-    void *pPtr;         /* Pointer when flags=MEM_NULL and eSubtype='p' */
+    int nZero;          /* Extra zero bytes when MEM_Zero and MEM_Blob set */
+    const char *zPType; /* Pointer type when MEM_Pointer and MEM_Null set */
     FuncDef *pDef;      /* Used only when flags==MEM_Agg */
     RowSet *pRowSet;    /* Used only when flags==MEM_RowSet */
     VdbeFrame *pFrame;  /* Used when flags==MEM_Frame */
@@ -240,13 +240,17 @@ struct sqlite3_value {
 #define MEM_Frame     0x0040   /* Value is a VdbeFrame object */
 #define MEM_Undefined 0x0080   /* Value is undefined */
 #define MEM_Cleared   0x0100   /* NULL set by OP_Null, not from data */
-#define MEM_TypeMask  0x81ff   /* Mask of type bits */
+#define MEM_TypeMask  0xc1ff   /* Mask of type bits */
 
 
 /* Whenever Mem contains a valid string or blob representation, one of
 ** the following flags must be set to determine the memory management
 ** policy for Mem.z.  The MEM_Term flag tells us whether or not the
 ** string is \000 or \u0000 terminated
+**
+** NB:  MEM_Zero and MEM_Pointer are the same value.  But MEM_Zero is
+** only value if MEM_Blob is also set, and MEM_Pointer is only valid
+** if MEM_Null is also set.
 */
 #define MEM_Term      0x0200   /* String rep is nul terminated */
 #define MEM_Dyn       0x0400   /* Need to call Mem.xDel() on Mem.z */
@@ -254,6 +258,7 @@ struct sqlite3_value {
 #define MEM_Ephem     0x1000   /* Mem.z points to an ephemeral string */
 #define MEM_Agg       0x2000   /* Mem.z points to an agg function context */
 #define MEM_Zero      0x4000   /* Mem.i contains count of 0s appended to blob */
+#define MEM_Pointer   0x4000   /* Mem.z is an extension pointer */
 #define MEM_Subtype   0x8000   /* Mem.eSubtype is valid */
 #ifdef SQLITE_OMIT_INCRBLOB
   #undef MEM_Zero
@@ -476,7 +481,7 @@ void sqlite3VdbeMemSetInt64(Mem*, i64);
 #else
   void sqlite3VdbeMemSetDouble(Mem*, double);
 #endif
-void sqlite3VdbeMemSetPointer(Mem*, void*, const char*);
+void sqlite3VdbeMemSetPointer(Mem*, void*, const char*, void(*)(void*));
 void sqlite3VdbeMemInit(Mem*,sqlite3*,u16);
 void sqlite3VdbeMemSetNull(Mem*);
 void sqlite3VdbeMemSetZeroBlob(Mem*,int);
index 35b194fffeff52dde9b47c5da5e588ea4abad7b1..e82b12b71a301c9d0766f87ee6e2b4158333d4c3 100644 (file)
@@ -201,12 +201,11 @@ unsigned int sqlite3_value_subtype(sqlite3_value *pVal){
 }
 void *sqlite3_value_pointer(sqlite3_value *pVal, const char *zPType){
   Mem *p = (Mem*)pVal;
-  if( p->flags==(MEM_Null|MEM_Subtype|MEM_Term|MEM_Static)
+  if( (p->flags&(MEM_AffMask|MEM_Pointer))==(MEM_Null|MEM_Pointer)
    && zPType!=0
-   && p->eSubtype=='p'
-   && strcmp(p->z, zPType)==0
+   && strcmp(p->u.zPType, zPType)==0
   ){
-    return p->u.pPtr;
+    return (void*)p->z;
   }else{
     return 0;
   }
@@ -389,11 +388,16 @@ void sqlite3_result_null(sqlite3_context *pCtx){
   assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
   sqlite3VdbeMemSetNull(pCtx->pOut);
 }
-void sqlite3_result_pointer(sqlite3_context *pCtx, void *pPtr, const char *zPT){
+void sqlite3_result_pointer(
+  sqlite3_context *pCtx,
+  void *pPtr,
+  const char *zPType,
+  void (*xDestructor)(void*)
+){
   Mem *pOut = pCtx->pOut;
   assert( sqlite3_mutex_held(pOut->db->mutex) );
   sqlite3VdbeMemSetNull(pOut);
-  sqlite3VdbeMemSetPointer(pOut, pPtr, zPT);
+  sqlite3VdbeMemSetPointer(pOut, pPtr, zPType, xDestructor);
 }
 void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){
   Mem *pOut = pCtx->pOut;
@@ -1398,12 +1402,18 @@ int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
   }
   return rc;
 }
-int sqlite3_bind_pointer(sqlite3_stmt *pStmt, int i, void *pPtr,const char *zT){
+int sqlite3_bind_pointer(
+  sqlite3_stmt *pStmt,
+  int i,
+  void *pPtr,
+  const char *zPTtype,
+  void (*xDestructor)(void*)
+){
   int rc;
   Vdbe *p = (Vdbe*)pStmt;
   rc = vdbeUnbind(p, i);
   if( rc==SQLITE_OK ){
-    sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr, zT);
+    sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr, zPTtype, xDestructor);
     sqlite3_mutex_leave(p->db->mutex);
   }
   return rc;
index 7c2bd87ef7f8a5335243c0ab5457ce633bf8a618..82d59c5e615556c3e0eed8701bd72dcb79d66ce8 100644 (file)
@@ -3224,7 +3224,7 @@ u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){
   assert( pMem->db->mallocFailed || flags&(MEM_Str|MEM_Blob) );
   assert( pMem->n>=0 );
   n = (u32)pMem->n;
-  if( flags & MEM_Zero ){
+  if( (flags & MEM_Zero)!=0 && (flags & MEM_Blob)!=0 ){
     n += pMem->u.nZero;
   }
   *pLen = n;
index eac3b9ed3eb81ea93fe5ca3e1b2c6f0d82d15f75..451e06f410bdbc41f657793b1ad92e722304760a 100644 (file)
@@ -220,9 +220,9 @@ int sqlite3VdbeMemMakeWriteable(Mem *pMem){
 int sqlite3VdbeMemExpandBlob(Mem *pMem){
   int nByte;
   assert( pMem->flags & MEM_Zero );
-  assert( pMem->flags&MEM_Blob );
   assert( (pMem->flags&MEM_RowSet)==0 );
   assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
+  if( (pMem->flags & MEM_Blob)==0 ) return SQLITE_OK;
 
   /* Set nByte to the number of bytes required to store the expanded blob. */
   nByte = pMem->n + pMem->u.nZero;
@@ -709,13 +709,21 @@ void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
 ** Set the value stored in *pMem should already be a NULL.
 ** Also store a pointer to go with it.
 */
-void sqlite3VdbeMemSetPointer(Mem *pMem, void *pPtr, const char *zPType){
+void sqlite3VdbeMemSetPointer(
+  Mem *pMem,
+  void *pPtr,
+  const char *zPType,
+  void (*xDestructor)(void*)
+){
   assert( pMem->flags==MEM_Null );
+  pMem->u.zPType = zPType;
+  pMem->z = pPtr;
   if( zPType ){
-    pMem->flags = MEM_Null|MEM_Subtype|MEM_Term|MEM_Static;
-    pMem->u.pPtr = pPtr;
-    pMem->eSubtype = 'p';
-    pMem->z = (char*)zPType;
+    pMem->flags = MEM_Null|MEM_Pointer;
+  }
+  if( xDestructor ){
+    pMem->xDel = xDestructor;
+    pMem->flags |= MEM_Dyn;
   }
 }