mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
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: 72de49f204277191f62601cce70d5013ec30b564a01063f1e841019c78ae6c77
This commit is contained in:
@@ -3353,8 +3353,7 @@ static int fts3ColumnMethod(
|
||||
switch( iCol-p->nColumn ){
|
||||
case 0:
|
||||
/* The special 'table-name' column */
|
||||
sqlite3_result_blob(pCtx, &pCsr, sizeof(Fts3Cursor*), SQLITE_TRANSIENT);
|
||||
sqlite3_result_subtype(pCtx, SQLITE_BLOB);
|
||||
sqlite3_result_pointer(pCtx, pCsr);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
@@ -3572,9 +3571,10 @@ static int fts3FunctionArg(
|
||||
sqlite3_value *pVal, /* argv[0] passed to function */
|
||||
Fts3Cursor **ppCsr /* OUT: Store cursor handle here */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
if( sqlite3_value_subtype(pVal)==SQLITE_BLOB ){
|
||||
*ppCsr = *(Fts3Cursor**)sqlite3_value_blob(pVal);
|
||||
int rc;
|
||||
*ppCsr = (Fts3Cursor*)sqlite3_value_pointer(pVal);
|
||||
if( (*ppCsr)!=0 ){
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
|
||||
sqlite3_result_error(pContext, zErr, -1);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
31
manifest
31
manifest
@@ -1,5 +1,5 @@
|
||||
C Smaller\sand\sfaster\simplementation\sfor\svdbeFreeOpArray()\sand\sfreeP4().
|
||||
D 2017-07-12T20:43:23.436
|
||||
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-13T18:09:36.846
|
||||
F Makefile.in 081e48dfe7f995d57ce1a88ddf4d2917b4349158648a6cd45b42beae30de3a12
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 20850e3e8d4d4791e0531955852d768eb06f24138214870d543abb1a47346fba
|
||||
@@ -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 b47d3ba5c00f550d1f436e62017264fed818665819471b4699aac9527906459b
|
||||
F ext/fts3/fts3.c 02fbd2215309a7a73cbf29045897344987b6e17bb0b1685d13155f8b29768a50
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h eb2502000148e80913b965db3e59f29251266d0a
|
||||
F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1
|
||||
@@ -254,7 +254,7 @@ F ext/lsm1/lsm_win32.c 0a4acbd7e8d136dd3a5753f0a9e7a9802263a9d96cef3278cf120bcaa
|
||||
F ext/misc/README.md 8e008c8d2b02e09096b31dfba033253ac27c6c06a18aa5826e299fa7601d90b2
|
||||
F ext/misc/amatch.c 6db4607cb17c54b853a2d7c7c36046d004853f65b9b733e6f019d543d5dfae87
|
||||
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
|
||||
F ext/misc/carray.c 40c27641010a4dc67e3690bdb7c9d36ca58b3c2d
|
||||
F ext/misc/carray.c 1fbaf9ada5b1919c07a5e76e260a41c13a20fe6d399411e41f1e9cc4a559479f
|
||||
F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704
|
||||
F ext/misc/completion.c 52c3f01523e3e387eb321b4739a89d1fe47cbe6025aa1f2d8d3685e9e365df0f
|
||||
F ext/misc/compress.c 122faa92d25033d6c3f07c39231de074ab3d2e83
|
||||
@@ -269,7 +269,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 b0f5f346aca9b7ff7caaf0da2efb4ad462441abd4dcd92a460cb573b3ea2370b
|
||||
@@ -413,7 +413,7 @@ F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c bb70abf32c7c926745eb550938db9132309584a667a44c2db0e5fa3207600391
|
||||
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
|
||||
F src/loadext.c 15e458a122bccef49850cc1d6b69802040ea3f9022e564a125faf599354fe050
|
||||
F src/loadext.c 20865b183bb8a3723d59cf1efffc3c50217eb452c1021d077b908c94da26b0b2
|
||||
F src/main.c 20574bb9a0d7911efcd659ac252f2126dc4e3308bed3c8764ea3fb5a00f70420
|
||||
F src/malloc.c e20bb2b48abec52d3faf01cce12e8b4f95973755fafec98d45162dfdab111978
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
@@ -452,9 +452,9 @@ F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
|
||||
F src/select.c 95659b7990e390f9bd8dc30b8975c675fcd1d46e569bc4f5a14e22a8d03e3d14
|
||||
F src/shell.c 0401a716fc5343594b8ee60ce065d9a71373d3403f0b81f9fed684741e6401d1
|
||||
F src/shell.c.in 98bfdeeb0808418b37f59e6d380568a76e0733efe2494377096f434b39940cad
|
||||
F src/sqlite.h.in 03a422ba13da1dfef7f1aaa1ba344acf18dc867112620b1fdb2a1426cabba634
|
||||
F src/sqlite.h.in 77f4bee882ad4999bf04cf011e1c4cd7f1c6488e290764f3fb46833810447c5d
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 5539ec41f3d81890d626d5a845b08c82bd0e946ddc5c1c341144b700bc56101e
|
||||
F src/sqlite3ext.h 654d76dd288780a460be9c88edc6a5eb2d61df03a7153c92f1d87aba41f73b96
|
||||
F src/sqliteInt.h 0ba730cdc8afa723a5642380712f8bb33abd6a69218571c18b94acf3562de22a
|
||||
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
|
||||
F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
|
||||
@@ -519,11 +519,11 @@ F src/util.c fc081ec6f63448dcd80d3dfad35baecfa104823254a815b081a4d9fe76e1db23
|
||||
F src/vacuum.c 874c0f2f15ab2908748297d587d22d485ea96d55aaec91d4775dddb2e24d2ecf
|
||||
F src/vdbe.c adc8a378710ec2376101483cc8a5f499539ee9bbebfb2a784f3370704d5d44ad
|
||||
F src/vdbe.h 7bf719031782823b915aff2c1f93d1944c1c6b300770a15339b7dbc9610b802e
|
||||
F src/vdbeInt.h c8b3d97001a7bab5cdf71927fc813869d95263160e67ba2ef78a32d7538f159d
|
||||
F src/vdbeapi.c 899d8f021c89ab348708b3a9b00b855f5ecc3c0f949a75359a61a3c621021281
|
||||
F src/vdbeInt.h 36b162cce2410f07cc6ad1c4472af7d5e31bcc0b8a532082aa6f2740e124a11f
|
||||
F src/vdbeapi.c 8f830cf2e37929315a09b578a975d77070bad8185ade2006b14e72bf60227f3e
|
||||
F src/vdbeaux.c 518d1cf6728ecb591390541c58b14902e8d61735ef574426b9971624c54d2c4b
|
||||
F src/vdbeblob.c 359891617358deefc85bef7bcf787fa6b77facb9
|
||||
F src/vdbemem.c 8d78df62becfd2dce3c317f64b32a94ecaff8346d814bc8b0b877b38a1ad3718
|
||||
F src/vdbemem.c 78dfccca73eba44f4f6988f1f3d6ca93dd6431fcf9e6946945f4505fff1fb03f
|
||||
F src/vdbesort.c f512c68d0bf7e0105316a5594c4329358c8ee9cae3b25138df041d97516c0372
|
||||
F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834
|
||||
F src/vtab.c 35b9bdc2b41de32a417141d12097bcc4e29a77ed7cdb8f836d1d2305d946b61b
|
||||
@@ -1230,7 +1230,7 @@ F test/sync.test 2f84bdbc2b2df1fcb0220575b4b9f8cea94b7529
|
||||
F test/sync2.test 6be8ed007fa063b147773c1982b5bdba97a32badc536bdc6077eff5cf8710ece
|
||||
F test/syscall.test 7a60601770172a8014a4d222d5f3d95a5d2b5c47fbb0374e2698e89c99e37256
|
||||
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
|
||||
@@ -1631,7 +1631,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 604c11d1a39f09e47b6fcee0f8b1c1054f9dbbc7b2c1cf93312aeaa4b7095018
|
||||
R 549dc263ced9c697f9b1d9eb2b003b47
|
||||
P 0c80593520d30958231be41fc443209eb39e0b3ee0e66308c3ef3a0f4cb8ea66 0bd7875bd9948836a14061275eb8ddac627f562a49f59f400ec98c00e2be82c5
|
||||
R c5909f0683f2365e40f92a217eed2222
|
||||
T +closed 0bd7875bd9948836a14061275eb8ddac627f562a49f59f400ec98c00e2be82c5
|
||||
U drh
|
||||
Z 774a79b024a9ed7218e88c0cd802cdf5
|
||||
Z 735f8446b62685dce77314aad945e37d
|
||||
|
@@ -1 +1 @@
|
||||
0c80593520d30958231be41fc443209eb39e0b3ee0e66308c3ef3a0f4cb8ea66
|
||||
72de49f204277191f62601cce70d5013ec30b564a01063f1e841019c78ae6c77
|
@@ -427,7 +427,10 @@ static const sqlite3_api_routines sqlite3Apis = {
|
||||
sqlite3_set_last_insert_rowid,
|
||||
/* Version 3.20.0 and later */
|
||||
sqlite3_prepare_v3,
|
||||
sqlite3_prepare16_v3
|
||||
sqlite3_prepare16_v3,
|
||||
sqlite3_bind_pointer,
|
||||
sqlite3_result_pointer,
|
||||
sqlite3_value_pointer
|
||||
};
|
||||
|
||||
/*
|
||||
|
@@ -3881,6 +3881,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()],
|
||||
@@ -3914,6 +3923,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);
|
||||
|
||||
@@ -4744,6 +4754,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_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],
|
||||
@@ -4780,6 +4795,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_bytes(sqlite3_value*);
|
||||
int sqlite3_value_bytes16(sqlite3_value*);
|
||||
int sqlite3_value_type(sqlite3_value*);
|
||||
@@ -4794,10 +4810,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*);
|
||||
|
||||
@@ -5080,6 +5092,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.
|
||||
@@ -5103,6 +5123,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);
|
||||
|
||||
|
@@ -289,6 +289,9 @@ 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*);
|
||||
void (*result_pointer)(sqlite3_context*,void*);
|
||||
void *(*value_pointer)(sqlite3_value*);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -552,6 +555,9 @@ typedef int (*sqlite3_loadext_entry)(
|
||||
/* Version 3.20.0 and later */
|
||||
#define sqlite3_prepare_v3 sqlite3_api->prepare_v3
|
||||
#define sqlite3_prepare16_v3 sqlite3_api->prepare16_v3
|
||||
#define sqlite3_bind_pointer sqlite3_api->bind_pointer
|
||||
#define sqlite3_result_pointer sqlite3_api->result_pointer
|
||||
#define sqlite3_value_pointer sqlite3_api->value_pointer
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
|
@@ -190,6 +190,7 @@ struct sqlite3_value {
|
||||
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 */
|
||||
@@ -475,6 +476,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);
|
||||
|
@@ -199,6 +199,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);
|
||||
}
|
||||
@@ -377,6 +385,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) );
|
||||
@@ -1380,6 +1394,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,
|
||||
|
@@ -705,6 +705,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,
|
||||
|
@@ -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 |}
|
||||
|
||||
|
Reference in New Issue
Block a user