/ Check-in [3d9e841f]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Add a destructor argument to sqlite3_bind_pointer() and sqlite3_result_pointer().
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | pointer-with-destructor
Files: files | file ages | folders
SHA3-256: 3d9e841f6011480ebb8a6d860da72af7fa545983e08835ddef2cac96e5f5cd4b
User & Date: drh 2017-07-27 03:48:02
Context
2017-07-27
15:53
Improved implementation of the destructor on pointer-passing interfaces. check-in: 601ad679 user: drh tags: pointer-with-destructor
03:48
Add a destructor argument to sqlite3_bind_pointer() and sqlite3_result_pointer(). check-in: 3d9e841f user: drh tags: pointer-with-destructor
2017-07-25
15:12
Release candidate 2 for 3.20.0. check-in: f39cb76b user: drh tags: branch-3.20
Changes
Hide Diffs Side-by-Side Diffs Show Whitespace Changes Patch

Changes to ext/fts3/fts3.c.

  3349   3349   
  3350   3350     /* The column value supplied by SQLite must be in range. */
  3351   3351     assert( iCol>=0 && iCol<=p->nColumn+2 );
  3352   3352   
  3353   3353     switch( iCol-p->nColumn ){
  3354   3354       case 0:
  3355   3355         /* The special 'table-name' column */
  3356         -      sqlite3_result_pointer(pCtx, pCsr, "fts3cursor");
         3356  +      sqlite3_result_pointer(pCtx, pCsr, "fts3cursor", 0);
  3357   3357         break;
  3358   3358   
  3359   3359       case 1:
  3360   3360         /* The docid column */
  3361   3361         sqlite3_result_int64(pCtx, pCsr->iPrevId);
  3362   3362         break;
  3363   3363   

Changes to ext/fts5/fts5_tcl.c.

   100    100       fts5_api *pApi = 0;
   101    101   
   102    102       rc = sqlite3_prepare_v2(db, "SELECT fts5(?1)", -1, &pStmt, 0);
   103    103       if( rc!=SQLITE_OK ){
   104    104         Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
   105    105         return TCL_ERROR;
   106    106       }
   107         -    sqlite3_bind_pointer(pStmt, 1, (void*)&pApi, "fts5_api_ptr");
          107  +    sqlite3_bind_pointer(pStmt, 1, (void*)&pApi, "fts5_api_ptr", 0);
   108    108       sqlite3_step(pStmt);
   109    109   
   110    110       if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
   111    111         Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
   112    112         return TCL_ERROR;
   113    113       }
   114    114   

Changes to ext/fts5/fts5_test_mi.c.

    71     71   static int fts5_api_from_db(sqlite3 *db, fts5_api **ppApi){
    72     72     sqlite3_stmt *pStmt = 0;
    73     73     int rc;
    74     74   
    75     75     *ppApi = 0;
    76     76     rc = sqlite3_prepare(db, "SELECT fts5(?1)", -1, &pStmt, 0);
    77     77     if( rc==SQLITE_OK ){
    78         -    sqlite3_bind_pointer(pStmt, 1, (void*)ppApi, "fts5_api_ptr");
           78  +    sqlite3_bind_pointer(pStmt, 1, (void*)ppApi, "fts5_api_ptr", 0);
    79     79       (void)sqlite3_step(pStmt);
    80     80       rc = sqlite3_finalize(pStmt);
    81     81     }
    82     82   
    83     83     return rc;
    84     84   }
    85     85   

Changes to ext/misc/carray.c.

    20     20   ** at the address $ptr.  $ptr is a pointer to the array of integers.
    21     21   ** The pointer value must be assigned to $ptr using the
    22     22   ** sqlite3_bind_pointer() interface with a pointer type of "carray".
    23     23   ** For example:
    24     24   **
    25     25   **    static int aX[] = { 53, 9, 17, 2231, 4, 99 };
    26     26   **    int i = sqlite3_bind_parameter_index(pStmt, "$ptr");
    27         -**    sqlite3_bind_value(pStmt, i, aX, "carray");
           27  +**    sqlite3_bind_value(pStmt, i, aX, "carray", 0);
    28     28   **
    29     29   ** There is an optional third parameter to determine the datatype of
    30     30   ** the C-language array.  Allowed values of the third parameter are
    31     31   ** 'int32', 'int64', 'double', 'char*'.  Example:
    32     32   **
    33     33   **      SELECT * FROM carray($ptr,10,'char*');
    34     34   **
