diff --git a/manifest b/manifest index 9e4b1c1fd7..f584ab9a63 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\sonecolumn\smethod\sin\sthe\sTCL\sinterface\sso\sthat\sit\sworks\sthe\ssame\nas\sthe\seval\smethod\sin\sall\sways\sexcept\sfor\sreturning\sjust\sthe\sfirst\svalue\nin\sthe\sresult\sset.\s(CVS\s1944) -D 2004-09-07T13:20:35 +C Wildcards\swith\sthe\ssame\sname\smap\sinto\sthe\ssame\svariable\snumber.\s\sNew\napi\ssqlite3_bind_parameter_index()\sadded\sto\smap\swildcard\snames\sinto\nwildcard\sindex\snumbers.\s\sSupport\sfor\s"?nnn"\swildcards.\s(CVS\s1945) +D 2004-09-07T16:19:53 F Makefile.in 65a7c43fcaf9a710d62f120b11b6e435eeb4a450 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -34,7 +34,7 @@ F src/build.c c6940e4a663fa6b7dc3dff34f7dddbc45d331d48 F src/date.c eb8d5fa1a6d5cfc09031c8852d10ff742a94b15b F src/delete.c e887f44aae1e33da1643df58abe86cd9cde45ad1 F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37 -F src/expr.c 5b6881a229e49869c348825aa1f1af6bd6b4bc76 +F src/expr.c 9130794d8c86af2cbf2b8cdc66f2158167fd15b1 F src/func.c 14bf20710a10fe66266e16da4364ca2dd8c4c36d F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84 @@ -54,22 +54,22 @@ F src/os_win.c 9e2887825b1a32f0ceb1b73b93ffe29a112cd86f F src/os_win.h babd4e912967c6b09088cfe38a45e8005a07ba44 F src/pager.c ae06c85de0db43f61a7a3e5eacad3fd5615daf59 F src/pager.h 67739fe649f33be55dba522ca8a9cc4e42d14f71 -F src/parse.y 581a2ce014b843506805b2470c02b7865ad034d5 +F src/parse.y 9389af67bd49b8e5c9d2968b3315a30565b4a200 F src/pragma.c 6385059dfd77eee9fe7e53c0469776315f136ae0 F src/printf.c 17b28a1eedfe8129b05de981719306c18c3f1327 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 F src/select.c 6e3ec12a01c6d5b51459d6ddaca36040d9e7730e F src/shell.c 4f1a2760ced81c829defb47b0a3b61ffec61b604 -F src/sqlite.h.in 8bdf3fc4c76040f939cb1831eb97babf6a2fa858 -F src/sqliteInt.h 0840e651db8e16f88f2b8a2393ac98dfdbf01df0 +F src/sqlite.h.in e29a526593b806f148017ed8bada760ada84cf2f +F src/sqliteInt.h abbb66373b410e242b617af0364def4f7af084fc F src/table.c 8168c6e824009f8485bff79fc60ea8fea6829b10 F src/tclsqlite.c 9225350a3144b3c0dd07a3cc88d2c219d57e2f0d -F src/test1.c 0a7ae23d822177ecf3e8b577d026f0c8a39fe5c3 +F src/test1.c e7df5556002c50e917420f6f0edcc63047567659 F src/test2.c f4c2f3928f1998fd8cb75a81e33a60e025ea85d4 F src/test3.c 94d0a2a90bccd85802488cb42c69ec8afd2e4646 F src/test4.c 7c6b9fc33dd1f3f93c7f1ee6e5e6d016afa6c1df F src/test5.c b001fa7f1b9e2dc5c2331de62fc641b5ab2bd7a1 -F src/tokenize.c 566ca7d1354dcb990475a52990056fc387d49df1 +F src/tokenize.c 60525d9966d90f548f44cc37116378379424c2a1 F src/trigger.c 98dd620bebd9f3dadaacf0db3958b916cf1e7b7f F src/update.c 0e00300763d2ce0dbd6a0598882a5039580b225e F src/utf.c 328890099db492dda5620ee5f924e244c6e57ff7 @@ -78,7 +78,7 @@ F src/vacuum.c 819a3f411cb8d2d714e55f0805e8c23a642dd7ba F src/vdbe.c b19de04c57b4136a8e0203d5e3b76dd82bded1b5 F src/vdbe.h 067ca8d6750ba4f69a50284765e5883dee860181 F src/vdbeInt.h e09362d6323a725de3c30b0cc381a691e86ed697 -F src/vdbeapi.c e3fa5b775161bc8337c20f2e46a68bb4746b2094 +F src/vdbeapi.c 20bf8901592c7f38e8aabb448a913327ab19f0a7 F src/vdbeaux.c 4080a6162d96818f875a95ead4f67cb9ca8ecf15 F src/vdbemem.c ef9ac7d32acfe4bce5c5b408b1294c8d9e0cdb56 F src/where.c 12e214870c84546858ddb9f121165a1fbfce6811 @@ -89,7 +89,7 @@ F test/attach3.test 6d060986ff004ebb89e1876a331d96c6bb62269e F test/auth.test e74b015545f608c06d5b84d17acdf7146eb818af F test/bigfile.test 62722ac4b420dfbcdceb137b8634e2cf2865fe27 F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747 -F test/bind.test 7968edd61eb83b6e09165e4ba38e327dace6fb35 +F test/bind.test d7e7f44817a6dbe0faedbb699ad2b559e5a3a7bb F test/blob.test 8727a7b46b2073a369cfc9bcb6f54dd366b9d884 F test/btree.test 97b563e1ab999bf8764b129e8c4b4be0a116a52a F test/btree2.test aa4a6d05b1ea90b1acaf83ba89039dd302a88635 @@ -217,7 +217,7 @@ F www/arch2b.fig d22a2c9642d584b89d4088b1e51e2bb0f7c04bed F www/audit.tcl 90e09d580f79c7efec0c7d6f447b7ec5c2dce5c0 F www/c_interface.tcl 83b39203e1ded4c2dab97f42edf31279a308efcb F www/capi3.tcl 5c1cb163f4d2a54e2d0e22dcc399dd71245c8b89 -F www/capi3ref.tcl bead38516efb0227ffa6ac76beb3f7ea405bb389 +F www/capi3ref.tcl aa6ea82ea34ff71357300b8f1ab9fd8232a9eec8 F www/changes.tcl 3641bc28b86b40c82d546727da45ea0f0aa9a9f4 F www/common.tcl f786e6be86fb2627ceb30e770e9efa83b9c67a3a F www/conflict.tcl fb8a2ba83746c7fdfd9e52fa7f6aaf5c422b8246 @@ -248,7 +248,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P d53047cbbc4e618c7bb5161b6f82876bb113db25 -R 303fc0394eb00108b3dd869bec641bd9 +P f323e4f86a08fe6448cbd4ff7cab459e8039d9f1 +R b14b673cf74913bc0aa77288120014ba U drh -Z 3769d67a37ed8f4ac0e4d151ebaba45a +Z abec07c7d353cf60af4ed426f1ba4bbf diff --git a/manifest.uuid b/manifest.uuid index 4d5283f9dd..ddef491877 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f323e4f86a08fe6448cbd4ff7cab459e8039d9f1 \ No newline at end of file +435b3f301fbb6953adc974c7f03589b06e9114c3 \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index b72474a618..86cb54ad39 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.160 2004/09/06 17:24:13 drh Exp $ +** $Id: expr.c,v 1.161 2004/09/07 16:19:53 drh Exp $ */ #include "sqliteInt.h" #include @@ -273,6 +273,75 @@ Expr *sqlite3ExprFunction(ExprList *pList, Token *pToken){ return pNew; } +/* +** Assign a variable number to an expression that encodes a wildcard +** in the original SQL statement. +** +** Wildcards consisting of a single "?" are assigned the next sequential +** variable number. +** +** Wildcards of the form "?nnn" are assigned the number "nnn". We make +** sure "nnn" is not too be to avoid a denial of service attack when +** the SQL statement comes from an external source. +** +** Wildcards of the form ":aaa" or "$aaa" are assigned the same number +** as the previous instance of the same wildcard. Or if this is the first +** instance of the wildcard, the next sequenial variable number is +** assigned. +*/ +void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ + Token *pToken; + if( pExpr==0 ) return; + pToken = &pExpr->token; + assert( pToken->n>=1 ); + assert( pToken->z!=0 ); + assert( pToken->z[0]!=0 ); + if( pToken->n==1 ){ + /* Wildcard of the form "?". Assign the next variable number */ + pExpr->iTable = ++pParse->nVar; + }else if( pToken->z[0]=='?' ){ + /* Wildcard of the form "?nnn". Convert "nnn" to an integer and + ** use it as the variable number */ + int i; + pExpr->iTable = i = atoi(&pToken->z[1]); + if( i<1 || i>SQLITE_MAX_VARIABLE_NUMBER ){ + sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d", + SQLITE_MAX_VARIABLE_NUMBER); + } + if( i>pParse->nVar ){ + pParse->nVar = i; + } + }else{ + /* Wildcards of the form ":aaa" or "$aaa". Reuse the same variable + ** number as the prior appearance of the same name, or if the name + ** has never appeared before, reuse the same variable number + */ + int i, n; + n = pToken->n; + for(i=0; inVarExpr; i++){ + Expr *pE; + if( (pE = pParse->apVarExpr[i])!=0 + && pE->token.n==n + && memcmp(pE->token.z, pToken->z, n)==0 ){ + pExpr->iTable = pE->iTable; + break; + } + } + if( i>=pParse->nVarExpr ){ + pExpr->iTable = ++pParse->nVar; + if( pParse->nVarExpr>=pParse->nVarExprAlloc-1 ){ + pParse->nVarExprAlloc += pParse->nVarExprAlloc + 10; + pParse->apVarExpr = sqliteRealloc(pParse->apVarExpr, + pParse->nVarExprAlloc*sizeof(pParse->apVarExpr[0]) ); + } + if( !sqlite3_malloc_failed ){ + assert( pParse->apVarExpr!=0 ); + pParse->apVarExpr[pParse->nVarExpr++] = pExpr; + } + } + } +} + /* ** Recursively delete an expression tree. */ diff --git a/src/parse.y b/src/parse.y index a22f9e5d14..37a864aac7 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,7 +14,7 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.135 2004/08/25 04:07:02 drh Exp $ +** @(#) $Id: parse.y,v 1.136 2004/09/07 16:19:54 drh Exp $ */ %token_prefix TK_ %token_type {Token} @@ -560,9 +560,7 @@ expr(A) ::= BLOB(X). {A = sqlite3Expr(@X, 0, 0, &X);} expr(A) ::= VARIABLE(X). { Token *pToken = &X; Expr *pExpr = A = sqlite3Expr(TK_VARIABLE, 0, 0, pToken); - if( pExpr ){ - pExpr->iTable = ++pParse->nVar; - } + sqlite3ExprAssignVarNumber(pParse, pExpr); } expr(A) ::= ID(X) LP exprlist(Y) RP(E). { A = sqlite3ExprFunction(Y, &X); diff --git a/src/sqlite.h.in b/src/sqlite.h.in index ae4ce19789..218a91cd47 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -12,7 +12,7 @@ ** This header file defines the interface that the SQLite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.118 2004/09/06 17:34:13 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.119 2004/09/07 16:19:54 drh Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -640,12 +640,19 @@ int sqlite3_bind_parameter_count(sqlite3_stmt*); /* ** Return the name of the i-th parameter. Ordinary wildcards "?" are -** nameless and a NULL is returned. For wildcards of the form :N: or +** nameless and a NULL is returned. For wildcards of the form :N or ** $vvvv the complete text of the wildcard is returned. ** NULL is returned if the index is out of range. */ const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int); +/* +** Return the index of a parameter with the given name. The name +** must match exactly. If no parameter with the given name is found, +** return 0. +*/ +int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); + /* ** Return the number of columns in the result set returned by the compiled ** SQL statement. This routine returns 0 if pStmt is an SQL statement diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 28f9f36c18..0fd1029fa5 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.319 2004/09/06 17:24:13 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.320 2004/09/07 16:19:54 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -67,6 +67,11 @@ */ #define MAX_ATTACHED 10 +/* +** The maximum value of a ?nnn wildcard that the parser will accept. +*/ +#define SQLITE_MAX_VARIABLE_NUMBER 999 + /* ** When building SQLite for embedded systems where memory is scarce, ** you can define one or more of the following macros to omit extra @@ -990,6 +995,9 @@ struct Parse { int nSet; /* Number of sets used so far */ int nAgg; /* Number of aggregate expressions */ int nVar; /* Number of '?' variables seen in the SQL so far */ + int nVarExpr; /* Number of used slots in apVarExpr[] */ + int nVarExprAlloc; /* Number of allocated slots in apVarExpr[] */ + Expr **apVarExpr; /* Pointers to :aaa and $aaaa wildcard expressions */ AggExpr *aAgg; /* An array of aggregate expressions */ const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ @@ -1209,6 +1217,7 @@ Expr *sqlite3Expr(int, Expr*, Expr*, Token*); Expr *sqlite3ExprAnd(Expr*, Expr*); void sqlite3ExprSpan(Expr*,Token*,Token*); Expr *sqlite3ExprFunction(ExprList*, Token*); +void sqlite3ExprAssignVarNumber(Parse*, Expr*); void sqlite3ExprDelete(Expr*); ExprList *sqlite3ExprListAppend(ExprList*,Expr*,Token*); void sqlite3ExprListDelete(ExprList*); diff --git a/src/test1.c b/src/test1.c index cbd3e7372d..a8a8b17e0e 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.101 2004/09/06 17:24:13 drh Exp $ +** $Id: test1.c,v 1.102 2004/09/07 16:19:54 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -1645,6 +1645,33 @@ static int test_bind_parameter_name( return TCL_OK; } +/* +** Usage: sqlite3_bind_parameter_index STMT NAME +** +** Return the index of the wildcard called NAME. Return 0 if there is +** no such wildcard. +*/ +static int test_bind_parameter_index( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + + if( objc!=3 ){ + Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME"); + return TCL_ERROR; + } + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; + Tcl_SetObjResult(interp, + Tcl_NewIntObj( + sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2])) + ) + ); + return TCL_OK; +} + /* ** Usage: sqlite3_errcode DB ** @@ -2463,6 +2490,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_bind_blob", test_bind_blob ,0 }, { "sqlite3_bind_parameter_count", test_bind_parameter_count, 0}, { "sqlite3_bind_parameter_name", test_bind_parameter_name, 0}, + { "sqlite3_bind_parameter_index", test_bind_parameter_index, 0}, { "sqlite3_errcode", test_errcode ,0 }, { "sqlite3_errmsg", test_errmsg ,0 }, { "sqlite3_errmsg16", test_errmsg16 ,0 }, diff --git a/src/tokenize.c b/src/tokenize.c index f3bda60144..7601cf34e8 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -15,7 +15,7 @@ ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** -** $Id: tokenize.c,v 1.85 2004/09/06 17:24:13 drh Exp $ +** $Id: tokenize.c,v 1.86 2004/09/07 16:19:54 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -371,7 +371,8 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){ } case '?': { *tokenType = TK_VARIABLE; - return 1; + for(i=1; isdigit(z[i]); i++){} + return i; } case ':': { for(i=1; (z[i]&0x80)!=0 || isIdChar[z[i]]; i++){} @@ -474,7 +475,13 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ sqlite3SetString(pzErrMsg, "out of memory", (char*)0); return 1; } - pParse->sLastToken.dyn = 0; + assert( pParse->sLastToken.dyn==0 ); + assert( pParse->pNewTable==0 ); + assert( pParse->pNewTrigger==0 ); + assert( pParse->nVar==0 ); + assert( pParse->nVarExpr==0 ); + assert( pParse->nVarExprAlloc==0 ); + assert( pParse->apVarExpr==0 ); pParse->zTail = pParse->zSql = zSql; while( sqlite3_malloc_failed==0 && zSql[i]!=0 ){ assert( i>=0 ); @@ -541,14 +548,9 @@ abort_parse: sqlite3VdbeDelete(pParse->pVdbe); pParse->pVdbe = 0; } - if( pParse->pNewTable ){ - sqlite3DeleteTable(pParse->db, pParse->pNewTable); - pParse->pNewTable = 0; - } - if( pParse->pNewTrigger ){ - sqlite3DeleteTrigger(pParse->pNewTrigger); - pParse->pNewTrigger = 0; - } + sqlite3DeleteTable(pParse->db, pParse->pNewTable); + sqlite3DeleteTrigger(pParse->pNewTrigger); + sqliteFree(pParse->apVarExpr); if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){ pParse->rc = SQLITE_ERROR; } diff --git a/src/vdbeapi.c b/src/vdbeapi.c index b238c7fe79..f5abe0ee66 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -525,16 +525,11 @@ int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){ } /* -** Return the name of a wildcard parameter. Return NULL if the index -** is out of range or if the wildcard is unnamed. -** -** The result is always UTF-8. +** Create a mapping from variable numbers to variable names +** in the Vdbe.azVar[] array, if such a mapping does not already +** exist. */ -const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){ - Vdbe *p = (Vdbe*)pStmt; - if( p==0 || i<1 || i>p->nVar ){ - return 0; - } +static void createVarMap(Vdbe *p){ if( !p->okVar ){ int j; Op *pOp; @@ -546,5 +541,39 @@ const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){ } p->okVar = 1; } +} + +/* +** Return the name of a wildcard parameter. Return NULL if the index +** is out of range or if the wildcard is unnamed. +** +** The result is always UTF-8. +*/ +const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){ + Vdbe *p = (Vdbe*)pStmt; + if( p==0 || i<1 || i>p->nVar ){ + return 0; + } + createVarMap(p); return p->azVar[i-1]; } + +/* +** Given a wildcard parameter name, return the index of the variable +** with that name. If there is no variable with the given name, +** return 0. +*/ +int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){ + Vdbe *p = (Vdbe*)pStmt; + int i; + if( p==0 ){ + return 0; + } + createVarMap(p); + for(i=0; inVar; i++){ + if( strcmp(p->azVar[i],zName)==0 ){ + return i+1; + } + } + return 0; +} diff --git a/test/bind.test b/test/bind.test index d5ea33f67c..f1c4d4c6d0 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.18 2004/08/25 04:07:03 drh Exp $ +# $Id: bind.test,v 1.19 2004/09/07 16:19:54 drh Exp $ # set testdir [file dirname $argv0] @@ -115,6 +115,18 @@ do_test bind-2.1.3 { do_test bind-2.1.4 { sqlite3_bind_parameter_name $VM 3 } {${x}} +do_test bind-2.1.5 { + sqlite3_bind_parameter_index $VM {$one} +} 1 +do_test bind-2.1.6 { + sqlite3_bind_parameter_index $VM {$::two} +} 2 +do_test bind-2.1.7 { + sqlite3_bind_parameter_index $VM {${x}} +} 3 +do_test bind-2.1.8 { + sqlite3_bind_parameter_index $VM {:hi} +} 0 # 32 bit Integers do_test bind-2.2 { @@ -280,10 +292,98 @@ do_test bind-8.15 { catch { sqlite3_bind_double $VM 4 6.0 } } {1} -do_test bind-9.99 { +do_test bind-8.99 { sqlite3_finalize $VM } SQLITE_OK +do_test bind-9.1 { + execsql { + CREATE TABLE t2(a,b,c,d,e,f); + } + set rc [catch { + sqlite3_prepare $DB { + INSERT INTO t2(a) VALUES(?0) + } -1 TAIL + } msg] + lappend rc $msg +} {1 {(1) variable number must be between ?1 and ?999}} +do_test bind-9.2 { + set rc [catch { + sqlite3_prepare $DB { + INSERT INTO t2(a) VALUES(?1000) + } -1 TAIL + } msg] + lappend rc $msg +} {1 {(1) variable number must be between ?1 and ?999}} +do_test bind-9.3 { + set VM [ + sqlite3_prepare $DB { + INSERT INTO t2(a,b) VALUES(?1,?999) + } -1 TAIL + ] + sqlite3_bind_parameter_count $VM +} {999} +catch {sqlite3_finalize $VM} +do_test bind-9.4 { + set VM [ + sqlite3_prepare $DB { + INSERT INTO t2(a,b,c,d) VALUES(?1,?999,?,?) + } -1 TAIL + ] + sqlite3_bind_parameter_count $VM +} {1001} +do_test bind-9.5 { + sqlite3_bind_int $VM 1 1 + sqlite3_bind_int $VM 999 999 + sqlite3_bind_int $VM 1000 1000 + sqlite3_bind_int $VM 1001 1001 + sqlite3_step $VM +} SQLITE_DONE +do_test bind-9.6 { + sqlite3_finalize $VM +} SQLITE_OK +do_test bind-9.7 { + execsql {SELECT * FROM t2} +} {1 999 1000 1001 {} {}} +do_test bind-10.1 { + catch {sqlite3_finalize $VM} + set VM [ + sqlite3_prepare $DB { + INSERT INTO t2(a,b,c,d,e,f) VALUES(:abc,$abc,:abc,$ab,$abc,:abc) + } -1 TAIL + ] + sqlite3_bind_parameter_count $VM +} 3 +do_test bind-10.2 { + sqlite3_bind_parameter_index $VM :abc +} 1 +do_test bind-10.3 { + sqlite3_bind_parameter_index $VM {$abc} +} 2 +do_test bind-10.4 { + sqlite3_bind_parameter_index $VM {$ab} +} 3 +do_test bind-10.5 { + sqlite3_bind_parameter_name $VM 1 +} :abc +do_test bind-10.6 { + sqlite3_bind_parameter_name $VM 2 +} {$abc} +do_test bind-10.7 { + sqlite3_bind_parameter_name $VM 3 +} {$ab} +do_test bind-10.8 { + sqlite3_bind_int $VM 1 1 + sqlite3_bind_int $VM 2 2 + sqlite3_bind_int $VM 3 3 + sqlite3_step $VM +} SQLITE_DONE +do_test bind-10.9 { + sqlite3_finalize $VM +} SQLITE_OK +do_test bind-10.10 { + execsql {SELECT * FROM t2} +} {1 999 1000 1001 {} {} 1 2 1 3 2 1} finish_test diff --git a/www/capi3ref.tcl b/www/capi3ref.tcl index 34ad945e21..df36e807c9 100644 --- a/www/capi3ref.tcl +++ b/www/capi3ref.tcl @@ -1,4 +1,4 @@ -set rcsid {$Id: capi3ref.tcl,v 1.10 2004/08/28 16:19:01 drh Exp $} +set rcsid {$Id: capi3ref.tcl,v 1.11 2004/09/07 16:19:54 drh Exp $} source common.tcl header {C/C++ Interface For SQLite Version 3} puts { @@ -124,13 +124,22 @@ api {} { } { Return the name of the n-th wildcard in the precompiled statement. Wildcards of the form ":AAA" have a name which is the string ":AAA". - Wildcards of the form "?" have no name. + Wildcards of the form "?" or "?NNN" have no name. If the value n is out of range or if the n-th wildcard is nameless, then NULL is returned. The returned string is always in the UTF-8 encoding. } +api {} { + int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName); +} { + Return the index of the wildcard with the given name. + The name must match exactly. + If there is no wildcard with the given name, return 0. + The string zName is always in the UTF-8 encoding. +} + api {} { int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*); } {