Index: ext/fts3/fts3.c ================================================================== --- ext/fts3/fts3.c +++ ext/fts3/fts3.c @@ -3351,11 +3351,11 @@ assert( iCol>=0 && iCol<=p->nColumn+2 ); switch( iCol-p->nColumn ){ case 0: /* The special 'table-name' column */ - sqlite3_result_pointer(pCtx, pCsr); + sqlite3_result_pointer(pCtx, pCsr, "fts3cursor"); break; case 1: /* The docid column */ sqlite3_result_int64(pCtx, pCsr->iPrevId); @@ -3570,11 +3570,11 @@ const char *zFunc, /* Function name */ sqlite3_value *pVal, /* argv[0] passed to function */ Fts3Cursor **ppCsr /* OUT: Store cursor handle here */ ){ int rc; - *ppCsr = (Fts3Cursor*)sqlite3_value_pointer(pVal); + *ppCsr = (Fts3Cursor*)sqlite3_value_pointer(pVal, "fts3cursor"); if( (*ppCsr)!=0 ){ rc = SQLITE_OK; }else{ char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc); sqlite3_result_error(pContext, zErr, -1); Index: ext/misc/carray.c ================================================================== --- ext/misc/carray.c +++ ext/misc/carray.c @@ -17,17 +17,24 @@ ** SELECT * FROM carray($ptr,5) ** ** The query above returns 5 integers contained in a C-language array ** at the address $ptr. $ptr is a pointer to the array of integers. ** The pointer value must be assigned to $ptr using the -** sqlite3_bind_pointer() interface. +** sqlite3_bind_pointer() interface with a pointer type of "carray". +** For example: +** +** static int aX[] = { 53, 9, 17, 2231, 4, 99 }; +** int i = sqlite3_bind_parameter_index(pStmt, "$ptr"); +** sqlite3_bind_value(pStmt, i, aX, "carray"); ** ** There is an optional third parameter to determine the datatype of ** the C-language array. Allowed values of the third parameter are ** 'int32', 'int64', 'double', 'char*'. Example: ** ** SELECT * FROM carray($ptr,10,'char*'); +** +** The default value of the third parameter is 'int32'. ** ** HOW IT WORKS ** ** The carray "function" is really a virtual table with the ** following schema: @@ -231,11 +238,11 @@ int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ carray_cursor *pCur = (carray_cursor *)pVtabCursor; if( idxNum ){ - pCur->pPtr = sqlite3_value_pointer(argv[0]); + pCur->pPtr = sqlite3_value_pointer(argv[0], "carray"); pCur->iCnt = pCur->pPtr ? sqlite3_value_int64(argv[1]) : 0; if( idxNum<3 ){ pCur->eType = CARRAY_INT32; }else{ unsigned char i; @@ -368,11 +375,11 @@ memcpy(&p, &i64, sizeof(p)); }else{ int i32 = i64 & 0xffffffff; memcpy(&p, &i32, sizeof(p)); } - sqlite3_result_pointer(context, p); + sqlite3_result_pointer(context, p, "carray"); } #endif /* SQLITE_TEST */ #endif /* SQLITE_OMIT_VIRTUALTABLE */ Index: ext/misc/remember.c ================================================================== --- ext/misc/remember.c +++ ext/misc/remember.c @@ -19,12 +19,13 @@ ** value retrieved, atomically, using a single statement: ** ** UPDATE counterTab SET cnt=remember(cnt,$PTR)+1 WHERE id=$ID ** ** Prepare the above statement once. Then to use it, bind the address -** of the output variable to $PTR (using sqlite3_bind_pointer()) and -** bind the id of the counter to $ID and run the prepared statement. +** of the output variable to $PTR using sqlite3_bind_pointer() with a +** pointer type of "carray" and bind the id of the counter to $ID and +** run the prepared statement. ** ** One can imagine doing similar things with floating-point values and ** strings, but this demonstration extension will stick to using just ** integers. */ @@ -45,11 +46,11 @@ ){ sqlite3_int64 v; sqlite3_int64 *ptr; assert( argc==2 ); v = sqlite3_value_int64(argv[0]); - ptr = sqlite3_value_pointer(argv[1]); + ptr = sqlite3_value_pointer(argv[1], "carray"); if( ptr ) *ptr = v; sqlite3_result_int64(pCtx, v); } #ifdef _WIN32 Index: src/sqlite.h.in ================================================================== --- src/sqlite.h.in +++ src/sqlite.h.in @@ -3881,13 +3881,13 @@ ** Zeroblobs are intended to serve as placeholders for BLOBs whose ** content is later written using ** [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) routine causes the I-th parameter in +** ^The sqlite3_bind_pointer(S,I,P,T) 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. +** associated with the pointer P of type T. ** ^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()]. @@ -3923,11 +3923,11 @@ 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_value(sqlite3_stmt*, int, const sqlite3_value*); -int sqlite3_bind_pointer(sqlite3_stmt*, int, void*); +int sqlite3_bind_pointer(sqlite3_stmt*, int, void*, const char*); int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64); /* ** CAPI3REF: Number Of SQL Parameters @@ -4756,13 +4756,14 @@ ** in the native byte-order of the host machine. ^The ** sqlite3_value_text16be() and sqlite3_value_text16le() interfaces ** 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)] or [sqlite3_result_pointer(C,P)], then -** sqlite3_value_pointer(V) will return the pointer P. Otherwise, -** sqlite3_value_pointer(V) returns a NULL. +** using [sqlite3_bind_pointer(S,I,P,X)] or [sqlite3_result_pointer(C,P,X)] +** 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. ** ** ^(The sqlite3_value_type(V) interface returns the ** [SQLITE_INTEGER | datatype code] for the initial datatype of the ** [sqlite3_value] object V. The returned value is one of [SQLITE_INTEGER], ** [SQLITE_FLOAT], [SQLITE_TEXT], [SQLITE_BLOB], or [SQLITE_NULL].)^ @@ -4792,11 +4793,11 @@ */ const void *sqlite3_value_blob(sqlite3_value*); double sqlite3_value_double(sqlite3_value*); int sqlite3_value_int(sqlite3_value*); sqlite3_int64 sqlite3_value_int64(sqlite3_value*); -void *sqlite3_value_pointer(sqlite3_value*); +void *sqlite3_value_pointer(sqlite3_value*, const char*); const unsigned char *sqlite3_value_text(sqlite3_value*); const void *sqlite3_value_text16(sqlite3_value*); const void *sqlite3_value_text16le(sqlite3_value*); const void *sqlite3_value_text16be(sqlite3_value*); int sqlite3_value_bytes(sqlite3_value*); @@ -5093,14 +5094,14 @@ ** be deallocated after sqlite3_result_value() returns without harm. ** ^A [protected sqlite3_value] object may always be used where an ** [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) interface sets the result to an +** ^The sqlite3_result_pointer(C,P,T) 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 with that NULL value such -** that the pointer can be retrieved within an +** 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()]. ** This mechanism can be used to pass non-SQL values between ** application-defined functions. ** ** If these routines are called from within the different thread @@ -5124,11 +5125,11 @@ 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*)); void sqlite3_result_value(sqlite3_context*, sqlite3_value*); -void sqlite3_result_pointer(sqlite3_context*, void*); +void sqlite3_result_pointer(sqlite3_context*, void*, const char*); void sqlite3_result_zeroblob(sqlite3_context*, int n); int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); /* Index: src/sqlite3ext.h ================================================================== --- src/sqlite3ext.h +++ src/sqlite3ext.h @@ -287,13 +287,13 @@ /* Version 3.20.0 and later */ int (*prepare_v3)(sqlite3*,const char*,int,unsigned int, sqlite3_stmt**,const char**); int (*prepare16_v3)(sqlite3*,const void*,int,unsigned int, sqlite3_stmt**,const void**); - int (*bind_pointer)(sqlite3_stmt*,int,void*); - void (*result_pointer)(sqlite3_context*,void*); - void *(*value_pointer)(sqlite3_value*); + int (*bind_pointer)(sqlite3_stmt*,int,void*,const char*); + void (*result_pointer)(sqlite3_context*,void*,const char*); + void *(*value_pointer)(sqlite3_value*,const char*); }; /* ** This is the function signature used for all extension entry points. It ** is also defined in the file "loadext.c". Index: src/vdbeInt.h ================================================================== --- src/vdbeInt.h +++ src/vdbeInt.h @@ -474,11 +474,11 @@ #ifdef SQLITE_OMIT_FLOATING_POINT # define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64 #else void sqlite3VdbeMemSetDouble(Mem*, double); #endif -void sqlite3VdbeMemSetPointer(Mem*, void*); +void sqlite3VdbeMemSetPointer(Mem*, void*, const char*); void sqlite3VdbeMemInit(Mem*,sqlite3*,u16); void sqlite3VdbeMemSetNull(Mem*); void sqlite3VdbeMemSetZeroBlob(Mem*,int); void sqlite3VdbeMemSetRowSet(Mem*); int sqlite3VdbeMemMakeWriteable(Mem*); Index: src/vdbeapi.c ================================================================== --- src/vdbeapi.c +++ src/vdbeapi.c @@ -197,13 +197,17 @@ } unsigned int sqlite3_value_subtype(sqlite3_value *pVal){ Mem *pMem = (Mem*)pVal; return ((pMem->flags & MEM_Subtype) ? pMem->eSubtype : 0); } -void *sqlite3_value_pointer(sqlite3_value *pVal){ +void *sqlite3_value_pointer(sqlite3_value *pVal, const char *zPType){ Mem *p = (Mem*)pVal; - if( (p->flags & MEM_TypeMask)==(MEM_Null|MEM_Subtype) && p->eSubtype=='p' ){ + if( p->flags==(MEM_Null|MEM_Subtype|MEM_Term|MEM_Static) + && p->eSubtype=='p' + && zPType!=0 + && strcmp(p->z, zPType)==0 + ){ return p->u.pPtr; }else{ return 0; } } @@ -383,15 +387,15 @@ } 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){ +void sqlite3_result_pointer(sqlite3_context *pCtx, void *pPtr, const char *zPT){ Mem *pOut = pCtx->pOut; assert( sqlite3_mutex_held(pOut->db->mutex) ); sqlite3VdbeMemSetNull(pOut); - sqlite3VdbeMemSetPointer(pOut, pPtr); + sqlite3VdbeMemSetPointer(pOut, pPtr, zPT); } void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){ Mem *pOut = pCtx->pOut; assert( sqlite3_mutex_held(pOut->db->mutex) ); pOut->eSubtype = eSubtype & 0xff; @@ -1392,16 +1396,16 @@ if( rc==SQLITE_OK ){ sqlite3_mutex_leave(p->db->mutex); } return rc; } -int sqlite3_bind_pointer(sqlite3_stmt *pStmt, int i, void *pPtr){ +int sqlite3_bind_pointer(sqlite3_stmt *pStmt, int i, void *pPtr,const char *zT){ int rc; Vdbe *p = (Vdbe*)pStmt; rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ - sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr); + sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr, zT); sqlite3_mutex_leave(p->db->mutex); } return rc; } int sqlite3_bind_text( Index: src/vdbemem.c ================================================================== --- src/vdbemem.c +++ src/vdbemem.c @@ -707,15 +707,18 @@ /* ** 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){ +void sqlite3VdbeMemSetPointer(Mem *pMem, void *pPtr, const char *zPType){ assert( pMem->flags==MEM_Null ); - pMem->flags = MEM_Null|MEM_Subtype; - pMem->u.pPtr = pPtr; - pMem->eSubtype = 'p'; + if( zPType ){ + pMem->flags = MEM_Null|MEM_Subtype|MEM_Term|MEM_Static; + pMem->u.pPtr = pPtr; + pMem->eSubtype = 'p'; + pMem->z = (char*)zPType; + } } #ifndef SQLITE_OMIT_FLOATING_POINT /* ** Delete any previous value and set the value stored in *pMem to val,