................................................................................
   373    373     i64 = sqlite3_value_int64(argv[0]);
   374    374     if( sizeof(i64)==sizeof(p) ){
   375    375       memcpy(&p, &i64, sizeof(p));
   376    376     }else{
   377    377       int i32 = i64 & 0xffffffff;
   378    378       memcpy(&p, &i32, sizeof(p));
   379    379     }
   380         -  sqlite3_result_pointer(context, p, "carray");
          380  +  sqlite3_result_pointer(context, p, "carray", 0);
   381    381   }
   382    382   #endif /* SQLITE_TEST */
   383    383   
   384    384   #endif /* SQLITE_OMIT_VIRTUALTABLE */
   385    385   
   386    386   #ifdef _WIN32
   387    387   __declspec(dllexport)

Changes to ext/rtree/rtree.c.

   335    335   struct RtreeGeomCallback {
   336    336     int (*xGeom)(sqlite3_rtree_geometry*, int, RtreeDValue*, int*);
   337    337     int (*xQueryFunc)(sqlite3_rtree_query_info*);
   338    338     void (*xDestructor)(void*);
   339    339     void *pContext;
   340    340   };
   341    341   
   342         -
   343         -/*
   344         -** Value for the first field of every RtreeMatchArg object. The MATCH
   345         -** operator tests that the first field of a blob operand matches this
   346         -** value to avoid operating on invalid blobs (which could cause a segfault).
   347         -*/
   348         -#define RTREE_GEOMETRY_MAGIC 0x891245AB
   349         -
   350    342   /*
   351    343   ** An instance of this structure (in the form of a BLOB) is returned by
   352    344   ** the SQL functions that sqlite3_rtree_geometry_callback() and
   353    345   ** sqlite3_rtree_query_callback() create, and is read as the right-hand
   354    346   ** operand to the MATCH operator of an R-Tree.
   355    347   */
   356    348   struct RtreeMatchArg {
   357         -  u32 magic;                  /* Always RTREE_GEOMETRY_MAGIC */
          349  +  u32 iSize;                  /* Size of this object */
   358    350     RtreeGeomCallback cb;       /* Info about the callback functions */
   359    351     int nParam;                 /* Number of parameters to the SQL function */
   360    352     sqlite3_value **apSqlParam; /* Original SQL parameter values */
   361    353     RtreeDValue aParam[1];      /* Values for parameters to the SQL function */
   362    354   };
   363    355   
   364    356   #ifndef MAX
