From 51e3d8e204824cf54bdee1aacf5846e161692813 Mon Sep 17 00:00:00 2001 From: danielk1977 Date: Thu, 20 May 2004 01:12:34 +0000 Subject: [PATCH] Add support for the new sqlite3_bind_*() APIs. (CVS 1410) FossilOrigin-Name: e8f980d842fcd793552acd32708db55c8f014634 --- manifest | 26 +++--- manifest.uuid | 2 +- src/sqliteInt.h | 3 +- src/test1.c | 242 +++++++++++++++++++++++++++++++++++++++++++++++- src/utf.c | 10 +- src/vdbe.c | 63 ++++++++++++- src/vdbeInt.h | 2 + src/vdbeaux.c | 38 ++++++-- test/bind.test | 131 +++++++++++++++++++++++++- 9 files changed, 480 insertions(+), 37 deletions(-) diff --git a/manifest b/manifest index bbd395bdd8..753acbb321 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Get\smore\stests\srunning.\s(CVS\s1409) -D 2004-05-19T21:09:32 +C Add\ssupport\sfor\sthe\snew\ssqlite3_bind_*()\sAPIs.\s(CVS\s1410) +D 2004-05-20T01:12:34 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -49,10 +49,10 @@ F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 F src/select.c d01c03462d57b9d1ea25eea297bbd2c1b1c70e47 F src/shell.c 0c4662e13bfbfd3d13b066c5859cc97ad2f95d21 F src/sqlite.h.in 8c62076ea226b1870df977d7438bf99383d02387 -F src/sqliteInt.h 6c3822050d10eb648dd04e4ca68a2e577e145496 +F src/sqliteInt.h 6b43ef88542c242b39ed41a84055e4504571a9f0 F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2 F src/tclsqlite.c fbf0fac73624ae246551a6c671f1de0235b5faa1 -F src/test1.c 12ef76b8aaba4408422f21f269256b630d4dd627 +F src/test1.c 9b068ec5488d1845fc890d25fc84e8577a0dff98 F src/test2.c 6195a1ca2c8d0d2d93644e86da3289b403486872 F src/test3.c 5e4a6d596f982f6f47a5f9f75ede9b4a3b739968 F src/test4.c b3fab9aea7a8940a8a7386ce1c7e2157b09bd296 @@ -60,13 +60,13 @@ F src/test5.c c92dca7028b19b9c8319d55e0a5037fc183640a6 F src/tokenize.c e7536dd31205d5afb76c1bdc832dea009c7a3847 F src/trigger.c 11afe9abfba13a2ba142944c797c952e162d117f F src/update.c 1f6687f8d1085f896a24c0fa13d802223ed55539 -F src/utf.c 48c537bf7990ce32a36b051401874d024ec2a07b +F src/utf.c 72a9843000985d11100e711e0ef06ff4b8946057 F src/util.c 35d20bd8d467861747262d12b87045d937781d93 F src/vacuum.c c134702e023db8778e6be59ac0ea7b02315b5476 -F src/vdbe.c 0f1918d2a702c5b99c7713646a60c78fe5085cfc +F src/vdbe.c 973ffe763e40b0a5c993d5f5632de58a37c411db F src/vdbe.h 314e9c07db73a42a6ba91ab7539e27652fc88870 -F src/vdbeInt.h faaa64433d2498f7a6eabccebac854e097b83680 -F src/vdbeaux.c c241a6ba1cc7dcd4158da6c4329d33de3c4d0e03 +F src/vdbeInt.h 97b95c622ea467d39879ae97d07732ebb4891b76 +F src/vdbeaux.c 4cd7291c34ff21079d4ddd62df4390b8bc22d1fb F src/where.c 626b2cbc4290d8be6c04ad7c8395f46d4e21d0d8 F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242 F test/attach.test cb9b884344e6cfa5e165965d5b1adea679a24c83 @@ -74,7 +74,7 @@ F test/attach2.test 7c388dee63a4c1997695c3d41957f32ce784ac56 F test/auth.test 5c4d95cdaf539c0c236e20ce1f71a93e7dde9185 F test/bigfile.test ea904b853ce2d703b16c5ce90e2b54951bc1ae81 F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578 -F test/bind.test 56a57043b42c4664ca705f6050e56717a8a6699a +F test/bind.test b0676476d1ccf210867ad972fa45d9ca0b9906c3 F test/btree.test 08e4093c78d2bc1d54e27266f8d17fed14751125 F test/btree2.test aa4a6d05b1ea90b1acaf83ba89039dd302a88635 F test/btree4.test 3797b4305694c7af6828675b0f4b1424b8ca30e4 @@ -193,7 +193,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604 F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P 34f03ba6a9d6e2144d0c6cbbbeb37b4c69705f1f -R 6f649f6c623ad18fd759a30cd0ff66ff -U drh -Z 2a22d59e6c6d628572425793997ef923 +P 7eb3f29e305d0f455f6544560c567fa6b6e24986 +R 1fcae74675628dbbea5a8739e50916af +U danielk1977 +Z 6bd7c10a30f56d031b982fa43af23d80 diff --git a/manifest.uuid b/manifest.uuid index 0c7a07de15..5279f2b0f8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7eb3f29e305d0f455f6544560c567fa6b6e24986 \ No newline at end of file +e8f980d842fcd793552acd32708db55c8f014634 \ No newline at end of file diff --git a/src/sqliteInt.h b/src/sqliteInt.h index afea0e4650..f757899f40 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.238 2004/05/19 20:41:03 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.239 2004/05/20 01:12:34 danielk1977 Exp $ */ #include "config.h" #include "sqlite.h" @@ -1321,6 +1321,7 @@ void *sqlite3utf8to16be(const unsigned char *pIn, int N); void *sqlite3utf8to16le(const unsigned char *pIn, int N); void sqlite3utf16to16le(void *pData, int N); void sqlite3utf16to16be(void *pData, int N); +int sqlite3utf16ByteLen(const void *pData); int sqlite3PutVarint(unsigned char *, u64); int sqlite3GetVarint(const unsigned char *, u64 *); int sqlite3GetVarint32(const unsigned char *, u32 *); diff --git a/src/test1.c b/src/test1.c index 1fe133d764..1a55fd3b2c 100644 --- a/src/test1.c +++ b/src/test1.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test1.c,v 1.40 2004/05/13 11:34:16 danielk1977 Exp $ +** $Id: test1.c,v 1.41 2004/05/20 01:12:35 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -51,6 +51,21 @@ static int getVmPointer(Tcl_Interp *interp, const char *zArg, sqlite_vm **ppVm){ return TCL_OK; } +/* +** Decode a pointer to an sqlite3_stmt object. +*/ +static int getStmtPointer( + Tcl_Interp *interp, + const char *zArg, + sqlite3_stmt **ppStmt +){ + if( sscanf(zArg, PTR_FMT, (void**)ppStmt)!=1 ){ + Tcl_AppendResult(interp, "\"", zArg, "\" is not a valid pointer value", 0); + return TCL_ERROR; + } + return TCL_OK; +} + /* ** Generate a text representation of a pointer that can be understood ** by the getDbPointer and getVmPointer routines above. @@ -967,6 +982,216 @@ static int test_breakpoint( return TCL_OK; /* Do nothing */ } +static int test_bind_int32( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int idx; + int value; + int rc; + + if( objc!=4 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " ", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; + + rc = sqlite3_bind_int32(pStmt, idx, value); + if( rc!=SQLITE_OK ){ + return TCL_ERROR; + } + + return TCL_OK; +} + +static int test_bind_int64( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int idx; + i64 value; + int rc; + + if( objc!=4 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " ", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; + if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR; + + rc = sqlite3_bind_int64(pStmt, idx, value); + if( rc!=SQLITE_OK ){ + return TCL_ERROR; + } + + return TCL_OK; +} + +static int test_bind_double( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int idx; + double value; + int rc; + + if( objc!=4 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " ", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; + if( Tcl_GetDoubleFromObj(interp, objv[3], &value) ) return TCL_ERROR; + + rc = sqlite3_bind_double(pStmt, idx, value); + if( rc!=SQLITE_OK ){ + return TCL_ERROR; + } + + return TCL_OK; +} + +static int test_bind_null( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int idx; + int rc; + + if( objc!=3 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " ", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; + + rc = sqlite3_bind_null(pStmt, idx); + if( rc!=SQLITE_OK ){ + return TCL_ERROR; + } + + return TCL_OK; +} + +static int test_bind_text( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int idx; + int bytes; + char *value; + int rc; + + if( objc!=5 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " " + " ", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; + value = Tcl_GetString(objv[3]); + if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; + + rc = sqlite3_bind_text(pStmt, idx, value, bytes, 1); + if( rc!=SQLITE_OK ){ + return TCL_ERROR; + } + + return TCL_OK; +} + +static int test_bind_text16( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int idx; + int bytes; + char *value; + int rc; + + if( objc!=5 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " " + " ", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; + value = Tcl_GetByteArrayFromObj(objv[3], 0); + if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR; + + rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, 1); + if( rc!=SQLITE_OK ){ + return TCL_ERROR; + } + + return TCL_OK; +} + +static int test_bind_blob( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int idx; + int bytes; + char *value; + int rc; + + if( objc!=5 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", + Tcl_GetStringFromObj(objv[0], 0), " " + " ", 0); + return TCL_ERROR; + } + + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR; + value = Tcl_GetString(objv[3]); + if( Tcl_GetIntFromObj(interp, objv[2], &bytes) ) return TCL_ERROR; + + rc = sqlite3_bind_blob(pStmt, idx, value, bytes, 1); + if( rc!=SQLITE_OK ){ + return TCL_ERROR; + } + + return TCL_OK; +} + /* ** Register commands with the TCL interpreter. */ @@ -1005,11 +1230,26 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite_reset", (Tcl_CmdProc*)test_reset }, { "breakpoint", (Tcl_CmdProc*)test_breakpoint }, }; + static struct { + char *zName; + Tcl_ObjCmdProc *xProc; + } aObjCmd[] = { + { "sqlite3_bind_int32", (Tcl_ObjCmdProc*)test_bind_int32 }, + { "sqlite3_bind_int64", (Tcl_ObjCmdProc*)test_bind_int64 }, + { "sqlite3_bind_double", (Tcl_ObjCmdProc*)test_bind_double }, + { "sqlite3_bind_null", (Tcl_ObjCmdProc*)test_bind_null }, + { "sqlite3_bind_text", (Tcl_ObjCmdProc*)test_bind_text }, + { "sqlite3_bind_text16", (Tcl_ObjCmdProc*)test_bind_text16 }, + { "sqlite3_bind_blob", (Tcl_ObjCmdProc*)test_bind_blob }, + }; int i; for(i=0; iflags & MEM_Str)==0){hardStringify(P);} \ + else if(((P)->flags & MEM_Term)==0){hardNulTermify(P);} +static int hardNulTermify(Mem *pStack){ + int flags = pStack->flags; + + assert( !(flags&MEM_Term) && (flags&MEM_Str) ); + assert( flags&(MEM_Utf8|MEM_Utf16le|MEM_Utf16be) ); + + if( flags&MEM_Utf8 ){ + /* If the string is already dynamically allocated, use sqliteRealloc() + ** to allocate extra space for the terminator. + */ + if( flags&MEM_Dyn ){ + pStack->z = sqliteRealloc(pStack->z, pStack->n+1); + if( !pStack->z ){ + return 1; + } + } + + if( flags&(MEM_Static|MEM_Ephem|MEM_Short) ){ + if( pStack->n+1zShort, pStack->z, pStack->n); + pStack->flags = MEM_Short|MEM_Str|MEM_Utf8|MEM_Term; + } + }else{ + char *z = sqliteMalloc(pStack->n+1); + if( !z ){ + return 1; + } + memcpy(z, pStack->z, pStack->n); + pStack->z = z; + pStack->flags = MEM_Dyn|MEM_Str|MEM_Utf8|MEM_Term; + } + } + + pStack->z[pStack->n] = '\0'; + pStack->n++; + }else{ + assert(0); + } + + return 0; +} + /* ** Convert the given stack entity into a string if it isn't one ** already. @@ -205,7 +250,7 @@ static int hardStringify(Mem *pStack){ } pStack->z = pStack->zShort; pStack->n = strlen(pStack->zShort)+1; - pStack->flags = MEM_Str | MEM_Short; + pStack->flags = MEM_Str | MEM_Short | MEM_Term; return 0; } @@ -834,7 +879,7 @@ case OP_Variable: { ** variable is used again, even after the virtual machine is reset, the ** conversion won't have to be done again. ** - ** TODO: This is where we need to support databases that use other than + ** FIX ME: This is where we need to support databases that use other than ** UTF-8 on disk. */ pVar = &p->apVar[j]; @@ -848,7 +893,17 @@ case OP_Variable: { Release(pVar); pVar->z = zUtf8; pVar->n = strlen(zUtf8)+1; - pVar->flags = MEM_Str|MEM_Dyn; + pVar->flags = MEM_Str|MEM_Dyn|MEM_Utf8|MEM_Term; + } + + /* Ensure that the variable value is nul terminated. Again, do this in + ** place. + ** + ** FIX ME: The rest of the vdbe will soon understand MEM_Term, making + ** this step unnecessary. + */ + if( pVar->flags&MEM_Str ){ + NulTermify(pVar); } /* Copy the value in pVar to the top of the stack. If pVar is a string or diff --git a/src/vdbeInt.h b/src/vdbeInt.h index f86a4aff31..4f5d0f7147 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -146,6 +146,8 @@ typedef struct Mem Mem; #define MEM_Real 0x0008 /* Value is a real number */ #define MEM_Blob 0x0010 /* Value is a BLOB */ +#define MEM_Term 0x1000 /* String has a nul terminator character */ + #define MEM_Utf8 0x0020 /* String uses UTF-8 encoding */ #define MEM_Utf16be 0x0040 /* String uses UTF-16 big-endian */ #define MEM_Utf16le 0x0080 /* String uses UTF-16 little-endian */ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index a8f04a5e94..03757e3878 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1043,10 +1043,16 @@ int sqlite3_bind_text( int nData, int eCopy ){ - if( zData && nData<0 ){ - nData = strlen(zData)+1; + int flags = MEM_Str|MEM_Utf8; + if( zData ){ + if( nData<0 ){ + nData = strlen(zData)+1; + flags |= MEM_Term; + }else if( !zData[nData-1] ){ + flags |= MEM_Term; + } } - return vdbeBindBlob((Vdbe *)p, i, zData, nData, eCopy, MEM_Str|MEM_Utf8); + return vdbeBindBlob((Vdbe *)p, i, zData, nData, eCopy, flags); } int sqlite3_bind_text16( @@ -1056,14 +1062,26 @@ int sqlite3_bind_text16( int nData, int eCopy ){ - if( zData && nData<0 ){ - char *z = (char *)zData; - while( (*z)!=0 && (*(z+1))!=0 ) z+=2; - nData = (z - (char *)zData) + 2; - } + int flags = MEM_Str|MEM_Utf16le|MEM_Utf16be; + + if( zData ){ + /* If nData is less than zero, measure the length of the string. + ** manually. In this case the variable will always be null terminated. + */ + if( nData<0 ){ + nData = sqlite3utf16ByteLen(zData) + 2; + flags |= MEM_Term; + }else{ + /* If nData is greater than zero, check if the final character appears + ** to be a terminator. + */ + if( !(((u8 *)zData)[nData-1]) && !(((u8 *)zData)[nData-2]) ){ + flags |= MEM_Term; + } + } + } - /* FIX ME - MEM_Utf16le? */ - return vdbeBindBlob((Vdbe *)p, i, zData, nData, eCopy, MEM_Str|MEM_Utf16le); + return vdbeBindBlob((Vdbe *)p, i, zData, nData, eCopy, flags); } int sqlite3_bind_blob( diff --git a/test/bind.test b/test/bind.test index 639eaaec4c..35a5cae83d 100644 --- a/test/bind.test +++ b/test/bind.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this script testing the sqlite_bind API. # -# $Id: bind.test,v 1.1 2003/09/06 22:45:21 drh Exp $ +# $Id: bind.test,v 1.2 2004/05/20 01:12:35 danielk1977 Exp $ # set testdir [file dirname $argv0] @@ -63,10 +63,137 @@ do_test bind-1.9 { execsql {SELECT rowid, * FROM t1} } {1 123 abcdefg {} 2 456 abcdefg {}} - do_test bind-1.99 { sqlite_finalize $VM } {} +do_test bind-2.1 { + execsql { + DELETE FROM t1; + } + set VM [sqlite_compile $DB {INSERT INTO t1 VALUES(?,?,?)} TAIL] + set TAIL +} {} + +# 32 bit Integers +do_test bind-2.2 { + sqlite3_bind_int32 $VM 1 123 + sqlite3_bind_int32 $VM 2 456 + sqlite3_bind_int32 $VM 3 789 + sqlite_step $VM N VALUES COLNAMES + sqlite_reset $VM + execsql {SELECT rowid, * FROM t1} +} {1 123 456 789} +do_test bind-2.3 { + sqlite3_bind_int32 $VM 2 -2000000000 + sqlite3_bind_int32 $VM 3 2000000000 + sqlite_step $VM N VALUES COLNAMES + sqlite_reset $VM + execsql {SELECT rowid, * FROM t1} +} {1 123 456 789 2 123 -2000000000 2000000000} +do_test bind-2.4 { + execsql {SELECT classof(a), classof(b), classof(c) FROM t1} +} {INTEGER INTEGER INTEGER INTEGER INTEGER INTEGER} +do_test bind-2.5 { + execsql { + DELETE FROM t1; + } +} {} + +# 64 bit Integers +do_test bind-3.1 { + sqlite3_bind_int64 $VM 1 32 + sqlite3_bind_int64 $VM 2 -2000000000000 + sqlite3_bind_int64 $VM 3 2000000000000 + sqlite_step $VM N VALUES COLNAMES + sqlite_reset $VM + execsql {SELECT rowid, * FROM t1} +} {1 32 -2000000000000 2000000000000} +do_test bind-3.2 { + execsql {SELECT classof(a), classof(b), classof(c) FROM t1} +} {INTEGER INTEGER INTEGER} +do_test bind-3.3 { + execsql { + DELETE FROM t1; + } +} {} + +# Doubles +do_test bind-4.1 { + sqlite3_bind_double $VM 1 1234.1234 + sqlite3_bind_double $VM 2 0.00001 + sqlite3_bind_double $VM 3 123456789 + sqlite_step $VM N VALUES COLNAMES + sqlite_reset $VM + execsql {SELECT rowid, * FROM t1} +} {1 1234.1234 1e-05 123456789} +do_test bind-4.2 { + execsql {SELECT classof(a), classof(b), classof(c) FROM t1} +} {REAL REAL REAL} +do_test bind-4.3 { + execsql { + DELETE FROM t1; + } +} {} + +# NULL +do_test bind-5.1 { + sqlite3_bind_null $VM 1 + sqlite3_bind_null $VM 2 + sqlite3_bind_null $VM 3 + sqlite_step $VM N VALUES COLNAMES + sqlite_reset $VM + execsql {SELECT rowid, * FROM t1} +} {1 {} {} {}} +do_test bind-5.2 { + execsql {SELECT classof(a), classof(b), classof(c) FROM t1} +} {NULL NULL NULL} +do_test bind-5.3 { + execsql { + DELETE FROM t1; + } +} {} + +# UTF-8 text +do_test bind-6.1 { + sqlite3_bind_text $VM 1 hellothere 5 + sqlite3_bind_text $VM 2 "." 2 + sqlite3_bind_text $VM 3 world -1 + sqlite_step $VM N VALUES COLNAMES + sqlite_reset $VM + execsql {SELECT rowid, * FROM t1} +} {1 hello . world} +do_test bind-6.2 { + execsql {SELECT classof(a), classof(b), classof(c) FROM t1} +} {TEXT TEXT TEXT} +do_test bind-6.3 { + execsql { + DELETE FROM t1; + } +} {} + +# UTF-16 text +do_test bind-7.1 { + sqlite3_bind_text16 $VM 1 [encoding convertto unicode hellothere] 10 + sqlite3_bind_text16 $VM 2 [encoding convertto unicode ""] 0 + sqlite3_bind_text16 $VM 3 [encoding convertto unicode world] 10 + sqlite_step $VM N VALUES COLNAMES + sqlite_reset $VM + execsql {SELECT rowid, * FROM t1} +} {1 hello {} world} +do_test bind-7.2 { + execsql {SELECT classof(a), classof(b), classof(c) FROM t1} +} {TEXT TEXT TEXT} +do_test bind-7.3 { + execsql { + DELETE FROM t1; + } +} {} + +do_test bind-8.99 { + sqlite_finalize $VM +} {} + + finish_test