/ Check-in [d3be0b7c]
Login
Overview
Comment:Add support for named wildcards in SQL statements. (CVS 1897)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:d3be0b7c5a39c02b9b2d6d85f1595d591984a569
User & Date: drh 2004-08-20 16:02:39
Context
2004-08-20
18:34
Tcl interface transfers values directly between SQLite and Tcl_Objs, without at translation to strings. (CVS 1898) check-in: e97c3313 user: drh tags: trunk
16:02
Add support for named wildcards in SQL statements. (CVS 1897) check-in: d3be0b7c user: drh tags: trunk
14:08
Optimizations in the hash table module. (CVS 1896) check-in: d5b0269e user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/expr.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
1158
1159
1160
1161
1162
1163
1164



1165
1166
1167
1168
1169
1170
1171
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.155 2004/08/08 23:39:19 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

char const *sqlite3AffinityString(char affinity){
  switch( affinity ){
    case SQLITE_AFF_INTEGER: return "i";
................................................................................
    }
    case TK_NULL: {
      sqlite3VdbeAddOp(v, OP_String8, 0, 0);
      break;
    }
    case TK_VARIABLE: {
      sqlite3VdbeAddOp(v, OP_Variable, pExpr->iTable, 0);



      break;
    }
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:







|







 







>
>
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.156 2004/08/20 16:02:39 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

char const *sqlite3AffinityString(char affinity){
  switch( affinity ){
    case SQLITE_AFF_INTEGER: return "i";
................................................................................
    }
    case TK_NULL: {
      sqlite3VdbeAddOp(v, OP_String8, 0, 0);
      break;
    }
    case TK_VARIABLE: {
      sqlite3VdbeAddOp(v, OP_Variable, pExpr->iTable, 0);
      if( pExpr->token.n>1 ){
        sqlite3VdbeChangeP3(v, -1, pExpr->token.z, pExpr->token.n);
      }
      break;
    }
    case TK_LT:
    case TK_LE:
    case TK_GT:
    case TK_GE:
    case TK_NE:

Changes to src/parse.y.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
554
555
556
557
558
559
560

561





562


563
564
565
566
567
568
569
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.133 2004/08/19 15:12:26 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  if( pParse->zErrMsg==0 ){
................................................................................
  A = sqlite3Expr(TK_DOT, temp1, temp4, 0);
}
expr(A) ::= INTEGER(X).      {A = sqlite3Expr(@X, 0, 0, &X);}
expr(A) ::= FLOAT(X).        {A = sqlite3Expr(@X, 0, 0, &X);}
expr(A) ::= STRING(X).       {A = sqlite3Expr(@X, 0, 0, &X);}
expr(A) ::= BLOB(X).         {A = sqlite3Expr(@X, 0, 0, &X);}
expr(A) ::= VARIABLE(X).     {

  A = sqlite3Expr(TK_VARIABLE, 0, 0, &X);





  if( A ) A->iTable = ++pParse->nVar;


}
expr(A) ::= ID(X) LP exprlist(Y) RP(E). {
  A = sqlite3ExprFunction(Y, &X);
  sqlite3ExprSpan(A,&X,&E);
}
expr(A) ::= ID(X) LP STAR RP(E). {
  A = sqlite3ExprFunction(0, &X);







|







 







>
|
>
>
>
>
>
|
>
>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.134 2004/08/20 16:02:39 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  if( pParse->zErrMsg==0 ){
................................................................................
  A = sqlite3Expr(TK_DOT, temp1, temp4, 0);
}
expr(A) ::= INTEGER(X).      {A = sqlite3Expr(@X, 0, 0, &X);}
expr(A) ::= FLOAT(X).        {A = sqlite3Expr(@X, 0, 0, &X);}
expr(A) ::= STRING(X).       {A = sqlite3Expr(@X, 0, 0, &X);}
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 ){
    if( pToken->z[0]==':' ){
      int n = pExpr->iTable = atoi(&pToken->z[1]);
      if( pParse->nVar<n ) pParse->nVar = n;
    }else{
      pExpr->iTable = ++pParse->nVar;
    }
  }
}
expr(A) ::= ID(X) LP exprlist(Y) RP(E). {
  A = sqlite3ExprFunction(Y, &X);
  sqlite3ExprSpan(A,&X,&E);
}
expr(A) ::= ID(X) LP STAR RP(E). {
  A = sqlite3ExprFunction(0, &X);

Changes to src/sqlite.h.in.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
628
629
630
631
632
633
634
635
636
637
638
639








640
641
642
643
644
645
646
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the SQLite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.113 2004/08/14 17:10:12 drh Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);

/*
** Return the number of wildcards in a compiled SQL statement.  This
** routine was added to support DBD::SQLite.
**
**** EXPERIMENTAL *****
*/
int sqlite3_bind_parameter_count(sqlite3_stmt*);









/*
** 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
** that does not return data (for example an UPDATE).
*/
int sqlite3_column_count(sqlite3_stmt *pStmt);








|







 







<
<



>
>
>
>
>
>
>
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
628
629
630
631
632
633
634


635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the SQLite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.114 2004/08/20 16:02:39 drh Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
int sqlite3_bind_text(sqlite3_stmt*, int, const char*, int n, void(*)(void*));
int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);