................................................................................
  1645   1637   /*
  1646   1638   ** This function is called to configure the RtreeConstraint object passed
  1647   1639   ** as the second argument for a MATCH constraint. The value passed as the
  1648   1640   ** first argument to this function is the right-hand operand to the MATCH
  1649   1641   ** operator.
  1650   1642   */
  1651   1643   static int deserializeGeometry(sqlite3_value *pValue, RtreeConstraint *pCons){
  1652         -  RtreeMatchArg *pBlob;              /* BLOB returned by geometry function */
         1644  +  RtreeMatchArg *pBlob, *pSrc;       /* BLOB returned by geometry function */
  1653   1645     sqlite3_rtree_query_info *pInfo;   /* Callback information */
  1654         -  int nBlob;                         /* Size of the geometry function blob */
  1655         -  int nExpected;                     /* Expected size of the BLOB */
  1656   1646   
  1657         -  /* Check that value is actually a blob. */
  1658         -  if( sqlite3_value_type(pValue)!=SQLITE_BLOB ) return SQLITE_ERROR;
  1659         -
  1660         -  /* Check that the blob is roughly the right size. */
  1661         -  nBlob = sqlite3_value_bytes(pValue);
  1662         -  if( nBlob<(int)sizeof(RtreeMatchArg) ){
  1663         -    return SQLITE_ERROR;
  1664         -  }
  1665         -
  1666         -  pInfo = (sqlite3_rtree_query_info*)sqlite3_malloc( sizeof(*pInfo)+nBlob );
         1647  +  pSrc = sqlite3_value_pointer(pValue, "RtreeMatchArg");
         1648  +  if( pSrc==0 ) return SQLITE_ERROR;
         1649  +  pInfo = (sqlite3_rtree_query_info*)
         1650  +                sqlite3_malloc64( sizeof(*pInfo)+pSrc->iSize );
  1667   1651     if( !pInfo ) return SQLITE_NOMEM;
  1668   1652     memset(pInfo, 0, sizeof(*pInfo));
  1669   1653     pBlob = (RtreeMatchArg*)&pInfo[1];
  1670         -
  1671         -  memcpy(pBlob, sqlite3_value_blob(pValue), nBlob);
  1672         -  nExpected = (int)(sizeof(RtreeMatchArg) +
  1673         -                    pBlob->nParam*sizeof(sqlite3_value*) +
  1674         -                    (pBlob->nParam-1)*sizeof(RtreeDValue));
  1675         -  if( pBlob->magic!=RTREE_GEOMETRY_MAGIC || nBlob!=nExpected ){
  1676         -    sqlite3_free(pInfo);
  1677         -    return SQLITE_ERROR;
  1678         -  }
         1654  +  memcpy(pBlob, pSrc, pSrc->iSize);
  1679   1655     pInfo->pContext = pBlob->cb.pContext;
  1680   1656     pInfo->nParam = pBlob->nParam;
  1681   1657     pInfo->aParam = pBlob->aParam;
  1682   1658     pInfo->apSqlParam = pBlob->apSqlParam;
  1683   1659   
  1684   1660     if( pBlob->cb.xGeom ){
  1685   1661       pCons->u.xGeom = pBlob->cb.xGeom;
................................................................................
  3709   3685     nBlob = sizeof(RtreeMatchArg) + (nArg-1)*sizeof(RtreeDValue)
  3710   3686              + nArg*sizeof(sqlite3_value*);
  3711   3687     pBlob = (RtreeMatchArg *)sqlite3_malloc(nBlob);
  3712   3688     if( !pBlob ){
  3713   3689       sqlite3_result_error_nomem(ctx);
  3714   3690     }else{
  3715   3691       int i;
  3716         -    pBlob->magic = RTREE_GEOMETRY_MAGIC;
         3692  +    pBlob->iSize = nBlob;
  3717   3693       pBlob->cb = pGeomCtx[0];
  3718   3694       pBlob->apSqlParam = (sqlite3_value**)&pBlob->aParam[nArg];
  3719   3695       pBlob->nParam = nArg;
  3720   3696       for(i=0; i<nArg; i++){
  3721   3697         pBlob->apSqlParam[i] = sqlite3_value_dup(aArg[i]);
  3722   3698         if( pBlob->apSqlParam[i]==0 ) memErr = 1;
  3723   3699   #ifdef SQLITE_RTREE_INT_ONLY
................................................................................
  3726   3702         pBlob->aParam[i] = sqlite3_value_double(aArg[i]);
  3727   3703   #endif
  3728   3704       }
  3729   3705       if( memErr ){
  3730   3706         sqlite3_result_error_nomem(ctx);
  3731   3707         rtreeMatchArgFree(pBlob);
  3732   3708       }else{
  3733         -      sqlite3_result_blob(ctx, pBlob, nBlob, rtreeMatchArgFree);
         3709  +      sqlite3_result_pointer(ctx, pBlob, "RtreeMatchArg", rtreeMatchArgFree);
  3734   3710       }
  3735   3711     }
  3736   3712   }
  3737   3713   
  3738   3714   /*
  3739   3715   ** Register a new geometry function for use with the r-tree MATCH operator.
  3740   3716   */

Changes to src/sqlite.h.in.

  3879   3879   ** is filled with zeroes.  ^A zeroblob uses a fixed amount of memory
  3880   3880   ** (just an integer to hold its size) while it is being processed.
  3881   3881   ** Zeroblobs are intended to serve as placeholders for BLOBs whose
  3882   3882   ** content is later written using
  3883   3883   ** [sqlite3_blob_open | incremental BLOB I/O] routines.
  3884   3884   ** ^A negative value for the zeroblob results in a zero-length BLOB.
  3885   3885   **
  3886         -** ^The sqlite3_bind_pointer(S,I,P,T) routine causes the I-th parameter in
         3886  +** ^The sqlite3_bind_pointer(S,I,P,T,D) routine causes the I-th parameter in
  3887   3887   ** [prepared statement] S to have an SQL value of NULL, but to also be
  3888         -** associated with the pointer P of type T.
         3888  +** associated with the pointer P of type T.  ^D is either a NULL pointer or
         3889  +** a pointer to a destructor function that is called when P goes out of scope.
  3889   3890   ** ^The sqlite3_bind_pointer() routine can be used to pass
  3890   3891   ** host-language pointers into [application-defined SQL functions].
  3891   3892   ** ^A parameter that is initialized using [sqlite3_bind_pointer()] appears
  3892   3893   ** to be an ordinary SQL NULL value to everything other than
  3893   3894   ** [sqlite3_value_pointer()].  The T parameter should be a static string,
  3894   3895   ** preferably a string literal.  The procedure that invokes 
  3895         -** sqlite3_bind_pointer(S,I,P,T) continues to own the P and T pointers and
  3896         -** must guarantee that those pointers remain valid until after the last
         3896  +** sqlite3_bind_pointer(S,I,P,T,D) owns the T string and
         3897  +** must guarantee that it remains valid and unchanged until after the last
  3897   3898   ** access via [sqlite3_value_pointer()].  The sqlite3_bind_pointer() routine
  3898   3899   ** is part of the [pointer passing interface] added for SQLite 3.20.0.
  3899   3900   **
  3900   3901   ** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer
  3901   3902   ** for the [prepared statement] or with a prepared statement for which
  3902   3903   ** [sqlite3_step()] has been called more recently than [sqlite3_reset()],
  3903   3904   ** then the call will return [SQLITE_MISUSE].  If any sqlite3_bind_()
................................................................................
  3926   3927   int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
  3927   3928   int sqlite3_bind_null(sqlite3_stmt*, int);
  3928   3929   int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
  3929   3930   int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
  3930   3931   int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
  3931   3932                            void(*)(void*), unsigned char encoding);
  3932   3933   int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
  3933         -int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*);
         3934  +int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*,void(*)(void*));
  3934   3935   int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
  3935   3936   int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64);
  3936   3937   
  3937   3938   /*
  3938   3939   ** CAPI3REF: Number Of SQL Parameters
  3939   3940   ** METHOD: sqlite3_stmt
  3940   3941   **
................................................................................
  4759   4760   **
  4760   4761   ** ^The sqlite3_value_text16() interface extracts a UTF-16 string
  4761   4762   ** in the native byte-order of the host machine.  ^The
  4762   4763   ** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces
  4763   4764   ** extract UTF-16 strings as big-endian and little-endian respectively.
  4764   4765   **
  4765   4766   ** ^If [sqlite3_value] object V was initialized 
  4766         -** using [sqlite3_bind_pointer(S,I,P,X)] or [sqlite3_result_pointer(C,P,X)]
         4767  +** using [sqlite3_bind_pointer(S,I,P,X,D)] or [sqlite3_result_pointer(C,P,X,D)]
  4767   4768   ** and if X and Y are strings that compare equal according to strcmp(X,Y),
  4768   4769   ** then sqlite3_value_pointer(V,Y) will return the pointer P.  ^Otherwise,
  4769   4770   ** sqlite3_value_pointer(V,Y) returns a NULL.
  4770   4771   **
  4771   4772   ** ^(The sqlite3_value_type(V) interface returns the
  4772   4773   ** [SQLITE_INTEGER | datatype code] for the initial datatype of the
  4773   4774   ** [sqlite3_value] object V. The returned value is one of [SQLITE_INTEGER],
................................................................................
  5097   5098   ** sqlite3_result_value() interface makes a copy of the [sqlite3_value]
  5098   5099   ** so that the [sqlite3_value] specified in the parameter may change or
  5099   5100   ** be deallocated after sqlite3_result_value() returns without harm.
  5100   5101   ** ^A [protected sqlite3_value] object may always be used where an
  5101   5102   ** [unprotected sqlite3_value] object is required, so either
  5102   5103   ** kind of [sqlite3_value] object can be used with this interface.
  5103   5104   **
  5104         -** ^The sqlite3_result_pointer(C,P,T) interface sets the result to an
         5105  +** ^The sqlite3_result_pointer(C,P,T,D) interface sets the result to an
  5105   5106   ** SQL NULL value, just like [sqlite3_result_null(C)], except that it
  5106   5107   ** also associates the host-language pointer P or type T with that 
  5107   5108   ** NULL value such that the pointer can be retrieved within an
  5108   5109   ** [application-defined SQL function] using [sqlite3_value_pointer()].
         5110  +** ^If the D parameter is not NULL, then it is a pointer to a destructor
         5111  +** for the P parameter.  ^The destructor D is invoked on P when the result
         5112  +** value goes out of scope.
  5109   5113   ** The T parameter should be a static string and preferably a string
  5110         -** literal. The procedure that invokes sqlite3_result_pointer(C,P,T)
         5114  +** literal. The procedure that invokes sqlite3_result_pointer(C,P,T,D)
  5111   5115   ** continues to own the P and T pointers and must guarantee that 
  5112   5116   ** those pointers remain valid until after the last access via
  5113   5117   ** [sqlite3_value_pointer()].  The sqlite3_result_pointer() routine
  5114   5118   ** is part of the [pointer passing interface] added for SQLite 3.20.0.
  5115   5119   **
  5116   5120   ** If these routines are called from within the different thread
  5117   5121   ** than the one containing the application-defined function that received
................................................................................
  5132   5136   void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
  5133   5137   void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
  5134   5138                              void(*)(void*), unsigned char encoding);
  5135   5139   void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
  5136   5140   void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
  5137   5141   void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
  5138   5142   void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
  5139         -void sqlite3_result_pointer(sqlite3_context*, void*, const char*);
         5143  +void sqlite3_result_pointer(sqlite3_context*, void*,const char*,void(*)(void*));
  5140   5144   void sqlite3_result_zeroblob(sqlite3_context*, int n);
  5141   5145   int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n);
  5142   5146   
  5143   5147   
  5144   5148   /*
  5145   5149   ** CAPI3REF: Setting The Subtype Of An SQL Function
  5146   5150   ** METHOD: sqlite3_context

Changes to src/sqlite3ext.h.

   285    285     /* Version 3.18.0 and later */
   286    286     void (*set_last_insert_rowid)(sqlite3*,sqlite3_int64);
   287    287     /* Version 3.20.0 and later */
   288    288     int (*prepare_v3)(sqlite3*,const char*,int,unsigned int,
   289    289                       sqlite3_stmt**,const char**);
   290    290     int (*prepare16_v3)(sqlite3*,const void*,int,unsigned int,
   291    291                         sqlite3_stmt**,const void**);
   292         -  int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*);
   293         -  void (*result_pointer)(sqlite3_context*,void*,const char*);
          292  +  int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*,void(*)(void*));
          293  +  void (*result_pointer)(sqlite3_context*,void*,const char*,void(*)(void*));
   294    294     void *(*value_pointer)(sqlite3_value*,const char*);
   295    295   };
   296    296   
   297    297   /*
   298    298   ** This is the function signature used for all extension entry points.  It
   299    299   ** is also defined in the file "loadext.c".
   300    300   */

