Index: third_party/sqlite/src/src/test_func.c |
diff --git a/third_party/sqlite/src/src/test_func.c b/third_party/sqlite/src/src/test_func.c |
index a123943425e7e00b686a0ffb3ac77d6f3a607767..c7850631d7b213a8ff5346a0a215be1b748b36c6 100644 |
--- a/third_party/sqlite/src/src/test_func.c |
+++ b/third_party/sqlite/src/src/test_func.c |
@@ -18,6 +18,9 @@ |
#include <string.h> |
#include <assert.h> |
+#include "sqliteInt.h" |
+#include "vdbeInt.h" |
+ |
/* |
** Allocate nByte bytes of space using sqlite3_malloc(). If the |
@@ -149,13 +152,13 @@ static void test_destructor_count( |
** arguments. It returns the text value returned by the sqlite3_errmsg16() |
** API function. |
*/ |
-#ifndef SQLITE_OMIT_BUILTIN_TEST |
+#ifndef SQLITE_OMIT_BUILTIN_TEST |
void sqlite3BeginBenignMalloc(void); |
void sqlite3EndBenignMalloc(void); |
-#else |
- #define sqlite3BeginBenignMalloc() |
- #define sqlite3EndBenignMalloc() |
-#endif |
+#else |
+ #define sqlite3BeginBenignMalloc() |
+ #define sqlite3EndBenignMalloc() |
+#endif |
static void test_agg_errmsg16_step(sqlite3_context *a, int b,sqlite3_value **c){ |
} |
static void test_agg_errmsg16_final(sqlite3_context *ctx){ |
@@ -202,7 +205,7 @@ static void test_auxdata( |
}else { |
zRet[i*2] = '0'; |
} |
- n = strlen(z) + 1; |
+ n = (int)strlen(z) + 1; |
zAux = testContextMalloc(pCtx, n); |
if( zAux ){ |
memcpy(zAux, z, n); |
@@ -422,6 +425,182 @@ static void testHexToUtf16le( |
} |
#endif |
+/* |
+** SQL function: real2hex(X) |
+** |
+** If argument X is a real number, then convert it into a string which is |
+** the big-endian hexadecimal representation of the ieee754 encoding of |
+** that number. If X is not a real number, return NULL. |
+*/ |
+static void real2hex( |
+ sqlite3_context *context, |
+ int argc, |
+ sqlite3_value **argv |
+){ |
+ union { |
+ sqlite3_uint64 i; |
+ double r; |
+ unsigned char x[8]; |
+ } v; |
+ char zOut[20]; |
+ int i; |
+ int bigEndian; |
+ v.i = 1; |
+ bigEndian = v.x[0]==0; |
+ v.r = sqlite3_value_double(argv[0]); |
+ for(i=0; i<8; i++){ |
+ if( bigEndian ){ |
+ zOut[i*2] = "0123456789abcdef"[v.x[i]>>4]; |
+ zOut[i*2+1] = "0123456789abcdef"[v.x[i]&0xf]; |
+ }else{ |
+ zOut[14-i*2] = "0123456789abcdef"[v.x[i]>>4]; |
+ zOut[14-i*2+1] = "0123456789abcdef"[v.x[i]&0xf]; |
+ } |
+ } |
+ zOut[16] = 0; |
+ sqlite3_result_text(context, zOut, -1, SQLITE_TRANSIENT); |
+} |
+ |
+/* |
+** tclcmd: test_extract(record, field) |
+** |
+** This function implements an SQL user-function that accepts a blob |
+** containing a formatted database record as the first argument. The |
+** second argument is the index of the field within that record to |
+** extract and return. |
+*/ |
+static void test_extract( |
+ sqlite3_context *context, |
+ int argc, |
+ sqlite3_value **argv |
+){ |
+ sqlite3 *db = sqlite3_context_db_handle(context); |
+ u8 *pRec; |
+ u8 *pEndHdr; /* Points to one byte past record header */ |
+ u8 *pHdr; /* Current point in record header */ |
+ u8 *pBody; /* Current point in record data */ |
+ u64 nHdr; /* Bytes in record header */ |
+ int iIdx; /* Required field */ |
+ int iCurrent = 0; /* Current field */ |
+ |
+ assert( argc==2 ); |
+ pRec = (u8*)sqlite3_value_blob(argv[0]); |
+ iIdx = sqlite3_value_int(argv[1]); |
+ |
+ pHdr = pRec + sqlite3GetVarint(pRec, &nHdr); |
+ pBody = pEndHdr = &pRec[nHdr]; |
+ |
+ for(iCurrent=0; pHdr<pEndHdr && iCurrent<=iIdx; iCurrent++){ |
+ u64 iSerialType; |
+ Mem mem; |
+ |
+ memset(&mem, 0, sizeof(mem)); |
+ mem.db = db; |
+ mem.enc = ENC(db); |
+ pHdr += sqlite3GetVarint(pHdr, &iSerialType); |
+ pBody += sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem); |
+ |
+ if( iCurrent==iIdx ){ |
+ sqlite3_result_value(context, &mem); |
+ } |
+ |
+ if( mem.szMalloc ) sqlite3DbFree(db, mem.zMalloc); |
+ } |
+} |
+ |
+/* |
+** tclcmd: test_decode(record) |
+** |
+** This function implements an SQL user-function that accepts a blob |
+** containing a formatted database record as its only argument. It returns |
+** a tcl list (type SQLITE_TEXT) containing each of the values stored |
+** in the record. |
+*/ |
+static void test_decode( |
+ sqlite3_context *context, |
+ int argc, |
+ sqlite3_value **argv |
+){ |
+ sqlite3 *db = sqlite3_context_db_handle(context); |
+ u8 *pRec; |
+ u8 *pEndHdr; /* Points to one byte past record header */ |
+ u8 *pHdr; /* Current point in record header */ |
+ u8 *pBody; /* Current point in record data */ |
+ u64 nHdr; /* Bytes in record header */ |
+ Tcl_Obj *pRet; /* Return value */ |
+ |
+ pRet = Tcl_NewObj(); |
+ Tcl_IncrRefCount(pRet); |
+ |
+ assert( argc==1 ); |
+ pRec = (u8*)sqlite3_value_blob(argv[0]); |
+ |
+ pHdr = pRec + sqlite3GetVarint(pRec, &nHdr); |
+ pBody = pEndHdr = &pRec[nHdr]; |
+ while( pHdr<pEndHdr ){ |
+ Tcl_Obj *pVal = 0; |
+ u64 iSerialType; |
+ Mem mem; |
+ |
+ memset(&mem, 0, sizeof(mem)); |
+ mem.db = db; |
+ mem.enc = ENC(db); |
+ pHdr += sqlite3GetVarint(pHdr, &iSerialType); |
+ pBody += sqlite3VdbeSerialGet(pBody, (u32)iSerialType, &mem); |
+ |
+ switch( sqlite3_value_type(&mem) ){ |
+ case SQLITE_TEXT: |
+ pVal = Tcl_NewStringObj((const char*)sqlite3_value_text(&mem), -1); |
+ break; |
+ |
+ case SQLITE_BLOB: { |
+ char hexdigit[] = { |
+ '0', '1', '2', '3', '4', '5', '6', '7', |
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' |
+ }; |
+ int n = sqlite3_value_bytes(&mem); |
+ u8 *z = (u8*)sqlite3_value_blob(&mem); |
+ int i; |
+ pVal = Tcl_NewStringObj("x'", -1); |
+ for(i=0; i<n; i++){ |
+ char hex[3]; |
+ hex[0] = hexdigit[((z[i] >> 4) & 0x0F)]; |
+ hex[1] = hexdigit[(z[i] & 0x0F)]; |
+ hex[2] = '\0'; |
+ Tcl_AppendStringsToObj(pVal, hex, 0); |
+ } |
+ Tcl_AppendStringsToObj(pVal, "'", 0); |
+ break; |
+ } |
+ |
+ case SQLITE_FLOAT: |
+ pVal = Tcl_NewDoubleObj(sqlite3_value_double(&mem)); |
+ break; |
+ |
+ case SQLITE_INTEGER: |
+ pVal = Tcl_NewWideIntObj(sqlite3_value_int64(&mem)); |
+ break; |
+ |
+ case SQLITE_NULL: |
+ pVal = Tcl_NewStringObj("NULL", -1); |
+ break; |
+ |
+ default: |
+ assert( 0 ); |
+ } |
+ |
+ Tcl_ListObjAppendElement(0, pRet, pVal); |
+ |
+ if( mem.szMalloc ){ |
+ sqlite3DbFree(db, mem.zMalloc); |
+ } |
+ } |
+ |
+ sqlite3_result_text(context, Tcl_GetString(pRet), -1, SQLITE_TRANSIENT); |
+ Tcl_DecrRefCount(pRet); |
+} |
+ |
+ |
static int registerTestFunctions(sqlite3 *db){ |
static const struct { |
char *zName; |
@@ -444,6 +623,9 @@ static int registerTestFunctions(sqlite3 *db){ |
{ "test_eval", 1, SQLITE_UTF8, test_eval}, |
{ "test_isolation", 2, SQLITE_UTF8, test_isolation}, |
{ "test_counter", 1, SQLITE_UTF8, counterFunc}, |
+ { "real2hex", 1, SQLITE_UTF8, real2hex}, |
+ { "test_decode", 1, SQLITE_UTF8, test_decode}, |
+ { "test_extract", 2, SQLITE_UTF8, test_extract}, |
}; |
int i; |