/*
** Return the number of wildcards in a compiled SQL statement.  This
** routine was added to support DBD::SQLite.


*/
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
** $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 number of columns in the result set returned by the compiled
** SQL statement. This routine returns 0 if pStmt is an SQL statement
** that does not return data (for example an UPDATE).
*/
int sqlite3_column_count(sqlite3_stmt *pStmt);

Changes to src/tclsqlite.c.

7
8
9
10
11
12
13
14
15
16
17
18

19
20
21
22
23
24
25
..
54
55
56
57
58
59
60

61
62
63
64
65
66
67
68
69
70
71
72

73
74
75
76
77
78
79
80


81
82
83
84
85
86
87
88
89
90
91
92
93
94
...
113
114
115
116
117
118
119

120
121
122
123






124
125
126
127
128
129
130
...
276
277
278
279
280
281
282

283
284
285
286
287
288
289
...
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
...
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** A TCL Interface to SQLite
**
** $Id: tclsqlite.c,v 1.98 2004/07/26 12:24:23 drh Exp $
*/
#ifndef NO_TCL     /* Omit this whole file if TCL is unavailable */

#include "sqliteInt.h"

#include "tcl.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>

/*
** If TCL uses UTF-8 and SQLite is configured to use iso8859, then we
................................................................................
};

/*
** There is one instance of this structure for each SQLite database
** that has been opened by the SQLite TCL interface.
*/
typedef struct SqliteDb SqliteDb;

struct SqliteDb {
  sqlite *db;           /* The "real" database structure */
  Tcl_Interp *interp;   /* The interpreter used for this database */
  char *zBusy;          /* The busy callback routine */
  char *zCommit;        /* The commit hook callback routine */
  char *zTrace;         /* The trace callback routine */
  char *zProgress;      /* The progress callback routine */
  char *zAuth;          /* The authorization callback routine */
  SqlFunc *pFunc;       /* List of SQL functions */
  SqlCollate *pCollate; /* List of SQL collation functions */
  int rc;               /* Return code of most recent sqlite3_exec() */
  Tcl_Obj *pCollateNeeded;  /* Collation needed script */

};

/*
** An instance of this structure passes information thru the sqlite
** logic from the original TCL command into the callback routine.
*/
typedef struct CallbackData CallbackData;
struct CallbackData {


  Tcl_Interp *interp;       /* The TCL interpreter */
  char *zArray;             /* The array into which data is written */
  Tcl_Obj *pCode;           /* The code to execute for each row */
  int once;                 /* Set for first callback only */
  int tcl_rc;               /* Return code from TCL script */
  int nColName;             /* Number of entries in the azColName[] array */
  char **azColName;         /* Column names translated to UTF-8 */
};

/*
** This is a second alternative callback for database queries.  A the
** first column of the first row of the result is made the TCL result.
*/
static int DbEvalCallback3(
................................................................................
  pElem = Tcl_NewStringObj(azCol[0], -1);
#endif
  Tcl_SetObjResult(interp, pElem);
  return 1;
}

