From: drh Date: Sat, 15 Jul 2017 10:44:13 +0000 (+0000) Subject: Add new interfaces sqlite3_bind_pointer(), sqlite3_result_pointer(), and X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=071ac77e93f81e06883cac6088cfff6fbeeb3584;p=thirdparty%2Fsqlite.git Add new interfaces sqlite3_bind_pointer(), sqlite3_result_pointer(), and sqlite3_value_pointer() used to safely move pointer values through SQL without exposing underlying memory address information. FossilOrigin-Name: d6a44b352d432d52e09cc0253dff8e6c1555262b54d9a384002ec555f0396991 --- diff --git a/ext/fts3/fts3.c b/ext/fts3/fts3.c index 7c931c42d4..ccdc9e3a94 100644 --- a/ext/fts3/fts3.c +++ b/ext/fts3/fts3.c @@ -3340,8 +3340,8 @@ static int fts3ColumnMethod( sqlite3_result_int64(pCtx, pCsr->iPrevId); }else if( iCol==p->nColumn ){ /* The extra column whose name is the same as the table. - ** Return a blob which is a pointer to the cursor. */ - sqlite3_result_blob(pCtx, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT); + ** Return a pointer to the cursor. */ + sqlite3_result_pointer(pCtx, pCsr); }else if( iCol==p->nColumn+2 && pCsr->pExpr ){ sqlite3_result_int64(pCtx, pCsr->iLangid); }else{ @@ -3553,16 +3553,13 @@ static int fts3FunctionArg( sqlite3_value *pVal, /* argv[0] passed to function */ Fts3Cursor **ppCsr /* OUT: Store cursor handle here */ ){ - Fts3Cursor *pRet; - if( sqlite3_value_type(pVal)!=SQLITE_BLOB - || sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *) - ){ + Fts3Cursor *pRet = (Fts3Cursor*)sqlite3_value_pointer(pVal); + if( pRet==0 ){ char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc); sqlite3_result_error(pContext, zErr, -1); sqlite3_free(zErr); return SQLITE_ERROR; } - memcpy(&pRet, sqlite3_value_blob(pVal), sizeof(Fts3Cursor *)); *ppCsr = pRet; return SQLITE_OK; } diff --git a/ext/misc/carray.c b/ext/misc/carray.c index 025eb5db2c..7c12067e5a 100644 --- a/ext/misc/carray.c +++ b/ext/misc/carray.c @@ -73,7 +73,7 @@ typedef struct carray_cursor carray_cursor; struct carray_cursor { sqlite3_vtab_cursor base; /* Base class - must be first */ sqlite3_int64 iRowid; /* The rowid */ - sqlite3_int64 iPtr; /* Pointer to array of values */ + void *pPtr; /* Pointer to the array of values */ sqlite3_int64 iCnt; /* Number of integers in the array */ unsigned char eType; /* One of the CARRAY_type values */ }; @@ -167,7 +167,7 @@ static int carrayColumn( carray_cursor *pCur = (carray_cursor*)cur; sqlite3_int64 x = 0; switch( i ){ - case CARRAY_COLUMN_POINTER: x = pCur->iPtr; break; + case CARRAY_COLUMN_POINTER: return SQLITE_OK; case CARRAY_COLUMN_COUNT: x = pCur->iCnt; break; case CARRAY_COLUMN_CTYPE: { sqlite3_result_text(ctx, azType[pCur->eType], -1, SQLITE_STATIC); @@ -176,22 +176,22 @@ static int carrayColumn( default: { switch( pCur->eType ){ case CARRAY_INT32: { - int *p = (int*)pCur->iPtr; + int *p = (int*)pCur->pPtr; sqlite3_result_int(ctx, p[pCur->iRowid-1]); return SQLITE_OK; } case CARRAY_INT64: { - sqlite3_int64 *p = (sqlite3_int64*)pCur->iPtr; + sqlite3_int64 *p = (sqlite3_int64*)pCur->pPtr; sqlite3_result_int64(ctx, p[pCur->iRowid-1]); return SQLITE_OK; } case CARRAY_DOUBLE: { - double *p = (double*)pCur->iPtr; + double *p = (double*)pCur->pPtr; sqlite3_result_double(ctx, p[pCur->iRowid-1]); return SQLITE_OK; } case CARRAY_TEXT: { - const char **p = (const char**)pCur->iPtr; + const char **p = (const char**)pCur->pPtr; sqlite3_result_text(ctx, p[pCur->iRowid-1], -1, SQLITE_TRANSIENT); return SQLITE_OK; } @@ -232,8 +232,8 @@ static int carrayFilter( ){ carray_cursor *pCur = (carray_cursor *)pVtabCursor; if( idxNum ){ - pCur->iPtr = sqlite3_value_int64(argv[0]); - pCur->iCnt = sqlite3_value_int64(argv[1]); + pCur->pPtr = sqlite3_value_pointer(argv[0]); + pCur->iCnt = pCur->pPtr ? sqlite3_value_int64(argv[1]) : 0; if( idxNum<3 ){ pCur->eType = CARRAY_INT32; }else{ @@ -251,7 +251,7 @@ static int carrayFilter( } } }else{ - pCur->iPtr = 0; + pCur->pPtr = 0; pCur->iCnt = 0; } pCur->iRowid = 1; @@ -345,6 +345,34 @@ static sqlite3_module carrayModule = { 0, /* xRename */ }; +/* +** For testing purpose in the TCL test harness, we need a method for +** setting the pointer value. The inttoptr(X) SQL function accomplishes +** this. Tcl script will bind an integer to X and the inttoptr() SQL +** function will use sqlite3_result_pointer() to convert that integer into +** a pointer. +** +** This is for testing on TCL only. +*/ +#ifdef SQLITE_TEST +static void inttoptrFunc( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + void *p; + sqlite3_int64 i64; + i64 = sqlite3_value_int64(argv[0]); + if( sizeof(i64)==sizeof(p) ){ + memcpy(&p, &i64, sizeof(p)); + }else{ + int i32 = i64 & 0xffffffff; + memcpy(&p, &i32, sizeof(p)); + } + sqlite3_result_pointer(context, p); +} +#endif /* SQLITE_TEST */ + #endif /* SQLITE_OMIT_VIRTUALTABLE */ #ifdef _WIN32 @@ -359,6 +387,12 @@ int sqlite3_carray_init( SQLITE_EXTENSION_INIT2(pApi); #ifndef SQLITE_OMIT_VIRTUALTABLE rc = sqlite3_create_module(db, "carray", &carrayModule, 0); -#endif +#ifdef SQLITE_TEST + if( rc==SQLITE_OK ){ + rc = sqlite3_create_function(db, "inttoptr", 1, SQLITE_UTF8, 0, + inttoptrFunc, 0, 0); + } +#endif /* SQLITE_TEST */ +#endif /* SQLITE_OMIT_VIRTUALTABLE */ return rc; } diff --git a/ext/misc/remember.c b/ext/misc/remember.c index aa3eff8a3f..587d44a12c 100644 --- a/ext/misc/remember.c +++ b/ext/misc/remember.c @@ -44,11 +44,11 @@ static void rememberFunc( sqlite3_value **argv ){ sqlite3_int64 v; - sqlite3_int64 ptr; + sqlite3_int64 *ptr; assert( argc==2 ); v = sqlite3_value_int64(argv[0]); - ptr = sqlite3_value_int64(argv[1]); - *((sqlite3_int64*)ptr) = v; + ptr = sqlite3_value_pointer(argv[1]); + if( ptr ) *ptr = v; sqlite3_result_int64(pCtx, v); } diff --git a/manifest b/manifest index cf5ca7ebd3..076548d650 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sthe\sCLANG_VERSION\smacro,\ssince\swe\shave\slearned\sthat\sversion\snumbers\sin\nclang\sare\s"marketing"\sand\sare\sinconsistent\sand\sunreliable.\s\sBuilds\susing\sclang\nwill\sstill\suse\sthe\sGCC_VERSION\smacro\ssince\sclang\sworks\shard\sto\sbe\sgcc\ncompatible. -D 2017-02-15T15:11:05.423 +C Add\snew\sinterfaces\ssqlite3_bind_pointer(),\ssqlite3_result_pointer(),\sand\nsqlite3_value_pointer()\sused\sto\ssafely\smove\spointer\svalues\sthrough\sSQL\swithout\nexposing\sunderlying\smemory\saddress\sinformation. +D 2017-07-15T10:44:13.064 F Makefile.in edb6bcdd37748d2b1c3422ff727c748df7ffe918 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 067a6766f800cc8d72845ab61f8de4ffe8f3fc99 @@ -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 c4d7eecb12de9749851bcab6e5ca616a5803047a +F ext/fts3/fts3.c 127b3f966cadebc198fc11a6706857c774c33baaf8c7dfa560cce6b3f1cdd17e F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe F ext/fts3/fts3Int.h eb2502000148e80913b965db3e59f29251266d0a F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1 @@ -205,7 +205,7 @@ F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43 F ext/icu/icu.c 84900472a088a3a172c6c079f58a1d3a1952c332 F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37 F ext/misc/amatch.c 211108e201105e4bb0c076527b8cfd34330fc234 -F ext/misc/carray.c 40c27641010a4dc67e3690bdb7c9d36ca58b3c2d +F ext/misc/carray.c 1fbaf9ada5b1919c07a5e76e260a41c13a20fe6d399411e41f1e9cc4a559479f F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704 F ext/misc/compress.c 122faa92d25033d6c3f07c39231de074ab3d2e83 F ext/misc/csv.c 531a46cbad789fca0aa9db69a0e6c8ac9e68767d @@ -218,7 +218,7 @@ F ext/misc/memvfs.c e5225bc22e79dde6b28380f3a068ddf600683a33 F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342 F ext/misc/percentile.c 92699c8cd7d517ff610e6037e56506f8904dae2e F ext/misc/regexp.c a68d25c659bd2d893cd1215667bbf75ecb9dc7d4 -F ext/misc/remember.c 8440f8d0b452c5cdefb62b57135ccd1267aa729d +F ext/misc/remember.c bee7963ddfa5b0633f4ac13f01cb471ae712f323a87978c9a9a47108b555598f F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a F ext/misc/scrub.c 1c5bfb8b0cd18b602fcb55755e84abf0023ac2fb F ext/misc/series.c e11e534ada797d5b816d7e7a93c022306563ca35 @@ -396,7 +396,7 @@ F src/resolve.c f9bc0de45a30a450da47b3766de00be89bf9be79 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac F src/select.c d12f3539f80db38b09015561b569e0eb1c4b6c5f F src/shell.c a84e453c213f3e0d6935a582024da4e242f85a19 -F src/sqlite.h.in 751ff125eb159c8f92c182b8df980a5e4f50e966 +F src/sqlite.h.in b58190e2bc024865aef7d589b0edb1fd61b37962d126d9fcb581f456837b0c14 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae F src/sqliteInt.h 2e3a663814058181048c3c7204ebc325affd8738 @@ -463,11 +463,11 @@ F src/util.c ca8440ede81e155d15cff7c101654f60b55a9ae6 F src/vacuum.c 33c174b28886b2faf26e503b5a49a1c01a9b1c16 F src/vdbe.c e7b1e860140f1d1803c6f4176b1e8f3801f3a290 F src/vdbe.h 59998ffd71d7caa8886bc78dafaf8caeccd4c13c -F src/vdbeInt.h 4e4b15b2e1330e1636e4e01974eab2b0b985092f -F src/vdbeapi.c 3e4a8893feeb78620f4aac4ac5b85d92255b97e1 +F src/vdbeInt.h 8912bdbc6f8fd745242b2a88dba016df3386e833737a36196cfa393c6de9b898 +F src/vdbeapi.c 0d8a4debe4d3799bfba9671a97d22cbbb50929bea2c41ee0901758bb904c846f F src/vdbeaux.c b9a36e530e6525ca9d9a685bc7b1d01fa77b5cf8 F src/vdbeblob.c 359891617358deefc85bef7bcf787fa6b77facb9 -F src/vdbemem.c 3b5a9a5b375458d3e12a50ae1aaa41eeec2175fd +F src/vdbemem.c dee85e4493748d39c663de16d1cae19543d438ec11e99ed21e701dad18e49939 F src/vdbesort.c eda25cb2d1727efca6f7862fea32b8aa33c0face F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834 F src/vtab.c c4bbe0f870f52036553f8098aee0703997f0577a @@ -1157,7 +1157,7 @@ F test/symlink.test c9ebe7330d228249e447038276bfc8a7b22f4849 F test/sync.test 2f84bdbc2b2df1fcb0220575b4b9f8cea94b7529 F test/syscall.test f59ba4e25f7ba4a4c031026cc2ef8b6e4b4c639c F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04 -F test/tabfunc01.test 699251cb99651415218a891384510a685c7ab012 +F test/tabfunc01.test c47171c36b3d411df2bd49719dcaa5d034f8d277477fd41d253940723b969a51 F test/table.test b708f3e5fa2542fa51dfab21fc07b36ea445cb2f F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126 F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930 @@ -1555,8 +1555,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P ada05cfa86ad7f5645450ac7a2a21c9aa6e57d2c -Q +810d29320b853b3a01aa50d8f2a0bceacf79e0aa -R 9daa2aaf287837264843b6d62b7e5aa5 +P 8d3f485d86b2f2d87a5c622acf95a5d15c4b371a +Q +72de49f204277191f62601cce70d5013ec30b564a01063f1e841019c78ae6c77 +R 29768151d9e2e0db30ff26f27855e70b U drh -Z 59bf4fbf4662683e6ba954acbe1164fa +Z 832872b5a064143213464bc95f29dfa3 diff --git a/manifest.uuid b/manifest.uuid index b7d07c0333..122b9f7375 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8d3f485d86b2f2d87a5c622acf95a5d15c4b371a \ No newline at end of file +d6a44b352d432d52e09cc0253dff8e6c1555262b54d9a384002ec555f0396991 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index eaa75fc249..2af1cde2ff 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -3786,6 +3786,15 @@ 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) 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. +** ^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()]. +** ** ^If any of the sqlite3_bind_*() routines are called with a NULL pointer ** for the [prepared statement] or with a prepared statement for which ** [sqlite3_step()] has been called more recently than [sqlite3_reset()], @@ -3819,6 +3828,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*); int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n); int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64); @@ -4588,6 +4598,11 @@ SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int), ** 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. +** ** ^(The sqlite3_value_numeric_type() interface attempts to apply ** numeric affinity to the value. This means that an attempt is ** made to convert the value to an integer or floating point. If @@ -4615,6 +4630,7 @@ 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*); +void *sqlite3_value_pointer(sqlite3_value*); int sqlite3_value_type(sqlite3_value*); int sqlite3_value_numeric_type(sqlite3_value*); @@ -4627,10 +4643,6 @@ int sqlite3_value_numeric_type(sqlite3_value*); ** information can be used to pass a limited amount of context from ** one SQL function to another. Use the [sqlite3_result_subtype()] ** routine to set the subtype for the return value of an SQL function. -** -** SQLite makes no use of subtype itself. It merely passes the subtype -** from the result of one [application-defined SQL function] into the -** input of another. */ unsigned int sqlite3_value_subtype(sqlite3_value*); @@ -4908,6 +4920,14 @@ 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) 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 +** [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 ** than the one containing the application-defined function that received ** the [sqlite3_context] pointer, the results are undefined. @@ -4931,6 +4951,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*); void sqlite3_result_zeroblob(sqlite3_context*, int n); int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 989cdfd346..69eab56bc5 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -189,6 +189,7 @@ struct Mem { 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' */ FuncDef *pDef; /* Used only when flags==MEM_Agg */ RowSet *pRowSet; /* Used only when flags==MEM_RowSet */ VdbeFrame *pFrame; /* Used when flags==MEM_Frame */ @@ -474,6 +475,7 @@ void sqlite3VdbeMemSetInt64(Mem*, i64); #else void sqlite3VdbeMemSetDouble(Mem*, double); #endif +void sqlite3VdbeMemSetPointer(Mem*, void*); void sqlite3VdbeMemInit(Mem*,sqlite3*,u16); void sqlite3VdbeMemSetNull(Mem*); void sqlite3VdbeMemSetZeroBlob(Mem*,int); diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 6eb97f1d1d..c54490c077 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -198,6 +198,14 @@ 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){ + Mem *p = (Mem*)pVal; + if( (p->flags & MEM_TypeMask)==(MEM_Null|MEM_Subtype) && p->eSubtype=='p' ){ + return p->u.pPtr; + }else{ + return 0; + } +} const unsigned char *sqlite3_value_text(sqlite3_value *pVal){ return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8); } @@ -376,6 +384,12 @@ 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){ + Mem *pOut = pCtx->pOut; + assert( sqlite3_mutex_held(pOut->db->mutex) ); + sqlite3VdbeMemSetNull(pOut); + sqlite3VdbeMemSetPointer(pOut, pPtr); +} void sqlite3_result_subtype(sqlite3_context *pCtx, unsigned int eSubtype){ Mem *pOut = pCtx->pOut; assert( sqlite3_mutex_held(pOut->db->mutex) ); @@ -1361,6 +1375,16 @@ int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){ } return rc; } +int sqlite3_bind_pointer(sqlite3_stmt *pStmt, int i, void *pPtr){ + int rc; + Vdbe *p = (Vdbe*)pStmt; + rc = vdbeUnbind(p, i); + if( rc==SQLITE_OK ){ + sqlite3VdbeMemSetPointer(&p->aVar[i-1], pPtr); + sqlite3_mutex_leave(p->db->mutex); + } + return rc; +} int sqlite3_bind_text( sqlite3_stmt *pStmt, int i, diff --git a/src/vdbemem.c b/src/vdbemem.c index 656e19bfa8..2f7aedb321 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -697,6 +697,17 @@ 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){ + assert( pMem->flags==MEM_Null ); + pMem->flags = MEM_Null|MEM_Subtype; + pMem->u.pPtr = pPtr; + pMem->eSubtype = 'p'; +} + #ifndef SQLITE_OMIT_FLOATING_POINT /* ** Delete any previous value and set the value stored in *pMem to val, diff --git a/test/tabfunc01.test b/test/tabfunc01.test index dcaafa420c..7e6a4b10be 100644 --- a/test/tabfunc01.test +++ b/test/tabfunc01.test @@ -150,62 +150,63 @@ do_execsql_test tabfunc01-600 { do_test tabfunc01-700 { set PTR1 [intarray_addr 5 7 13 17 23] db eval { - SELECT b FROM t600, carray($PTR1,5) WHERE a=value; + SELECT b FROM t600, carray(inttoptr($PTR1),5) WHERE a=value; } } {(005) (007) (013) (017) (023)} do_test tabfunc01-701 { db eval { - SELECT b FROM t600 WHERE a IN carray($PTR1,5,'int32'); + SELECT b FROM t600 WHERE a IN carray(inttoptr($PTR1),5,'int32'); } } {(005) (007) (013) (017) (023)} do_test tabfunc01-702 { db eval { - SELECT b FROM t600 WHERE a IN carray($PTR1,4,'int32'); + SELECT b FROM t600 WHERE a IN carray(inttoptr($PTR1),4,'int32'); } } {(005) (007) (013) (017)} do_catchsql_test tabfunc01-710 { - SELECT b FROM t600 WHERE a IN carray($PTR1,5,'int33'); + SELECT b FROM t600 WHERE a IN carray(inttoptr($PTR1),5,'int33'); } {1 {unknown datatype: 'int33'}} do_test tabfunc01-720 { set PTR2 [int64array_addr 5 7 13 17 23] db eval { - SELECT b FROM t600, carray($PTR2,5,'int64') WHERE a=value; + SELECT b FROM t600, carray(inttoptr($PTR2),5,'int64') WHERE a=value; } } {(005) (007) (013) (017) (023)} do_test tabfunc01-721 { db eval { - SELECT remember(123,$PTR2); - SELECT value FROM carray($PTR2,5,'int64'); + SELECT remember(123,inttoptr($PTR2)); + SELECT value FROM carray(inttoptr($PTR2),5,'int64'); } } {123 123 7 13 17 23} do_test tabfunc01-722 { set PTR3 [expr {$PTR2+16}] db eval { - SELECT remember(987,$PTR3); - SELECT value FROM carray($PTR2,5,'int64'); + SELECT remember(987,inttoptr($PTR3)); + SELECT value FROM carray(inttoptr($PTR2),5,'int64'); } } {987 123 7 987 17 23} do_test tabfunc01-730 { set PTR4 [doublearray_addr 5.0 7.0 13.0 17.0 23.0] db eval { - SELECT b FROM t600, carray($PTR4,5,'double') WHERE a=value; + SELECT b FROM t600, carray(inttoptr($PTR4),5,'double') WHERE a=value; } } {(005) (007) (013) (017) (023)} do_test tabfunc01-740 { set PTR5 [textarray_addr x5 x7 x13 x17 x23] db eval { - SELECT b FROM t600, carray($PTR5,5,'char*') WHERE a=trim(value,'x'); + SELECT b FROM t600, carray(inttoptr($PTR5),5,'char*') + WHERE a=trim(value,'x'); } } {(005) (007) (013) (017) (023)} do_test tabfunc01-750 { db eval { SELECT aa.value, bb.value, '|' - FROM carray($PTR4,5,'double') AS aa - JOIN carray($PTR5,5,'char*') AS bb ON aa.rowid=bb.rowid; + FROM carray(inttoptr($PTR4),5,'double') AS aa + JOIN carray(inttoptr($PTR5),5,'char*') AS bb ON aa.rowid=bb.rowid; } } {5.0 x5 | 7.0 x7 | 13.0 x13 | 17.0 x17 | 23.0 x23 |}