Index: ext/fts3/fts3.c ================================================================== --- ext/fts3/fts3.c +++ ext/fts3/fts3.c @@ -3338,12 +3338,12 @@ ** alias for "rowid", use the xRowid() method to obtain the value. */ 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{ /* The requested column is either a user column (one that contains ** indexed data), or the language-id column. */ @@ -3551,20 +3551,17 @@ sqlite3_context *pContext, /* SQL function call context */ const char *zFunc, /* Function name */ 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; } /* Index: ext/misc/carray.c ================================================================== --- ext/misc/carray.c +++ ext/misc/carray.c @@ -71,11 +71,11 @@ */ 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 */ }; /* @@ -165,35 +165,35 @@ int i /* Which column to return */ ){ 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); return SQLITE_OK; } 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; } } } @@ -230,12 +230,12 @@ int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ 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{ unsigned char i; const char *zType = (const char*)sqlite3_value_text(argv[2]); @@ -249,11 +249,11 @@ }else{ pCur->eType = i; } } }else{ - pCur->iPtr = 0; + pCur->pPtr = 0; pCur->iCnt = 0; } pCur->iRowid = 1; return SQLITE_OK; } @@ -343,10 +343,38 @@ 0, /* xRollback */ 0, /* xFindMethod */ 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 __declspec(dllexport) #endif @@ -357,8 +385,14 @@ ){ int rc = SQLITE_OK; 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; } Index: ext/misc/remember.c ================================================================== --- ext/misc/remember.c +++ ext/misc/remember.c @@ -42,15 +42,15 @@ sqlite3_context *pCtx, int argc, 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); } #ifdef _WIN32 __declspec(dllexport) Index: ext/rtree/rtree.c ================================================================== --- ext/rtree/rtree.c +++ ext/rtree/rtree.c @@ -366,27 +366,21 @@ #endif #ifndef MIN # define MIN(x,y) ((x) > (y) ? (y) : (x)) #endif -/* What version of GCC is being used. 0 means GCC is not being used */ +/* What version of GCC is being used. 0 means GCC is not being used . +** Note that the GCC_VERSION macro will also be set correctly when using +** clang, since clang works hard to be gcc compatible. So the gcc +** optimizations will also work when compiling with clang. +*/ #ifndef GCC_VERSION #if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC) # define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__) #else # define GCC_VERSION 0 #endif -#endif - -/* What version of CLANG is being used. 0 means CLANG is not being used */ -#ifndef CLANG_VERSION -#if defined(__clang__) && !defined(_WIN32) && !defined(SQLITE_DISABLE_INTRINSIC) -# define CLANG_VERSION \ - (__clang_major__*1000000+__clang_minor__*1000+__clang_patchlevel__) -#else -# define CLANG_VERSION 0 -#endif #endif /* The testcase() macro should already be defined in the amalgamation. If ** it is not, make it a no-op. */ @@ -435,11 +429,11 @@ } static void readCoord(u8 *p, RtreeCoord *pCoord){ assert( ((((char*)p) - (char*)0)&3)==0 ); /* p is always 4-byte aligned */ #if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 pCoord->u = _byteswap_ulong(*(u32*)p); -#elif SQLITE_BYTEORDER==1234 && (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000) +#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 pCoord->u = __builtin_bswap32(*(u32*)p); #elif SQLITE_BYTEORDER==4321 pCoord->u = *(u32*)p; #else pCoord->u = ( @@ -453,11 +447,11 @@ static i64 readInt64(u8 *p){ #if SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 u64 x; memcpy(&x, p, 8); return (i64)_byteswap_uint64(x); -#elif SQLITE_BYTEORDER==1234 && (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000) +#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 u64 x; memcpy(&x, p, 8); return (i64)__builtin_bswap64(x); #elif SQLITE_BYTEORDER==4321 i64 x; @@ -489,11 +483,11 @@ static int writeCoord(u8 *p, RtreeCoord *pCoord){ u32 i; assert( ((((char*)p) - (char*)0)&3)==0 ); /* p is always 4-byte aligned */ assert( sizeof(RtreeCoord)==4 ); assert( sizeof(u32)==4 ); -#if SQLITE_BYTEORDER==1234 && (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000) +#if SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 i = __builtin_bswap32(pCoord->u); memcpy(p, &i, 4); #elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 i = _byteswap_ulong(pCoord->u); memcpy(p, &i, 4); @@ -508,11 +502,11 @@ p[3] = (i>> 0)&0xFF; #endif return 4; } static int writeInt64(u8 *p, i64 i){ -#if SQLITE_BYTEORDER==1234 && (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000) +#if SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 i = (i64)__builtin_bswap64((u64)i); memcpy(p, &i, 8); #elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 i = (i64)_byteswap_uint64((u64)i); memcpy(p, &i, 8); @@ -1064,11 +1058,11 @@ #define RTREE_DECODE_COORD(eInt, a, r) { \ RtreeCoord c; /* Coordinate decoded */ \ c.u = _byteswap_ulong(*(u32*)a); \ r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \ } -#elif SQLITE_BYTEORDER==1234 && (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000) +#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 #define RTREE_DECODE_COORD(eInt, a, r) { \ RtreeCoord c; /* Coordinate decoded */ \ c.u = __builtin_bswap32(*(u32*)a); \ r = eInt ? (sqlite3_rtree_dbl)c.i : (sqlite3_rtree_dbl)c.f; \ } Index: src/btreeInt.h ================================================================== --- src/btreeInt.h +++ src/btreeInt.h @@ -692,10 +692,10 @@ */ #if SQLITE_BYTEORDER==4321 # define get2byteAligned(x) (*(u16*)(x)) #elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4008000 # define get2byteAligned(x) __builtin_bswap16(*(u16*)(x)) -#elif SQLITE_BYTEORDER==1234 && MSCV_VERSION>=1300 +#elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 # define get2byteAligned(x) _byteswap_ushort(*(u16*)(x)) #else # define get2byteAligned(x) ((x)[0]<<8 | (x)[1]) #endif Index: src/expr.c ================================================================== --- src/expr.c +++ src/expr.c @@ -229,11 +229,11 @@ aff = sqlite3ExprAffinity(pExpr->pLeft); if( pExpr->pRight ){ aff = sqlite3CompareAffinity(pExpr->pRight, aff); }else if( ExprHasProperty(pExpr, EP_xIsSelect) ){ aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff); - }else if( NEVER(aff==0) ){ + }else if( aff==0 ){ aff = SQLITE_AFF_BLOB; } return aff; } Index: src/mutex_w32.c ================================================================== --- src/mutex_w32.c +++ src/mutex_w32.c @@ -85,11 +85,11 @@ void sqlite3MemoryBarrier(void){ #if defined(SQLITE_MEMORY_BARRIER) SQLITE_MEMORY_BARRIER; #elif defined(__GNUC__) __sync_synchronize(); -#elif MSCV_VERSION>=1300 +#elif MSVC_VERSION>=1300 _ReadWriteBarrier(); #elif defined(MemoryBarrier) MemoryBarrier(); #endif } Index: src/sqlite.h.in ================================================================== --- src/sqlite.h.in +++ src/sqlite.h.in @@ -3783,10 +3783,19 @@ ** (just an integer to hold its size) while it is being processed. ** 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 +** [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()], ** then the call will return [SQLITE_MISUSE]. If any sqlite3_bind_() @@ -3817,10 +3826,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_zeroblob(sqlite3_stmt*, int, int n); int sqlite3_bind_zeroblob64(sqlite3_stmt*, int, sqlite3_uint64); /* ** CAPI3REF: Number Of SQL Parameters @@ -4585,10 +4595,15 @@ ** ** ^The sqlite3_value_text16() interface extracts a UTF-16 string ** 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. ** ** ^(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 ** such a conversion is possible without loss of information (in other @@ -4613,10 +4628,11 @@ sqlite3_int64 sqlite3_value_int64(sqlite3_value*); 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*); /* ** CAPI3REF: Finding The Subtype Of SQL Values @@ -4625,14 +4641,10 @@ ** The sqlite3_value_subtype(V) function returns the subtype for ** an [application-defined SQL function] argument V. The subtype ** 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*); /* ** CAPI3REF: Copy And Free SQL Values @@ -4905,10 +4917,18 @@ ** so that the [sqlite3_value] specified in the parameter may change or ** 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 +** 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. */ @@ -4929,10 +4949,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_zeroblob(sqlite3_context*, int n); int sqlite3_result_zeroblob64(sqlite3_context*, sqlite3_uint64 n); /* Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -101,27 +101,28 @@ # define _FILE_OFFSET_BITS 64 # endif # define _LARGEFILE_SOURCE 1 #endif -/* The GCC_VERSION, CLANG_VERSION, and MSVC_VERSION macros are used to +/* The GCC_VERSION and MSVC_VERSION macros are used to ** conditionally include optimizations for each of these compilers. A ** value of 0 means that compiler is not being used. The ** SQLITE_DISABLE_INTRINSIC macro means do not use any compiler-specific ** optimizations, and hence set all compiler macros to 0 +** +** There was once also a CLANG_VERSION macro. However, we learn that the +** version numbers in clang are for "marketing" only and are inconsistent +** and unreliable. Fortunately, all versions of clang also recognize the +** gcc version numbers and have reasonable settings for gcc version numbers, +** so the GCC_VERSION macro will be set to a correct non-zero value even +** when compiling with clang. */ #if defined(__GNUC__) && !defined(SQLITE_DISABLE_INTRINSIC) # define GCC_VERSION (__GNUC__*1000000+__GNUC_MINOR__*1000+__GNUC_PATCHLEVEL__) #else # define GCC_VERSION 0 #endif -#if defined(__clang__) && !defined(_WIN32) && !defined(SQLITE_DISABLE_INTRINSIC) -# define CLANG_VERSION \ - (__clang_major__*1000000+__clang_minor__*1000+__clang_patchlevel__) -#else -# define CLANG_VERSION 0 -#endif #if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC) # define MSVC_VERSION _MSC_VER #else # define MSVC_VERSION 0 #endif Index: src/util.c ================================================================== --- src/util.c +++ src/util.c @@ -1138,11 +1138,11 @@ u32 sqlite3Get4byte(const u8 *p){ #if SQLITE_BYTEORDER==4321 u32 x; memcpy(&x,p,4); return x; -#elif SQLITE_BYTEORDER==1234 && (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000) +#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 u32 x; memcpy(&x,p,4); return __builtin_bswap32(x); #elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 u32 x; @@ -1154,11 +1154,11 @@ #endif } void sqlite3Put4byte(unsigned char *p, u32 v){ #if SQLITE_BYTEORDER==4321 memcpy(p,&v,4); -#elif SQLITE_BYTEORDER==1234 && (GCC_VERSION>=4003000 || CLANG_VERSION>=3000000) +#elif SQLITE_BYTEORDER==1234 && GCC_VERSION>=4003000 u32 x = __builtin_bswap32(v); memcpy(p,&x,4); #elif SQLITE_BYTEORDER==1234 && MSVC_VERSION>=1300 u32 x = _byteswap_ulong(v); memcpy(p,&x,4); @@ -1273,11 +1273,11 @@ ** the other 64-bit signed integer at *pA and store the result in *pA. ** Return 0 on success. Or if the operation would have resulted in an ** overflow, leave *pA unchanged and return 1. */ int sqlite3AddInt64(i64 *pA, i64 iB){ -#if GCC_VERSION>=5004000 || CLANG_VERSION>=4000000 +#if GCC_VERSION>=5004000 return __builtin_add_overflow(*pA, iB, pA); #else i64 iA = *pA; testcase( iA==0 ); testcase( iA==1 ); testcase( iB==-1 ); testcase( iB==0 ); @@ -1293,11 +1293,11 @@ *pA += iB; return 0; #endif } int sqlite3SubInt64(i64 *pA, i64 iB){ -#if GCC_VERSION>=5004000 || CLANG_VERSION>=4000000 +#if GCC_VERSION>=5004000 return __builtin_sub_overflow(*pA, iB, pA); #else testcase( iB==SMALLEST_INT64+1 ); if( iB==SMALLEST_INT64 ){ testcase( (*pA)==(-1) ); testcase( (*pA)==0 ); @@ -1308,11 +1308,11 @@ return sqlite3AddInt64(pA, -iB); } #endif } int sqlite3MulInt64(i64 *pA, i64 iB){ -#if GCC_VERSION>=5004000 || CLANG_VERSION>=4000000 +#if GCC_VERSION>=5004000 return __builtin_mul_overflow(*pA, iB, pA); #else i64 iA = *pA; if( iB>0 ){ if( iA>LARGEST_INT64/iB ) return 1; Index: src/vdbeInt.h ================================================================== --- src/vdbeInt.h +++ src/vdbeInt.h @@ -187,10 +187,11 @@ struct Mem { union MemValue { double r; /* Real value used when MEM_Real is set in flags */ i64 i; /* Integer value used when MEM_Int is set in flags */ int nZero; /* Used when bit MEM_Zero is set in flags */ + void *pPtr; /* Pointer when flags=MEM_NULL and eSubtype='p' */ FuncDef *pDef; /* Used only when flags==MEM_Agg */ RowSet *pRowSet; /* Used only when flags==MEM_RowSet */ VdbeFrame *pFrame; /* Used when flags==MEM_Frame */ } u; u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ @@ -472,10 +473,11 @@ #ifdef SQLITE_OMIT_FLOATING_POINT # define sqlite3VdbeMemSetDouble sqlite3VdbeMemSetInt64 #else void sqlite3VdbeMemSetDouble(Mem*, double); #endif +void sqlite3VdbeMemSetPointer(Mem*, void*); 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 @@ -195,10 +195,18 @@ return sqlite3VdbeIntValue((Mem*)pVal); } 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); } #ifndef SQLITE_OMIT_UTF16 @@ -373,10 +381,16 @@ sqlite3VdbeMemSetInt64(pCtx->pOut, iVal); } 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) ); pOut->eSubtype = eSubtype & 0xff; @@ -1358,10 +1372,20 @@ rc = vdbeUnbind(p, i); if( rc==SQLITE_OK ){ sqlite3_mutex_leave(p->db->mutex); } 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, const char *zData, Index: src/vdbemem.c ================================================================== --- src/vdbemem.c +++ src/vdbemem.c @@ -694,10 +694,21 @@ }else{ pMem->u.i = val; pMem->flags = MEM_Int; } } + +/* +** 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, ** manifest type REAL. Index: src/where.c ================================================================== --- src/where.c +++ src/where.c @@ -306,10 +306,11 @@ if( pIdx ){ int j = iColumn; iColumn = pIdx->aiColumn[j]; if( iColumn==XN_EXPR ){ pScan->pIdxExpr = pIdx->aColExpr->a[j].pExpr; + pScan->zCollName = pIdx->azColl[j]; }else if( iColumn==pIdx->pTable->iPKey ){ iColumn = XN_ROWID; }else if( iColumn>=0 ){ pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; pScan->zCollName = pIdx->azColl[j]; Index: test/indexexpr1.test ================================================================== --- test/indexexpr1.test +++ test/indexexpr1.test @@ -367,7 +367,17 @@ do_execsql_test indexexpr1-1200.4 { SELECT a+b, c+d FROM t10 ORDER BY a+b, c+d; } { 0 0 0 2 0 4 2 0 2 2 4 0 } + +# Ticket https://www.sqlite.org/src/tktview/eb703ba7b50c1a +# Incorrect result using an index on an expression with a collating function +# +do_execsql_test indexexpr1-1300.1 { + CREATE TABLE t1300(a INTEGER PRIMARY KEY, b); + INSERT INTO t1300 VALUES(1,'coffee'),(2,'COFFEE'),(3,'stress'),(4,'STRESS'); + CREATE INDEX t1300bexpr ON t1300( substr(b,4) ); + SELECT a FROM t1300 WHERE substr(b,4)='ess' COLLATE nocase ORDER BY +a; +} {3 4} finish_test Index: test/tabfunc01.test ================================================================== --- test/tabfunc01.test +++ test/tabfunc01.test @@ -148,66 +148,67 @@ 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 |} # Free up memory allocations intarray_addr