/*

** Called when the command is deleted.
*/
static void DbDeleteCmd(void *db){
  SqliteDb *pDb = (SqliteDb*)db;






  sqlite3_close(pDb->db);
  while( pDb->pFunc ){
    SqlFunc *pFunc = pDb->pFunc;
    pDb->pFunc = pFunc->pNext;
    Tcl_Free((char*)pFunc);
  }
  while( pDb->pCollate ){
................................................................................
  if( rc ){
    sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1); 
  }else{
    sqlite3_result_text(context, Tcl_GetStringResult(p->interp), -1, 
        SQLITE_TRANSIENT);
  }
}

#ifndef SQLITE_OMIT_AUTHORIZATION
/*
** This is the authentication function.  It appends the authentication
** type code and the two arguments to zCmd[] then invokes the result
** on the interpreter.  The reply is examined to determine if the
** authentication fails or succeeds.
*/
................................................................................
  */
  case DB_ERRORCODE: {
    Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_errcode(pDb->db)));
    break;
  }
   
  /*
  **    $db eval $sql ?array {  ...code... }?
  **
  ** The SQL statement in $sql is evaluated.  For each row, the values are
  ** placed in elements of the array named "array" and ...code... is executed.
  ** If "array" and "code" are omitted, then no callback is every invoked.
  ** If "array" is an empty string, then the values are placed in variables
  ** that have the same name as the fields extracted by the query.
  */
................................................................................
    char const *zSql;
    char const *zLeft;
    sqlite3_stmt *pStmt;

    Tcl_Obj *pRet = Tcl_NewObj();
    Tcl_IncrRefCount(pRet);

    if( objc!=5 && objc!=3 ){
      Tcl_WrongNumArgs(interp, 2, objv, "SQL ?ARRAY-NAME CODE?");
      return TCL_ERROR;
    }

    zSql = Tcl_GetStringFromObj(objv[2], 0);
    while( zSql[0] ){
      int i;
  







|




>







 







>

|










>



|
<

<
|
>
>
|
|
|
|
<
<
<







 







>
|



>
>
>
>
>
>







 







>







 







|







 







|
|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
..
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

80

81
82
83
84
85
86
87



88
89
90
91
92
93
94
...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
...
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
...
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** A TCL Interface to SQLite
**
** $Id: tclsqlite.c,v 1.99 2004/08/20 16:02:39 drh Exp $
*/
#ifndef NO_TCL     /* Omit this whole file if TCL is unavailable */

#include "sqliteInt.h"
#include "hash.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>

/*
** If TCL uses UTF-8 and SQLite is configured to use iso8859, then we
................................................................................
};

/*
** There is one instance of this structure for each SQLite database
** that has been opened by the SQLite TCL interface.
*/
typedef struct SqliteDb SqliteDb;
typedef struct SqlStmt SqlStmt;
struct SqliteDb {
  sqlite3 *db;          /* The "real" database structure */
  Tcl_Interp *interp;   /* The interpreter used for this database */
  char *zBusy;          /* The busy callback routine */
  char *zCommit;        /* The commit hook callback routine */
  char *zTrace;         /* The trace callback routine */
  char *zProgress;      /* The progress callback routine */
  char *zAuth;          /* The authorization callback routine */
  SqlFunc *pFunc;       /* List of SQL functions */
  SqlCollate *pCollate; /* List of SQL collation functions */
  int rc;               /* Return code of most recent sqlite3_exec() */
  Tcl_Obj *pCollateNeeded;  /* Collation needed script */
  SqlStmt *pStmtList;   /* List of all prepared statements */
};

/*
** Each prepared statement is an instance of the following structure.

*/

struct SqlStmt {
  SqliteDb *pDb;        /* The database that this statement is part of */
  SqlStmt *pAll;        /* Next statement in list of all for pDb */
  SqlStmt **ppPrev;     /* Previous pAll pointer */
  sqlite3_stmt *pVm;    /* Compiled statement. */
  int nBind;            /* Number of bindings in this statement */
  char *azBindVar[1];   /* Name of variables for each binding */



};

/*
** This is a second alternative callback for database queries.  A the
** first column of the first row of the result is made the TCL result.
*/
static int DbEvalCallback3(
................................................................................
  pElem = Tcl_NewStringObj(azCol[0], -1);
#endif
  Tcl_SetObjResult(interp, pElem);
  return 1;
}

/*
** TCL calls this procedure when an sqlite3 database command is
** deleted.
*/
static void DbDeleteCmd(void *db){
  SqliteDb *pDb = (SqliteDb*)db;
  SqlStmt *pStmt, *pNextStmt;
  for(pStmt=pDb->pStmtList; pStmt; pStmt=pNextStmt){
    pNextStmt = pStmt->pAll;
    sqlite3_finalize(pStmt->pVm);
    Tcl_Free(pStmt);
  }
  sqlite3_close(pDb->db);
  while( pDb->pFunc ){
    SqlFunc *pFunc = pDb->pFunc;
    pDb->pFunc = pFunc->pNext;
    Tcl_Free((char*)pFunc);
  }
  while( pDb->pCollate ){
................................................................................
  if( rc ){
    sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1); 
  }else{
    sqlite3_result_text(context, Tcl_GetStringResult(p->interp), -1, 
        SQLITE_TRANSIENT);
  }
}

#ifndef SQLITE_OMIT_AUTHORIZATION
/*
** This is the authentication function.  It appends the authentication
** type code and the two arguments to zCmd[] then invokes the result
** on the interpreter.  The reply is examined to determine if the
** authentication fails or succeeds.
*/
................................................................................
  */
  case DB_ERRORCODE: {
    Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_errcode(pDb->db)));
    break;
  }
   
  /*
  **    $db eval $sql ?array? ?{  ...code... }?
  **
  ** The SQL statement in $sql is evaluated.  For each row, the values are
  ** placed in elements of the array named "array" and ...code... is executed.
  ** If "array" and "code" are omitted, then no callback is every invoked.
  ** If "array" is an empty string, then the values are placed in variables
  ** that have the same name as the fields extracted by the query.
  */