Changes to src/vdbe.c.

   412    412       }
   413    413       for(i=0; i<16 && i<pMem->n; i++){
   414    414         char z = pMem->z[i];
   415    415         if( z<32 || z>126 ) *zCsr++ = '.';
   416    416         else *zCsr++ = z;
   417    417       }
   418    418       *(zCsr++) = ']';
   419         -    if( f & MEM_Zero ){
          419  +    if( (f & (MEM_Zero|MEM_Blob))==(MEM_Zero|MEM_Blob) ){
   420    420         sqlite3_snprintf(100, zCsr,"+%dz",pMem->u.nZero);
   421    421         zCsr += sqlite3Strlen30(zCsr);
   422    422       }
   423    423       *zCsr = '\0';
   424    424     }else if( f & MEM_Str ){
   425    425       int j, k;
   426    426       zBuf[0] = ' ';
................................................................................
  2731   2731     /* Loop through the elements that will make up the record to figure
  2732   2732     ** out how much space is required for the new record.
  2733   2733     */
  2734   2734     pRec = pLast;
  2735   2735     do{
  2736   2736       assert( memIsValid(pRec) );
  2737   2737       pRec->uTemp = serial_type = sqlite3VdbeSerialType(pRec, file_format, &len);
  2738         -    if( pRec->flags & MEM_Zero ){
         2738  +    if( (pRec->flags & MEM_Zero)!=0 && (pRec->flags & MEM_Blob)!=0 ){
  2739   2739         if( nData ){
  2740   2740           if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem;
  2741   2741         }else{
  2742   2742           nZero += pRec->u.nZero;
  2743   2743           len -= pRec->u.nZero;
  2744   2744         }
  2745   2745       }
................................................................................
  4407   4407       x.nData = 0;
  4408   4408     }else{
  4409   4409       assert( pData->flags & (MEM_Blob|MEM_Str) );
  4410   4410       x.pData = pData->z;
  4411   4411       x.nData = pData->n;
  4412   4412     }
  4413   4413     seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0);
  4414         -  if( pData->flags & MEM_Zero ){
         4414  +  if( (pData->flags & MEM_Zero)!=0 && (pData->flags & MEM_Blob)!=0 ){
  4415   4415       x.nZero = pData->u.nZero;
  4416   4416     }else{
  4417   4417       x.nZero = 0;
  4418   4418     }
  4419   4419     x.pKey = 0;
  4420   4420     rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
  4421   4421         (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)), seekResult

Changes to src/vdbeInt.h.

   185    185   ** structures. Each Mem struct may cache multiple representations (string,
   186    186   ** integer etc.) of the same value.
   187    187   */
   188    188   struct sqlite3_value {
   189    189     union MemValue {
   190    190       double r;           /* Real value used when MEM_Real is set in flags */
   191    191       i64 i;              /* Integer value used when MEM_Int is set in flags */
   192         -    int nZero;          /* Used when bit MEM_Zero is set in flags */
   193         -    void *pPtr;         /* Pointer when flags=MEM_NULL and eSubtype='p' */
          192  +    int nZero;          /* Extra zero bytes when MEM_Zero and MEM_Blob set */
          193  +    const char *zPType; /* Pointer type when MEM_Pointer and MEM_Null set */
   194    194       FuncDef *pDef;      /* Used only when flags==MEM_Agg */
   195    195       RowSet *pRowSet;    /* Used only when flags==MEM_RowSet */
   196    196       VdbeFrame *pFrame;  /* Used when flags==MEM_Frame */
   197    197     } u;
   198    198     u16 flags;          /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
   199    199     u8  enc;            /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
   200    200     u8  eSubtype;       /* Subtype for this value */
................................................................................
   236    236   #define MEM_Real      0x0008   /* Value is a real number */
   237    237   #define MEM_Blob      0x0010   /* Value is a BLOB */
   238    238   #define MEM_AffMask   0x001f   /* Mask of affinity bits */
   239    239   #define MEM_RowSet    0x0020   /* Value is a RowSet object */
   240    240   #define MEM_Frame     0x0040   /* Value is a VdbeFrame object */
   241    241   #define MEM_Undefined 0x0080   /* Value is undefined */
   242    242   #define MEM_Cleared   0x0100   /* NULL set by OP_Null, not from data */
   243         -#define MEM_TypeMask  0x81ff   /* Mask of type bits */
          243  +#define MEM_TypeMask  0xc1ff   /* Mask of type bits */
   244    244   
   245    245   
   246    246   /* Whenever Mem contains a valid string or blob representation, one of
   247    247   ** the following flags must be set to determine the memory management
   248    248   ** policy for Mem.z.  The MEM_Term flag tells us whether or not the
   249    249   ** string is \000 or \u0000 terminated
          250  +**
          251  +** NB:  MEM_Zero and MEM_Pointer are the same value.  But MEM_Zero is
          252  +** only value if MEM_Blob is also set, and MEM_Pointer is only valid
          253  +** if MEM_Null is also set.
   250    254   */
   251    255   #define MEM_Term      0x0200   /* String rep is nul terminated */
   252    256   #define MEM_Dyn       0x0400   /* Need to call Mem.xDel() on Mem.z */
   253    257   #define MEM_Static    0x0800   /* Mem.z points to a static string */
   254    258   #define MEM_Ephem     0x1000   /* Mem.z points to an ephemeral string */
   255    259   #define MEM_Agg       0x2000   /* Mem.z points to an agg function context */
   256    260   #define MEM_Zero      0x4000   /* Mem.i contains count of 0s appended to blob */
          261  +#define MEM_Pointer   0x4000   /* Mem.z is an extension pointer */
   257    262   #define MEM_Subtype   0x8000   /* Mem.eSubtype is valid */
   258    263   #ifdef SQLITE_OMIT_INCRBLOB
   259    264     #undef MEM_Zero
   260    265     #define MEM_Zero 0x0000
   261    266   #endif
   262    267   
   263    268   /* Return TRUE if Mem X contains dynamically allocated content - anything
................................................................................
   472    477   int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
   473    478   void sqlite3VdbeMemSetInt64(Mem*, i64);
   474    479   #ifdef SQLITE_OMIT_FLOATING_POINT
   475    480   # define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64
   476    481   #else
   477    482     void sqlite3VdbeMemSetDouble(Mem*, double);
   478    483   #endif
   479         -void sqlite3VdbeMemSetPointer(Mem*, void*, const char*);
          484  +void sqlite3VdbeMemSetPointer(Mem*, void*, const char*, void(*)(void*));
   480    485   void sqlite3VdbeMemInit(Mem*,sqlite3*,u16);
   481    486   void sqlite3VdbeMemSetNull(Mem*);
   482    487   void sqlite3VdbeMemSetZeroBlob(Mem*,int);
   483    488   void sqlite3VdbeMemSetRowSet(Mem*);
   484    489   int sqlite3VdbeMemMakeWriteable(Mem*);
   485    490   int sqlite3VdbeMemStringify(Mem*, u8, u8);
   486    491   i64 sqlite3VdbeIntValue(Mem*);

Changes to src/vdbeapi.c.

   197    197   }
   198    198   unsigned int sqlite3_value_subtype(sqlite3_value *pVal){
   199    199     Mem *pMem = (Mem*)pVal;
   200    200     return ((pMem->flags & MEM_Subtype) ? pMem->eSubtype : 0);
   201    201   }
   202    202   void *sqlite3_value_pointer(sqlite3_value *pVal, const char *zPType){
   203    203     Mem *p = (Mem*)pVal;
   204         -  if( p->flags==(MEM_Null|MEM_Subtype|MEM_Term|MEM_Static)
          204  +  if( (p->flags&(MEM_AffMask|MEM_Pointer))==(MEM_Null|MEM_Pointer)
   205    205      && zPType!=0
   206         -   && p->eSubtype=='p'
   207         -   && strcmp(p->z, zPType)==0
          206  +   && strcmp(p->u.zPType, zPType)==0
   208    207     ){
   209         -    return p->u.pPtr;
          208  +    return (void*)p->z;
   210    209     }else{
   211    210       return 0;
   212    211     }
   213    212   }
   214    213   const unsigned char *sqlite3_value_text(sqlite3_value *pVal){
   215    214     return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8);
   216    215   }
................................................................................
   385    384     assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
   386    385     sqlite3VdbeMemSetInt64(pCtx->pOut, iVal);
   387    386   }
   388    387   void sqlite3_result_null(sqlite3_context *pCtx){
   389    388     assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
   390    389     sqlite3VdbeMemSetNull(pCtx->pOut);
   391    390   }
   392         -void sqlite3_result_pointer(sqlite3_context *pCtx, void *pPtr, const char *zPT){
          391  +void sqlite3_result_pointer(
          392  +  sqlite3_context *pCtx,
          393  +  void *pPtr,
          394  +  const char *zPType,
          395  +  void (*xDestructor)(void*)
          396  +){
   393    397     Mem *pOut = pCtx->pOut;
   394    398     assert( sqlite3_mutex_held(pOut->db->mutex) );
   395    399     sqlite3VdbeMemSetNull(pOut);
   396         -  sqlite3VdbeMemSetPointer(pOut, pPtr, zPT);
          400  +  sqlite3VdbeMemSetPointer(pOut, pPtr, zPType, xDestructor);
   397    401   }
   398    402   void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){
   399    403     Mem *pOut = pCtx->pOut;
   400    404     assert( sqlite3_mutex_held(pOut->db->mutex) );
   401    405     pOut->eSubtype = eSubtype & 0xff;
   402    406     pOut->flags |= MEM_Subtype;
   403    407   }
................................................................................
  1394   1398     Vdbe *p = (Vdbe*)pStmt;
  1395   1399     rc = vdbeUnbind(p, i);
  1396   1400     if( rc==SQLITE_OK ){
  1397   1401       sqlite3_mutex_leave(p->db->mutex);
  1398   1402     }
  1399   1403     return rc;
  1400   1404   }
  1401         -int sqlite3_bind_pointer(sqlite3_stmt *pStmt, int i, void *pPtr,const char *zT){
         1405  +int sqlite3_bind_pointer(
         1406  +  sqlite3_stmt *pStmt,
         1407  +  int i,
         1408  +  void *pPtr,
         1409  +  const char *zPTtype,
         1410  +  void (*xDestructor)(void*)
         1411  +){
  1402   1412     int rc;
  1403   1413     Vdbe *p = (Vdbe*)pStmt;
  1404   1414     rc = vdbeUnbind(p, i);
  1405   1415     if( rc==SQLITE_OK ){
  1406         -    sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr, zT);
         1416  +    sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr, zPTtype, xDestructor);
  1407   1417       sqlite3_mutex_leave(p->db->mutex);
  1408   1418     }
  1409   1419     return rc;
  1410   1420   }
  1411   1421   int sqlite3_bind_text( 
  1412   1422     sqlite3_stmt *pStmt, 
  1413   1423     int i, 

Changes to src/vdbeaux.c.

  3220   3220     if( flags&MEM_Real ){
  3221   3221       *pLen = 8;
  3222   3222       return 7;
  3223   3223     }
  3224   3224     assert( pMem->db->mallocFailed || flags&(MEM_Str|MEM_Blob) );
  3225   3225     assert( pMem->n>=0 );
  3226   3226     n = (u32)pMem->n;
  3227         -  if( flags & MEM_Zero ){
         3227  +  if( (flags & MEM_Zero)!=0 && (flags & MEM_Blob)!=0 ){
  3228   3228       n += pMem->u.nZero;
  3229   3229     }
  3230   3230     *pLen = n;
  3231   3231     return ((n*2) + 12 + ((flags&MEM_Str)!=0));
  3232   3232   }
  3233   3233   
  3234   3234   /*

Changes to src/vdbemem.c.

   216    216   ** If the given Mem* has a zero-filled tail, turn it into an ordinary
   217    217   ** blob stored in dynamically allocated space.
   218    218   */
   219    219   #ifndef SQLITE_OMIT_INCRBLOB
   220    220   int sqlite3VdbeMemExpandBlob(Mem *pMem){
   221    221     int nByte;
   222    222     assert( pMem->flags & MEM_Zero );
   223         -  assert( pMem->flags&MEM_Blob );
   224    223     assert( (pMem->flags&MEM_RowSet)==0 );
   225    224     assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
          225  +  if( (pMem->flags & MEM_Blob)==0 ) return SQLITE_OK;
   226    226   
   227    227     /* Set nByte to the number of bytes required to store the expanded blob. */
   228    228     nByte = pMem->n + pMem->u.nZero;
   229    229     if( nByte<=0 ){
   230    230       nByte = 1;
   231    231     }
   232    232     if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){
................................................................................
   705    705     }
   706    706   }
   707    707   
   708    708   /*
   709    709   ** Set the value stored in *pMem should already be a NULL.
   710    710   ** Also store a pointer to go with it.
   711    711   */
   712         -void sqlite3VdbeMemSetPointer(Mem *pMem, void *pPtr, const char *zPType){
          712  +void sqlite3VdbeMemSetPointer(
          713  +  Mem *pMem,
          714  +  void *pPtr,
          715  +  const char *zPType,
          716  +  void (*xDestructor)(void*)
          717  +){
   713    718     assert( pMem->flags==MEM_Null );
          719  +  pMem->u.zPType = zPType;
          720  +  pMem->z = pPtr;
   714    721     if( zPType ){
   715         -    pMem->flags = MEM_Null|MEM_Subtype|MEM_Term|MEM_Static;
   716         -    pMem->u.pPtr = pPtr;
   717         -    pMem->eSubtype = 'p';
   718         -    pMem->z = (char*)zPType;
          722  +    pMem->flags = MEM_Null|MEM_Pointer;
          723  +  }
          724  +  if( xDestructor ){
          725  +    pMem->xDel = xDestructor;
          726  +    pMem->flags |= MEM_Dyn;
   719    727     }
   720    728   }
   721    729   
   722    730   #ifndef SQLITE_OMIT_FLOATING_POINT
   723    731   /*
   724    732   ** Delete any previous value and set the value stored in *pMem to val,
   725    733   ** manifest type REAL.