................................................................................
    char const *zSql;
    char const *zLeft;
    sqlite3_stmt *pStmt;

    Tcl_Obj *pRet = Tcl_NewObj();
    Tcl_IncrRefCount(pRet);

    if( objc<3 || objc>5 || objc==4 ){
      Tcl_WrongNumArgs(interp, 2, objv, "SQL ?ARRAY-NAME? ?SCRIPT?");
      return TCL_ERROR;
    }

    zSql = Tcl_GetStringFromObj(objv[2], 0);
    while( zSql[0] ){
      int i;
  

Changes to src/test1.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
....
1612
1613
1614
1615
1616
1617
1618




























1619
1620
1621
1622
1623
1624
1625
....
2405
2406
2407
2408
2409
2410
2411

2412
2413
2414
2415
2416
2417
2418
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the printf() interface to SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.97 2004/08/14 17:10:12 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

................................................................................
    Tcl_WrongNumArgs(interp, 1, objv, "STMT");
    return TCL_ERROR;
  }
  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt)));
  return TCL_OK;
}





























/*
** Usage: sqlite3_errcode DB
**
** Return the string representation of the most recent sqlite3_* API
** error code. e.g. "SQLITE_ERROR".
*/
................................................................................
     { "sqlite3_bind_int64",            test_bind_int64,    0 },
     { "sqlite3_bind_double",           test_bind_double,   0 },
     { "sqlite3_bind_null",             test_bind_null     ,0 },
     { "sqlite3_bind_text",             test_bind_text     ,0 },
     { "sqlite3_bind_text16",           test_bind_text16   ,0 },
     { "sqlite3_bind_blob",             test_bind_blob     ,0 },
     { "sqlite3_bind_parameter_count",  test_bind_parameter_count, 0},

     { "sqlite3_errcode",               test_errcode       ,0 },
     { "sqlite3_errmsg",                test_errmsg        ,0 },
     { "sqlite3_errmsg16",              test_errmsg16      ,0 },
     { "sqlite3_open",                  test_open          ,0 },
     { "sqlite3_open16",                test_open16        ,0 },
     { "sqlite3_complete16",            test_complete16    ,0 },








|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
....
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
....
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the printf() interface to SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.98 2004/08/20 16:02:39 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

................................................................................
    Tcl_WrongNumArgs(interp, 1, objv, "STMT");
    return TCL_ERROR;
  }
  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt)));
  return TCL_OK;
}

/*
** Usage:   sqlite3_bind_parameter_name  STMT  N
**
** Return the name of the Nth wildcard.  The first wildcard is 1.
** An empty string is returned if N is out of range or if the wildcard
** is nameless.
*/
static int test_bind_parameter_name(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3_stmt *pStmt;
  int i;

  if( objc!=3 ){
    Tcl_WrongNumArgs(interp, 1, objv, "STMT N");
    return TCL_ERROR;
  }
  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
  if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR;
  Tcl_SetObjResult(interp, 
     Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1)
  );
  return TCL_OK;
}

/*
** Usage: sqlite3_errcode DB
**
** Return the string representation of the most recent sqlite3_* API
** error code. e.g. "SQLITE_ERROR".
*/
................................................................................
     { "sqlite3_bind_int64",            test_bind_int64,    0 },
     { "sqlite3_bind_double",           test_bind_double,   0 },
     { "sqlite3_bind_null",             test_bind_null     ,0 },
     { "sqlite3_bind_text",             test_bind_text     ,0 },
     { "sqlite3_bind_text16",           test_bind_text16   ,0 },
     { "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_errcode",               test_errcode       ,0 },
     { "sqlite3_errmsg",                test_errmsg        ,0 },
     { "sqlite3_errmsg16",              test_errmsg16      ,0 },
     { "sqlite3_open",                  test_open          ,0 },
     { "sqlite3_open16",                test_open16        ,0 },
     { "sqlite3_complete16",            test_complete16    ,0 },

Changes to src/tokenize.c.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
...
369
370
371
372
373
374
375
















































376
377
378
379
380
381
382
*************************************************************************
** An tokenizer for SQL
**
** This file contains C code that splits an SQL input string up into
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
** $Id: tokenize.c,v 1.81 2004/08/08 23:39:19 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include <stdlib.h>

/*
................................................................................
      *tokenType = TK_ID;
      return i;
    }
    case '?': {
      *tokenType = TK_VARIABLE;
      return 1;
    }
















































    case 'x': case 'X': {
      if( z[1]=='\'' || z[1]=='"' ){
        int delim = z[1];
        *tokenType = TK_BLOB;
        for(i=2; z[i]; i++){
          if( z[i]==delim ){
            if( i%2 ) *tokenType = TK_ILLEGAL;







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
...
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
*************************************************************************
** An tokenizer for SQL
**
** This file contains C code that splits an SQL input string up into
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
** $Id: tokenize.c,v 1.82 2004/08/20 16:02:39 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include <stdlib.h>

/*
................................................................................
      *tokenType = TK_ID;
      return i;
    }
    case '?': {
      *tokenType = TK_VARIABLE;
      return 1;
    }
    case ':': {
      for(i=1; isdigit(z[i]); i++){}
      if( i>1 && z[i]==':' ){
        *tokenType = TK_VARIABLE;
        return i+1;
      }else{
        *tokenType = TK_ILLEGAL;
        return i;
      }
    }
    case '$': {
      int c;
      if( z[1]=='{' ){
        int nBrace = 1;
        for(i=2; (c=z[i])!=0 && nBrace; i++){
          if( c=='{' ){
            nBrace++;
          }else if( c=='}' ){
            nBrace--;
          }
        }
        *tokenType = c!=0 ? TK_VARIABLE : TK_ILLEGAL;
      }else{
        int n = 0;
        for(i=1; (c=z[i])!=0; i++){
          if( isalnum(c) || c=='_' ){
            n++;
          }else if( c=='(' && n>0 ){
            do{
              i++;
            }while( (c=z[i])!=0 && !isspace(c) && c!=')' );
            if( c==')' ){
              i++;
              *tokenType = TK_VARIABLE;
            }else{
              *tokenType = TK_ILLEGAL;
            }
            break;
          }else if( c==':' && z[i+1]==':' ){
            i++;
          }else{
            *tokenType = n==0 ? TK_ILLEGAL : TK_VARIABLE;
            break;
          }
        }
      }
      return i;
    } 
    case 'x': case 'X': {
      if( z[1]=='\'' || z[1]=='"' ){
        int delim = z[1];
        *tokenType = TK_BLOB;
        for(i=2; z[i]; i++){
          if( z[i]==delim ){
            if( i%2 ) *tokenType = TK_ILLEGAL;

Changes to src/vdbeInt.h.

312
313
314
315
316
317
318


319
320
321
322
323
324
325
  Cursor **apCsr;     /* One element of this array for each open cursor */
  Sorter *pSort;      /* A linked list of objects to be sorted */
  FILE *pFile;        /* At most one open file handler */
  int nField;         /* Number of file fields */
  char **azField;     /* Data for each file field */
  int nVar;           /* Number of entries in apVar[] */
  Mem *apVar;         /* Values for the OP_Variable opcode. */


  char *zLine;            /* A single line from the input file */
  int nLineAlloc;         /* Number of spaces allocated for zLine */
  int magic;              /* Magic number for sanity checking */
  int nMem;               /* Number of memory locations currently allocated */
  Mem *aMem;              /* The memory locations */
  Agg agg;                /* Aggregate information */
  int nCallback;          /* Number of callbacks invoked so far */







>
>







312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
  Cursor **apCsr;     /* One element of this array for each open cursor */
  Sorter *pSort;      /* A linked list of objects to be sorted */
  FILE *pFile;        /* At most one open file handler */
  int nField;         /* Number of file fields */
  char **azField;     /* Data for each file field */
  int nVar;           /* Number of entries in apVar[] */
  Mem *apVar;         /* Values for the OP_Variable opcode. */
  char **azVar;       /* Name of variables */
  int okVar;          /* True if azVar[] has been initialized */
  char *zLine;            /* A single line from the input file */
  int nLineAlloc;         /* Number of spaces allocated for zLine */
  int magic;              /* Magic number for sanity checking */
  int nMem;               /* Number of memory locations currently allocated */
  Mem *aMem;              /* The memory locations */
  Agg agg;                /* Aggregate information */
  int nCallback;          /* Number of callbacks invoked so far */

Changes to src/vdbeapi.c.

514
515
516
517
518
519
520
521
522
523
524
525
526

























  rc = sqlite3VdbeChangeEncoding(pVar, p->db->enc);
  return rc;
}

/*
** Return the number of wildcards that can be potentially bound to.
** This routine is added to support DBD::SQLite.  
**
******** EXPERIMENTAL *******
*/
int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
  return ((Vdbe*)pStmt)->nVar;
}
































<
<




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
514
515
516
517
518
519
520


521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
  rc = sqlite3VdbeChangeEncoding(pVar, p->db->enc);
  return rc;
}

/*
** Return the number of wildcards that can be potentially bound to.
** This routine is added to support DBD::SQLite.  


*/
int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
  return ((Vdbe*)pStmt)->nVar;
}

/*
** 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( i<1 || i>p->nVar ){
    return 0;
  }
  if( !p->okVar ){
    int j;
    Op *pOp;
    for(j=0, pOp=p->aOp; j<p->nOp; j++, pOp++){
      if( pOp->opcode==OP_Variable ){
        assert( pOp->p1>0 && pOp->p1<=p->nVar );
        p->azVar[pOp->p1-1] = pOp->p3;
      }
    }
    p->okVar = 1;
  }
  return p->azVar[i-1];
}

Changes to src/vdbeaux.c.

570
571
572
573
574
575
576

577
578
579


580
581
582
583
584
585
586
  if( p->aStack==0 ){
    p->nVar = nVar;
    assert( nVar>=0 );
    n = isExplain ? 10 : p->nOp;
    p->aStack = sqliteMalloc(
      n*(sizeof(p->aStack[0])+sizeof(Mem*))          /* aStack, apArg */
      + p->nVar*sizeof(Mem)                          /* apVar */

    );
    p->apArg = (Mem **)&p->aStack[n];
    p->apVar = (Mem *)&p->apArg[n];


    for(n=0; n<p->nVar; n++){
      p->apVar[n].flags = MEM_Null;
    }
  }

#ifdef SQLITE_DEBUG
  if( (p->db->flags & SQLITE_VdbeListing)!=0







>



>
>







570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
  if( p->aStack==0 ){
    p->nVar = nVar;
    assert( nVar>=0 );
    n = isExplain ? 10 : p->nOp;
    p->aStack = sqliteMalloc(
      n*(sizeof(p->aStack[0])+sizeof(Mem*))          /* aStack, apArg */
      + p->nVar*sizeof(Mem)                          /* apVar */
      + p->nVar*sizeof(char*)                        /* apVarName */
    );
    p->apArg = (Mem **)&p->aStack[n];
    p->apVar = (Mem *)&p->apArg[n];
    p->azVar = (char**)&p->apVar[p->nVar];
    p->okVar = 0;
    for(n=0; n<p->nVar; n++){
      p->apVar[n].flags = MEM_Null;
    }
  }

#ifdef SQLITE_DEBUG
  if( (p->db->flags & SQLITE_VdbeListing)!=0

Changes to test/bind.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
34
35
36
37
38
39
40
41
42
43
44
45
46









47
48
49
50
51
52
53
..
87
88
89
90
91
92
93
94
95
96












97
98
99
100
101
102
103
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script testing the sqlite_bind API.
#
# $Id: bind.test,v 1.15 2004/07/15 14:15:02 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

proc sqlite_step {stmt N VALS COLS} {
  upvar VALS vals
................................................................................
  return $rc
}

do_test bind-1.1 {
  db close
  set DB [sqlite3 db test.db]
  execsql {CREATE TABLE t1(a,b,c)}
  set VM [sqlite3_prepare $DB {INSERT INTO t1 VALUES(?,?,?)} -1 TAIL]
  set TAIL
} {}
do_test bind-1.1.1 {
  sqlite3_bind_parameter_count $VM
} 3









do_test bind-1.2 {
  sqlite_step $VM N VALUES COLNAMES
} {SQLITE_DONE}
do_test bind-1.3 {
  execsql {SELECT rowid, * FROM t1}
} {1 {} {} {}}
do_test bind-1.4 {
................................................................................
  sqlite3_finalize $VM
} SQLITE_OK

do_test bind-2.1 {
  execsql {
    DELETE FROM t1;
  }
  set VM [sqlite3_prepare $DB {INSERT INTO t1 VALUES(?,?,?)} -1 TAIL]
  set TAIL
} {}













# 32 bit Integers
do_test bind-2.2 {
  sqlite3_bind_int $VM 1 123
  sqlite3_bind_int $VM 2 456
  sqlite3_bind_int $VM 3 789
  sqlite_step $VM N VALUES COLNAMES







|







 







|





>
>
>
>
>
>
>
>
>







 







|


>
>
>
>
>
>
>
>
>
>
>
>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
..
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script testing the sqlite_bind API.
#
# $Id: bind.test,v 1.16 2004/08/20 16:02:39 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

proc sqlite_step {stmt N VALS COLS} {
  upvar VALS vals
................................................................................
  return $rc
}

do_test bind-1.1 {
  db close
  set DB [sqlite3 db test.db]
  execsql {CREATE TABLE t1(a,b,c)}
  set VM [sqlite3_prepare $DB {INSERT INTO t1 VALUES(:1:,?,:3:)} -1 TAIL]
  set TAIL
} {}
do_test bind-1.1.1 {
  sqlite3_bind_parameter_count $VM
} 3
do_test bind-1.1.2 {
  sqlite3_bind_parameter_name $VM 1
} {:1:}
do_test bind-1.1.3 {
  sqlite3_bind_parameter_name $VM 2
} {}
do_test bind-1.1.4 {
  sqlite3_bind_parameter_name $VM 3
} {:3:}
do_test bind-1.2 {
  sqlite_step $VM N VALUES COLNAMES
} {SQLITE_DONE}
do_test bind-1.3 {
  execsql {SELECT rowid, * FROM t1}
} {1 {} {} {}}
do_test bind-1.4 {
................................................................................
  sqlite3_finalize $VM
} SQLITE_OK

do_test bind-2.1 {
  execsql {
    DELETE FROM t1;
  }
  set VM [sqlite3_prepare $DB {INSERT INTO t1 VALUES($one,$::two,${x})} -1 TAIL]
  set TAIL
} {}
do_test bind-2.1.1 {
  sqlite3_bind_parameter_count $VM
} 3
do_test bind-2.1.2 {
  sqlite3_bind_parameter_name $VM 1
} {$one}
do_test bind-2.1.3 {
  sqlite3_bind_parameter_name $VM 2
} {$::two}
do_test bind-2.1.4 {
  sqlite3_bind_parameter_name $VM 3
} {${x}}

# 32 bit Integers
do_test bind-2.2 {
  sqlite3_bind_int $VM 1 123
  sqlite3_bind_int $VM 2 456
  sqlite3_bind_int $VM 3 789
  sqlite_step $VM N VALUES COLNAMES

Changes to test/tclsqlite.test.

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
..
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# This file implements regression tests for TCL interface to the
# SQLite library. 
#
# Actually, all tests are based on the TCL interface, so the main
# interface is pretty well tested.  This file contains some addition
# tests for fringe issues that the main test suite does not cover.
#
# $Id: tclsqlite.test,v 1.28 2004/07/26 12:24:24 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Check the error messages generated by tclsqlite
#
if {[sqlite3 -has-codec]} {
................................................................................
do_test tcl-1.13 {
  set v [catch {db complete} msg]
  lappend v $msg
} {1 {wrong # args: should be "db complete SQL"}}
do_test tcl-1.14 {
  set v [catch {db eval} msg]
  lappend v $msg
} {1 {wrong # args: should be "db eval SQL ?ARRAY-NAME CODE?"}}
do_test tcl-1.15 {
  set v [catch {db function} msg]
  lappend v $msg
} {1 {wrong # args: should be "db function NAME SCRIPT"}}
do_test tcl-1.14 {
  set v [catch {db last_insert_rowid xyz} msg]
  lappend v $msg







|







 







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
..
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# This file implements regression tests for TCL interface to the
# SQLite library. 
#
# Actually, all tests are based on the TCL interface, so the main
# interface is pretty well tested.  This file contains some addition
# tests for fringe issues that the main test suite does not cover.
#
# $Id: tclsqlite.test,v 1.29 2004/08/20 16:02:39 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Check the error messages generated by tclsqlite
#
if {[sqlite3 -has-codec]} {
................................................................................
do_test tcl-1.13 {
  set v [catch {db complete} msg]
  lappend v $msg
} {1 {wrong # args: should be "db complete SQL"}}
do_test tcl-1.14 {
  set v [catch {db eval} msg]
  lappend v $msg
} {1 {wrong # args: should be "db eval SQL ?ARRAY-NAME? ?SCRIPT?"}}
do_test tcl-1.15 {
  set v [catch {db function} msg]
  lappend v $msg
} {1 {wrong # args: should be "db function NAME SCRIPT"}}
do_test tcl-1.14 {
  set v [catch {db last_insert_rowid xyz} msg]
  lappend v $msg

Changes to www/capi3ref.tcl.

1
2
3
4
5
6
7
8
..
98
99
100
101
102
103
104



















105
106
107
108
109
110
111
set rcsid {$Id: capi3ref.tcl,v 1.7 2004/07/22 15:45:16 drh Exp $}
source common.tcl
header {C/C++ Interface For SQLite Version 3}
puts {
<h2>C/C++ Interface For SQLite Version 3</h2>
}

proc api {name prototype desc {notused x}} {
................................................................................
 own private copy of the data.

 The sqlite3_bind_*() routine must be called after
 sqlite3_prepare() or sqlite3_reset() and before sqlite3_step().
 Bindings are not reset by the sqlite3_reset() routine.
 Unbound wildcards are interpreted as NULL.
}




















api {} {
  int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
} {
 This routine identifies a callback function that is invoked
 whenever an attempt is made to open a database table that is
 currently locked by another process or thread.  If the busy callback
|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
..
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
set rcsid {$Id: capi3ref.tcl,v 1.8 2004/08/20 16:02:40 drh Exp $}
source common.tcl
header {C/C++ Interface For SQLite Version 3}
puts {
<h2>C/C++ Interface For SQLite Version 3</h2>
}

proc api {name prototype desc {notused x}} {
................................................................................
 own private copy of the data.

 The sqlite3_bind_*() routine must be called after
 sqlite3_prepare() or sqlite3_reset() and before sqlite3_step().
 Bindings are not reset by the sqlite3_reset() routine.
 Unbound wildcards are interpreted as NULL.
}

api {} {
  int sqlite3_bind_parameter_count(sqlite3_stmt*);
} {
  Return the number of wildcards in the precompiled statement given as
  the argument.
}

api {} {
  const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int n);
} {
  Return the name of the n-th wildcard in the precompiled statement.
  Wildcards of the form ":N:" have a name which is the string ":N:".
  Wildcards of the form "?" 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_busy_handler(sqlite3*, int(*)(void*,int), void*);
} {
 This routine identifies a callback function that is invoked
 whenever an attempt is made to open a database table that is
 currently locked by another process or thread.  If the busy callback