blob: 959a9f74799bd2f2f2185dca392e1feb86a72993 [file] [log] [blame]
drhd1bf3512001-04-07 15:24:33 +00001/*
drhb19a2bc2001-09-16 00:13:26 +00002** 2001 September 15
drhd1bf3512001-04-07 15:24:33 +00003**
drhb19a2bc2001-09-16 00:13:26 +00004** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
drhd1bf3512001-04-07 15:24:33 +00006**
drhb19a2bc2001-09-16 00:13:26 +00007** May you do good and not evil.
8** May you find forgiveness for yourself and forgive others.
9** May you share freely, never taking more than you give.
drhd1bf3512001-04-07 15:24:33 +000010**
11*************************************************************************
12** Code for testing the printf() interface to SQLite. This code
13** is not included in the SQLite library. It is used for automated
14** testing of the SQLite library.
15**
danielk1977106bb232004-05-21 10:08:53 +000016** $Id: test1.c,v 1.45 2004/05/21 10:08:54 danielk1977 Exp $
drhd1bf3512001-04-07 15:24:33 +000017*/
18#include "sqliteInt.h"
19#include "tcl.h"
drh94e92032003-02-16 22:21:32 +000020#include "os.h"
drhd1bf3512001-04-07 15:24:33 +000021#include <stdlib.h>
22#include <string.h>
23
drh94e92032003-02-16 22:21:32 +000024#if OS_WIN
25# define PTR_FMT "%x"
26#else
27# define PTR_FMT "%p"
28#endif
29
danielk19776622cce2004-05-20 11:00:52 +000030static const char * errorName(int rc){
31 const char *zName = 0;
32 switch( rc ){
33 case SQLITE_OK: zName = "SQLITE_OK"; break;
34 case SQLITE_ERROR: zName = "SQLITE_ERROR"; break;
35 case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break;
36 case SQLITE_PERM: zName = "SQLITE_PERM"; break;
37 case SQLITE_ABORT: zName = "SQLITE_ABORT"; break;
38 case SQLITE_BUSY: zName = "SQLITE_BUSY"; break;
39 case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break;
40 case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break;
41 case SQLITE_READONLY: zName = "SQLITE_READONLY"; break;
42 case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break;
43 case SQLITE_IOERR: zName = "SQLITE_IOERR"; break;
44 case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break;
45 case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break;
46 case SQLITE_FULL: zName = "SQLITE_FULL"; break;
47 case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break;
48 case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
49 case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break;
50 case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break;
51 case SQLITE_TOOBIG: zName = "SQLITE_TOOBIG"; break;
52 case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break;
53 case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break;
54 case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break;
55 case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break;
56 case SQLITE_AUTH: zName = "SQLITE_AUTH"; break;
57 case SQLITE_FORMAT: zName = "SQLITE_FORMAT"; break;
58 case SQLITE_RANGE: zName = "SQLITE_RANGE"; break;
59 case SQLITE_ROW: zName = "SQLITE_ROW"; break;
60 case SQLITE_DONE: zName = "SQLITE_DONE"; break;
61 default: zName = "SQLITE_Unknown"; break;
62 }
63 return zName;
64}
65
drhd1bf3512001-04-07 15:24:33 +000066/*
drhb86ccfb2003-01-28 23:13:10 +000067** Decode a pointer to an sqlite object.
68*/
drh90f405e2003-12-23 03:06:23 +000069static int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite **ppDb){
70 if( sscanf(zA, PTR_FMT, (void**)ppDb)!=1 &&
71 (zA[0]!='0' || zA[1]!='x' || sscanf(&zA[2], PTR_FMT, (void**)ppDb)!=1)
72 ){
73 Tcl_AppendResult(interp, "\"", zA, "\" is not a valid pointer value", 0);
drhb86ccfb2003-01-28 23:13:10 +000074 return TCL_ERROR;
75 }
76 return TCL_OK;
77}
78
79/*
80** Decode a pointer to an sqlite_vm object.
81*/
82static int getVmPointer(Tcl_Interp *interp, const char *zArg, sqlite_vm **ppVm){
drh94e92032003-02-16 22:21:32 +000083 if( sscanf(zArg, PTR_FMT, (void**)ppVm)!=1 ){
drhb86ccfb2003-01-28 23:13:10 +000084 Tcl_AppendResult(interp, "\"", zArg, "\" is not a valid pointer value", 0);
85 return TCL_ERROR;
86 }
87 return TCL_OK;
88}
89
90/*
danielk197751e3d8e2004-05-20 01:12:34 +000091** Decode a pointer to an sqlite3_stmt object.
92*/
93static int getStmtPointer(
94 Tcl_Interp *interp,
95 const char *zArg,
96 sqlite3_stmt **ppStmt
97){
98 if( sscanf(zArg, PTR_FMT, (void**)ppStmt)!=1 ){
99 Tcl_AppendResult(interp, "\"", zArg, "\" is not a valid pointer value", 0);
100 return TCL_ERROR;
101 }
102 return TCL_OK;
103}
104
105/*
drh7d8085a2003-04-26 13:19:38 +0000106** Generate a text representation of a pointer that can be understood
107** by the getDbPointer and getVmPointer routines above.
108**
109** The problem is, on some machines (Solaris) if you do a printf with
110** "%p" you cannot turn around and do a scanf with the same "%p" and
111** get your pointer back. You have to prepend a "0x" before it will
112** work. Or at least that is what is reported to me (drh). But this
113** behavior varies from machine to machine. The solution used her is
114** to test the string right after it is generated to see if it can be
115** understood by scanf, and if not, try prepending an "0x" to see if
116** that helps. If nothing works, a fatal error is generated.
117*/
118static int makePointerStr(Tcl_Interp *interp, char *zPtr, void *p){
119 void *p2;
120 sprintf(zPtr, PTR_FMT, p);
121 if( sscanf(zPtr, PTR_FMT, &p2)!=1 || p2!=p ){
122 sprintf(zPtr, "0x" PTR_FMT, p);
123 if( sscanf(zPtr, PTR_FMT, &p2)!=1 || p2!=p ){
124 Tcl_AppendResult(interp, "unable to convert a pointer to a string "
125 "in the file " __FILE__ " in function makePointerStr(). Please "
126 "report this problem to the SQLite mailing list or as a new but "
127 "report. Please provide detailed information about how you compiled "
128 "SQLite and what computer you are running on.", 0);
129 return TCL_ERROR;
130 }
131 }
132 return TCL_OK;
133}
134
135/*
danielk19776f8a5032004-05-10 10:34:51 +0000136** The callback routine for sqlite3_exec_printf().
drhd1bf3512001-04-07 15:24:33 +0000137*/
138static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){
139 Tcl_DString *str = (Tcl_DString*)pArg;
140 int i;
141
142 if( Tcl_DStringLength(str)==0 ){
143 for(i=0; i<argc; i++){
144 Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL");
145 }
146 }
147 for(i=0; i<argc; i++){
148 Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL");
149 }
150 return 0;
151}
152
153/*
danielk19776f8a5032004-05-10 10:34:51 +0000154** Usage: sqlite3_exec_printf DB FORMAT STRING
drhd1bf3512001-04-07 15:24:33 +0000155**
danielk19776f8a5032004-05-10 10:34:51 +0000156** Invoke the sqlite3_exec_printf() interface using the open database
drhd1bf3512001-04-07 15:24:33 +0000157** DB. The SQL is the string FORMAT. The format string should contain
158** one %s or %q. STRING is the value inserted into %s or %q.
159*/
160static int test_exec_printf(
161 void *NotUsed,
162 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
163 int argc, /* Number of arguments */
164 char **argv /* Text of each argument */
165){
166 sqlite *db;
167 Tcl_DString str;
168 int rc;
169 char *zErr = 0;
170 char zBuf[30];
171 if( argc!=4 ){
172 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
173 " DB FORMAT STRING", 0);
174 return TCL_ERROR;
175 }
drhb86ccfb2003-01-28 23:13:10 +0000176 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000177 Tcl_DStringInit(&str);
danielk19776f8a5032004-05-10 10:34:51 +0000178 rc = sqlite3_exec_printf(db, argv[2], exec_printf_cb, &str, &zErr, argv[3]);
drhd1bf3512001-04-07 15:24:33 +0000179 sprintf(zBuf, "%d", rc);
180 Tcl_AppendElement(interp, zBuf);
181 Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
182 Tcl_DStringFree(&str);
183 if( zErr ) free(zErr);
184 return TCL_OK;
185}
186
187/*
danielk19776f8a5032004-05-10 10:34:51 +0000188** Usage: sqlite3_mprintf_z_test SEPARATOR ARG0 ARG1 ...
drhd93d8a82003-06-16 03:08:18 +0000189**
190** Test the %z format of mprintf(). Use multiple mprintf() calls to
191** concatenate arg0 through argn using separator as the separator.
192** Return the result.
193*/
194static int test_mprintf_z(
195 void *NotUsed,
196 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
197 int argc, /* Number of arguments */
198 char **argv /* Text of each argument */
199){
200 char *zResult = 0;
201 int i;
202
203 for(i=2; i<argc; i++){
danielk19774adee202004-05-08 08:23:19 +0000204 zResult = sqlite3MPrintf("%z%s%s", zResult, argv[1], argv[i]);
drhd93d8a82003-06-16 03:08:18 +0000205 }
206 Tcl_AppendResult(interp, zResult, 0);
drh5f968432004-02-21 19:02:30 +0000207 sqliteFree(zResult);
drhd93d8a82003-06-16 03:08:18 +0000208 return TCL_OK;
209}
210
211/*
danielk19776f8a5032004-05-10 10:34:51 +0000212** Usage: sqlite3_get_table_printf DB FORMAT STRING
drhd1bf3512001-04-07 15:24:33 +0000213**
danielk19776f8a5032004-05-10 10:34:51 +0000214** Invoke the sqlite3_get_table_printf() interface using the open database
drhd1bf3512001-04-07 15:24:33 +0000215** DB. The SQL is the string FORMAT. The format string should contain
216** one %s or %q. STRING is the value inserted into %s or %q.
217*/
218static int test_get_table_printf(
219 void *NotUsed,
220 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
221 int argc, /* Number of arguments */
222 char **argv /* Text of each argument */
223){
224 sqlite *db;
225 Tcl_DString str;
226 int rc;
227 char *zErr = 0;
228 int nRow, nCol;
229 char **aResult;
230 int i;
231 char zBuf[30];
232 if( argc!=4 ){
233 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
234 " DB FORMAT STRING", 0);
235 return TCL_ERROR;
236 }
drhb86ccfb2003-01-28 23:13:10 +0000237 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000238 Tcl_DStringInit(&str);
danielk19776f8a5032004-05-10 10:34:51 +0000239 rc = sqlite3_get_table_printf(db, argv[2], &aResult, &nRow, &nCol,
drhd1bf3512001-04-07 15:24:33 +0000240 &zErr, argv[3]);
241 sprintf(zBuf, "%d", rc);
242 Tcl_AppendElement(interp, zBuf);
243 if( rc==SQLITE_OK ){
244 sprintf(zBuf, "%d", nRow);
245 Tcl_AppendElement(interp, zBuf);
246 sprintf(zBuf, "%d", nCol);
247 Tcl_AppendElement(interp, zBuf);
248 for(i=0; i<(nRow+1)*nCol; i++){
249 Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL");
250 }
251 }else{
252 Tcl_AppendElement(interp, zErr);
253 }
danielk19776f8a5032004-05-10 10:34:51 +0000254 sqlite3_free_table(aResult);
drhd1bf3512001-04-07 15:24:33 +0000255 if( zErr ) free(zErr);
256 return TCL_OK;
257}
258
drhaf9ff332002-01-16 21:00:27 +0000259
260/*
danielk19776f8a5032004-05-10 10:34:51 +0000261** Usage: sqlite3_last_insert_rowid DB
drhaf9ff332002-01-16 21:00:27 +0000262**
263** Returns the integer ROWID of the most recent insert.
264*/
265static int test_last_rowid(
266 void *NotUsed,
267 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
268 int argc, /* Number of arguments */
269 char **argv /* Text of each argument */
270){
271 sqlite *db;
272 char zBuf[30];
273
274 if( argc!=2 ){
275 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0);
276 return TCL_ERROR;
277 }
drhb86ccfb2003-01-28 23:13:10 +0000278 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk19776f8a5032004-05-10 10:34:51 +0000279 sprintf(zBuf, "%d", sqlite3_last_insert_rowid(db));
drhaf9ff332002-01-16 21:00:27 +0000280 Tcl_AppendResult(interp, zBuf, 0);
281 return SQLITE_OK;
282}
283
drhd1bf3512001-04-07 15:24:33 +0000284/*
danielk19776f8a5032004-05-10 10:34:51 +0000285** Usage: sqlite3_close DB
drhd1bf3512001-04-07 15:24:33 +0000286**
danielk19776f8a5032004-05-10 10:34:51 +0000287** Closes the database opened by sqlite3_open.
drhd1bf3512001-04-07 15:24:33 +0000288*/
289static int sqlite_test_close(
290 void *NotUsed,
291 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
292 int argc, /* Number of arguments */
293 char **argv /* Text of each argument */
294){
295 sqlite *db;
296 if( argc!=2 ){
297 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
298 " FILENAME\"", 0);
299 return TCL_ERROR;
300 }
drhb86ccfb2003-01-28 23:13:10 +0000301 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk19776f8a5032004-05-10 10:34:51 +0000302 sqlite3_close(db);
drhd1bf3512001-04-07 15:24:33 +0000303 return TCL_OK;
304}
305
306/*
drhc22bd472002-05-10 13:14:07 +0000307** Implementation of the x_coalesce() function.
308** Return the first argument non-NULL argument.
309*/
310static void ifnullFunc(sqlite_func *context, int argc, const char **argv){
311 int i;
312 for(i=0; i<argc; i++){
313 if( argv[i] ){
danielk19776f8a5032004-05-10 10:34:51 +0000314 sqlite3_set_result_string(context, argv[i], -1);
drhc22bd472002-05-10 13:14:07 +0000315 break;
316 }
317 }
318}
319
320/*
drhd1d9fc32004-01-07 19:24:48 +0000321** A structure into which to accumulate text.
322*/
323struct dstr {
324 int nAlloc; /* Space allocated */
325 int nUsed; /* Space used */
326 char *z; /* The space */
327};
328
329/*
330** Append text to a dstr
331*/
332static void dstrAppend(struct dstr *p, const char *z, int divider){
333 int n = strlen(z);
334 if( p->nUsed + n + 2 > p->nAlloc ){
335 char *zNew;
336 p->nAlloc = p->nAlloc*2 + n + 200;
337 zNew = sqliteRealloc(p->z, p->nAlloc);
338 if( zNew==0 ){
339 sqliteFree(p->z);
340 memset(p, 0, sizeof(*p));
341 return;
342 }
343 p->z = zNew;
344 }
345 if( divider && p->nUsed>0 ){
346 p->z[p->nUsed++] = divider;
347 }
348 memcpy(&p->z[p->nUsed], z, n+1);
349 p->nUsed += n;
350}
351
352/*
danielk19774adee202004-05-08 08:23:19 +0000353** Invoked for each callback from sqlite3ExecFunc
drhd1d9fc32004-01-07 19:24:48 +0000354*/
355static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){
356 struct dstr *p = (struct dstr*)pData;
357 int i;
358 for(i=0; i<argc; i++){
359 if( argv[i]==0 ){
360 dstrAppend(p, "NULL", ' ');
361 }else{
362 dstrAppend(p, argv[i], ' ');
363 }
364 }
365 return 0;
366}
367
368/*
danielk19776f8a5032004-05-10 10:34:51 +0000369** Implementation of the x_sqlite3_exec() function. This function takes
drhc22bd472002-05-10 13:14:07 +0000370** a single argument and attempts to execute that argument as SQL code.
drh6cbe1f12002-07-01 00:31:36 +0000371** This is illegal and should set the SQLITE_MISUSE flag on the database.
drhd1d9fc32004-01-07 19:24:48 +0000372**
danielk19776f8a5032004-05-10 10:34:51 +0000373** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec()
drhd1d9fc32004-01-07 19:24:48 +0000374** from within a function call.
drhc22bd472002-05-10 13:14:07 +0000375**
376** This routine simulates the effect of having two threads attempt to
377** use the same database at the same time.
378*/
danielk19774adee202004-05-08 08:23:19 +0000379static void sqlite3ExecFunc(sqlite_func *context, int argc, const char **argv){
drhd1d9fc32004-01-07 19:24:48 +0000380 struct dstr x;
381 memset(&x, 0, sizeof(x));
danielk19776f8a5032004-05-10 10:34:51 +0000382 sqlite3_exec((sqlite*)sqlite3_user_data(context), argv[0],
drhd1d9fc32004-01-07 19:24:48 +0000383 execFuncCallback, &x, 0);
danielk19776f8a5032004-05-10 10:34:51 +0000384 sqlite3_set_result_string(context, x.z, x.nUsed);
drhd1d9fc32004-01-07 19:24:48 +0000385 sqliteFree(x.z);
drhc22bd472002-05-10 13:14:07 +0000386}
387
388/*
389** Usage: sqlite_test_create_function DB
390**
danielk19776f8a5032004-05-10 10:34:51 +0000391** Call the sqlite3_create_function API on the given database in order
drhc22bd472002-05-10 13:14:07 +0000392** to create a function named "x_coalesce". This function does the same thing
393** as the "coalesce" function. This function also registers an SQL function
danielk19776f8a5032004-05-10 10:34:51 +0000394** named "x_sqlite3_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec()
drhc22bd472002-05-10 13:14:07 +0000395** in this way is illegal recursion and should raise an SQLITE_MISUSE error.
396** The effect is similar to trying to use the same database connection from
397** two threads at the same time.
398**
399** The original motivation for this routine was to be able to call the
danielk19776f8a5032004-05-10 10:34:51 +0000400** sqlite3_create_function function while a query is in progress in order
drhc22bd472002-05-10 13:14:07 +0000401** to test the SQLITE_MISUSE detection logic.
402*/
drhc2eef3b2002-08-31 18:53:06 +0000403static int test_create_function(
drhc22bd472002-05-10 13:14:07 +0000404 void *NotUsed,
405 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
406 int argc, /* Number of arguments */
407 char **argv /* Text of each argument */
408){
409 sqlite *db;
410 extern void Md5_Register(sqlite*);
411 if( argc!=2 ){
412 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
413 " FILENAME\"", 0);
414 return TCL_ERROR;
415 }
drhb86ccfb2003-01-28 23:13:10 +0000416 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk19776f8a5032004-05-10 10:34:51 +0000417 sqlite3_create_function(db, "x_coalesce", -1, ifnullFunc, 0);
418 sqlite3_create_function(db, "x_sqlite3_exec", 1, sqlite3ExecFunc, db);
drhc22bd472002-05-10 13:14:07 +0000419 return TCL_OK;
420}
421
422/*
423** Routines to implement the x_count() aggregate function.
424*/
425typedef struct CountCtx CountCtx;
426struct CountCtx {
427 int n;
428};
429static void countStep(sqlite_func *context, int argc, const char **argv){
430 CountCtx *p;
danielk19776f8a5032004-05-10 10:34:51 +0000431 p = sqlite3_aggregate_context(context, sizeof(*p));
drhc22bd472002-05-10 13:14:07 +0000432 if( (argc==0 || argv[0]) && p ){
433 p->n++;
434 }
435}
436static void countFinalize(sqlite_func *context){
437 CountCtx *p;
danielk19776f8a5032004-05-10 10:34:51 +0000438 p = sqlite3_aggregate_context(context, sizeof(*p));
439 sqlite3_set_result_int(context, p ? p->n : 0);
drhc22bd472002-05-10 13:14:07 +0000440}
441
442/*
443** Usage: sqlite_test_create_aggregate DB
444**
danielk19776f8a5032004-05-10 10:34:51 +0000445** Call the sqlite3_create_function API on the given database in order
drhc22bd472002-05-10 13:14:07 +0000446** to create a function named "x_count". This function does the same thing
447** as the "md5sum" function.
448**
449** The original motivation for this routine was to be able to call the
danielk19776f8a5032004-05-10 10:34:51 +0000450** sqlite3_create_aggregate function while a query is in progress in order
drhc22bd472002-05-10 13:14:07 +0000451** to test the SQLITE_MISUSE detection logic.
452*/
drhc2eef3b2002-08-31 18:53:06 +0000453static int test_create_aggregate(
drhc22bd472002-05-10 13:14:07 +0000454 void *NotUsed,
455 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
456 int argc, /* Number of arguments */
457 char **argv /* Text of each argument */
458){
459 sqlite *db;
460 if( argc!=2 ){
461 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
462 " FILENAME\"", 0);
463 return TCL_ERROR;
464 }
drhb86ccfb2003-01-28 23:13:10 +0000465 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk19776f8a5032004-05-10 10:34:51 +0000466 sqlite3_create_aggregate(db, "x_count", 0, countStep, countFinalize, 0);
467 sqlite3_create_aggregate(db, "x_count", 1, countStep, countFinalize, 0);
drhc22bd472002-05-10 13:14:07 +0000468 return TCL_OK;
469}
470
471
472
473/*
danielk19776f8a5032004-05-10 10:34:51 +0000474** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER
drhd1bf3512001-04-07 15:24:33 +0000475**
476** Call mprintf with three integer arguments
477*/
danielk19776f8a5032004-05-10 10:34:51 +0000478static int sqlite3_mprintf_int(
drhd1bf3512001-04-07 15:24:33 +0000479 void *NotUsed,
480 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
481 int argc, /* Number of arguments */
482 char **argv /* Text of each argument */
483){
484 int a[3], i;
485 char *z;
486 if( argc!=5 ){
487 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
488 " FORMAT INT INT INT\"", 0);
489 return TCL_ERROR;
490 }
491 for(i=2; i<5; i++){
492 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
493 }
danielk19776f8a5032004-05-10 10:34:51 +0000494 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
drhd1bf3512001-04-07 15:24:33 +0000495 Tcl_AppendResult(interp, z, 0);
danielk19776f8a5032004-05-10 10:34:51 +0000496 sqlite3_freemem(z);
drhd1bf3512001-04-07 15:24:33 +0000497 return TCL_OK;
498}
499
500/*
danielk19776f8a5032004-05-10 10:34:51 +0000501** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING
drhd1bf3512001-04-07 15:24:33 +0000502**
503** Call mprintf with two integer arguments and one string argument
504*/
danielk19776f8a5032004-05-10 10:34:51 +0000505static int sqlite3_mprintf_str(
drhd1bf3512001-04-07 15:24:33 +0000506 void *NotUsed,
507 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
508 int argc, /* Number of arguments */
509 char **argv /* Text of each argument */
510){
511 int a[3], i;
512 char *z;
chwf220b242002-06-16 04:54:28 +0000513 if( argc<4 || argc>5 ){
drhd1bf3512001-04-07 15:24:33 +0000514 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
chwf220b242002-06-16 04:54:28 +0000515 " FORMAT INT INT ?STRING?\"", 0);
drhd1bf3512001-04-07 15:24:33 +0000516 return TCL_ERROR;
517 }
518 for(i=2; i<4; i++){
519 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
520 }
danielk19776f8a5032004-05-10 10:34:51 +0000521 z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL);
drhd1bf3512001-04-07 15:24:33 +0000522 Tcl_AppendResult(interp, z, 0);
danielk19776f8a5032004-05-10 10:34:51 +0000523 sqlite3_freemem(z);
drhd1bf3512001-04-07 15:24:33 +0000524 return TCL_OK;
525}
526
527/*
danielk19776f8a5032004-05-10 10:34:51 +0000528** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER DOUBLE
drhd1bf3512001-04-07 15:24:33 +0000529**
530** Call mprintf with two integer arguments and one double argument
531*/
danielk19776f8a5032004-05-10 10:34:51 +0000532static int sqlite3_mprintf_double(
drhd1bf3512001-04-07 15:24:33 +0000533 void *NotUsed,
534 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
535 int argc, /* Number of arguments */
536 char **argv /* Text of each argument */
537){
538 int a[3], i;
539 double r;
540 char *z;
541 if( argc!=5 ){
542 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
543 " FORMAT INT INT STRING\"", 0);
544 return TCL_ERROR;
545 }
546 for(i=2; i<4; i++){
547 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
548 }
549 if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
danielk19776f8a5032004-05-10 10:34:51 +0000550 z = sqlite3_mprintf(argv[1], a[0], a[1], r);
drhd1bf3512001-04-07 15:24:33 +0000551 Tcl_AppendResult(interp, z, 0);
danielk19776f8a5032004-05-10 10:34:51 +0000552 sqlite3_freemem(z);
drhd1bf3512001-04-07 15:24:33 +0000553 return TCL_OK;
554}
555
556/*
danielk19776f8a5032004-05-10 10:34:51 +0000557** Usage: sqlite3_mprintf_str FORMAT DOUBLE DOUBLE
drhb621c232004-02-21 19:41:04 +0000558**
559** Call mprintf with a single double argument which is the product of the
560** two arguments given above. This is used to generate overflow and underflow
561** doubles to test that they are converted properly.
562*/
danielk19776f8a5032004-05-10 10:34:51 +0000563static int sqlite3_mprintf_scaled(
drhb621c232004-02-21 19:41:04 +0000564 void *NotUsed,
565 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
566 int argc, /* Number of arguments */
567 char **argv /* Text of each argument */
568){
569 int i;
570 double r[2];
571 char *z;
572 if( argc!=4 ){
573 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
574 " FORMAT DOUBLE DOUBLE\"", 0);
575 return TCL_ERROR;
576 }
577 for(i=2; i<4; i++){
578 if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR;
579 }
danielk19776f8a5032004-05-10 10:34:51 +0000580 z = sqlite3_mprintf(argv[1], r[0]*r[1]);
drhb621c232004-02-21 19:41:04 +0000581 Tcl_AppendResult(interp, z, 0);
danielk19776f8a5032004-05-10 10:34:51 +0000582 sqlite3_freemem(z);
drhb621c232004-02-21 19:41:04 +0000583 return TCL_OK;
584}
585
586/*
drhdaffd0e2001-04-11 14:28:42 +0000587** Usage: sqlite_malloc_fail N
588**
drhafa4a022001-09-24 03:12:39 +0000589** Rig sqliteMalloc() to fail on the N-th call. Turn off this mechanism
danielk19776f8a5032004-05-10 10:34:51 +0000590** and reset the sqlite3_malloc_failed variable is N==0.
drhdaffd0e2001-04-11 14:28:42 +0000591*/
592#ifdef MEMORY_DEBUG
593static int sqlite_malloc_fail(
594 void *NotUsed,
595 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
596 int argc, /* Number of arguments */
597 char **argv /* Text of each argument */
598){
599 int n;
600 if( argc!=2 ){
601 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0);
602 return TCL_ERROR;
603 }
604 if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
danielk19776f8a5032004-05-10 10:34:51 +0000605 sqlite3_iMallocFail = n;
606 sqlite3_malloc_failed = 0;
drhdaffd0e2001-04-11 14:28:42 +0000607 return TCL_OK;
608}
609#endif
610
611/*
612** Usage: sqlite_malloc_stat
613**
614** Return the number of prior calls to sqliteMalloc() and sqliteFree().
615*/
616#ifdef MEMORY_DEBUG
617static int sqlite_malloc_stat(
618 void *NotUsed,
619 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
620 int argc, /* Number of arguments */
621 char **argv /* Text of each argument */
622){
623 char zBuf[200];
danielk19776f8a5032004-05-10 10:34:51 +0000624 sprintf(zBuf, "%d %d %d", sqlite3_nMalloc, sqlite3_nFree, sqlite3_iMallocFail);
drhdaffd0e2001-04-11 14:28:42 +0000625 Tcl_AppendResult(interp, zBuf, 0);
626 return TCL_OK;
627}
628#endif
629
630/*
drh28b4e482002-03-11 02:06:13 +0000631** Usage: sqlite_abort
632**
633** Shutdown the process immediately. This is not a clean shutdown.
634** This command is used to test the recoverability of a database in
635** the event of a program crash.
636*/
637static int sqlite_abort(
638 void *NotUsed,
639 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
640 int argc, /* Number of arguments */
641 char **argv /* Text of each argument */
642){
643 assert( interp==0 ); /* This will always fail */
644 return TCL_OK;
645}
646
647/*
drh6cbe1f12002-07-01 00:31:36 +0000648** The following routine is a user-defined SQL function whose purpose
649** is to test the sqlite_set_result() API.
650*/
651static void testFunc(sqlite_func *context, int argc, const char **argv){
652 while( argc>=2 ){
653 if( argv[0]==0 ){
danielk19776f8a5032004-05-10 10:34:51 +0000654 sqlite3_set_result_error(context, "first argument to test function "
drh6cbe1f12002-07-01 00:31:36 +0000655 "may not be NULL", -1);
danielk19774adee202004-05-08 08:23:19 +0000656 }else if( sqlite3StrICmp(argv[0],"string")==0 ){
danielk19776f8a5032004-05-10 10:34:51 +0000657 sqlite3_set_result_string(context, argv[1], -1);
drh6cbe1f12002-07-01 00:31:36 +0000658 }else if( argv[1]==0 ){
danielk19776f8a5032004-05-10 10:34:51 +0000659 sqlite3_set_result_error(context, "2nd argument may not be NULL if the "
drh6cbe1f12002-07-01 00:31:36 +0000660 "first argument is not \"string\"", -1);
danielk19774adee202004-05-08 08:23:19 +0000661 }else if( sqlite3StrICmp(argv[0],"int")==0 ){
danielk19776f8a5032004-05-10 10:34:51 +0000662 sqlite3_set_result_int(context, atoi(argv[1]));
danielk19774adee202004-05-08 08:23:19 +0000663 }else if( sqlite3StrICmp(argv[0],"double")==0 ){
danielk19776f8a5032004-05-10 10:34:51 +0000664 sqlite3_set_result_double(context, sqlite3AtoF(argv[1], 0));
drh6cbe1f12002-07-01 00:31:36 +0000665 }else{
danielk19776f8a5032004-05-10 10:34:51 +0000666 sqlite3_set_result_error(context,"first argument should be one of: "
drh6cbe1f12002-07-01 00:31:36 +0000667 "string int double", -1);
668 }
669 argc -= 2;
670 argv += 2;
671 }
672}
673
674/*
675** Usage: sqlite_register_test_function DB NAME
676**
677** Register the test SQL function on the database DB under the name NAME.
678*/
drhc2eef3b2002-08-31 18:53:06 +0000679static int test_register_func(
drh6cbe1f12002-07-01 00:31:36 +0000680 void *NotUsed,
681 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
682 int argc, /* Number of arguments */
683 char **argv /* Text of each argument */
684){
685 sqlite *db;
686 int rc;
687 if( argc!=3 ){
688 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
689 " DB FUNCTION-NAME", 0);
690 return TCL_ERROR;
691 }
drhb86ccfb2003-01-28 23:13:10 +0000692 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk19776f8a5032004-05-10 10:34:51 +0000693 rc = sqlite3_create_function(db, argv[2], -1, testFunc, 0);
drh6cbe1f12002-07-01 00:31:36 +0000694 if( rc!=0 ){
danielk19776f8a5032004-05-10 10:34:51 +0000695 Tcl_AppendResult(interp, sqlite3_error_string(rc), 0);
drh6cbe1f12002-07-01 00:31:36 +0000696 return TCL_ERROR;
697 }
698 return TCL_OK;
699}
700
701/*
drh5a387052003-01-11 14:19:51 +0000702** This SQLite callback records the datatype of all columns.
703**
704** The pArg argument is really a pointer to a TCL interpreter. The
705** column names are inserted as the result of this interpreter.
706**
707** This routine returns non-zero which causes the query to abort.
708*/
709static int rememberDataTypes(void *pArg, int nCol, char **argv, char **colv){
710 int i;
711 Tcl_Interp *interp = (Tcl_Interp*)pArg;
712 Tcl_Obj *pList, *pElem;
713 if( colv[nCol+1]==0 ){
714 return 1;
715 }
716 pList = Tcl_NewObj();
717 for(i=0; i<nCol; i++){
718 pElem = Tcl_NewStringObj(colv[i+nCol] ? colv[i+nCol] : "NULL", -1);
719 Tcl_ListObjAppendElement(interp, pList, pElem);
720 }
721 Tcl_SetObjResult(interp, pList);
722 return 1;
723}
724
725/*
726** Invoke an SQL statement but ignore all the data in the result. Instead,
727** return a list that consists of the datatypes of the various columns.
728**
729** This only works if "PRAGMA show_datatypes=on" has been executed against
730** the database connection.
731*/
732static int sqlite_datatypes(
733 void *NotUsed,
734 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
735 int argc, /* Number of arguments */
736 char **argv /* Text of each argument */
737){
738 sqlite *db;
739 int rc;
740 if( argc!=3 ){
741 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
742 " DB SQL", 0);
743 return TCL_ERROR;
744 }
drhb86ccfb2003-01-28 23:13:10 +0000745 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk19776f8a5032004-05-10 10:34:51 +0000746 rc = sqlite3_exec(db, argv[2], rememberDataTypes, interp, 0);
drh5a387052003-01-11 14:19:51 +0000747 if( rc!=0 && rc!=SQLITE_ABORT ){
danielk19776f8a5032004-05-10 10:34:51 +0000748 Tcl_AppendResult(interp, sqlite3_error_string(rc), 0);
drh5a387052003-01-11 14:19:51 +0000749 return TCL_ERROR;
750 }
751 return TCL_OK;
752}
753
drhb86ccfb2003-01-28 23:13:10 +0000754/*
danielk19776f8a5032004-05-10 10:34:51 +0000755** Usage: sqlite3_step VM ?NVAR? ?VALUEVAR? ?COLNAMEVAR?
drhb86ccfb2003-01-28 23:13:10 +0000756**
757** Step a virtual machine. Return a the result code as a string.
758** Column results are written into three variables.
759*/
760static int test_step(
761 void *NotUsed,
762 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
763 int argc, /* Number of arguments */
764 char **argv /* Text of each argument */
765){
766 sqlite_vm *vm;
767 int rc, i;
drh3a840692003-01-29 22:58:26 +0000768 const char **azValue = 0;
769 const char **azColName = 0;
770 int N = 0;
drhb86ccfb2003-01-28 23:13:10 +0000771 char *zRc;
772 char zBuf[50];
drh073e5a72003-07-09 00:28:13 +0000773 if( argc<2 || argc>5 ){
drhb86ccfb2003-01-28 23:13:10 +0000774 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
775 " VM NVAR VALUEVAR COLNAMEVAR", 0);
776 return TCL_ERROR;
777 }
778 if( getVmPointer(interp, argv[1], &vm) ) return TCL_ERROR;
danielk19776f8a5032004-05-10 10:34:51 +0000779 rc = sqlite3_step(vm, argc>=3?&N:0, argc>=4?&azValue:0, argc==5?&azColName:0);
drh073e5a72003-07-09 00:28:13 +0000780 if( argc>=3 ){
781 sprintf(zBuf, "%d", N);
782 Tcl_SetVar(interp, argv[2], zBuf, 0);
783 }
784 if( argc>=4 ){
785 Tcl_SetVar(interp, argv[3], "", 0);
786 if( azValue ){
787 for(i=0; i<N; i++){
788 Tcl_SetVar(interp, argv[3], azValue[i] ? azValue[i] : "",
789 TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
790 }
drhb86ccfb2003-01-28 23:13:10 +0000791 }
drh3a840692003-01-29 22:58:26 +0000792 }
drh073e5a72003-07-09 00:28:13 +0000793 if( argc==5 ){
794 Tcl_SetVar(interp, argv[4], "", 0);
795 if( azColName ){
796 for(i=0; i<N*2; i++){
797 Tcl_SetVar(interp, argv[4], azColName[i] ? azColName[i] : "",
798 TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
799 }
drhb86ccfb2003-01-28 23:13:10 +0000800 }
801 }
802 switch( rc ){
803 case SQLITE_DONE: zRc = "SQLITE_DONE"; break;
drh326dce72003-01-29 14:06:07 +0000804 case SQLITE_BUSY: zRc = "SQLITE_BUSY"; break;
805 case SQLITE_ROW: zRc = "SQLITE_ROW"; break;
806 case SQLITE_ERROR: zRc = "SQLITE_ERROR"; break;
drhb86ccfb2003-01-28 23:13:10 +0000807 case SQLITE_MISUSE: zRc = "SQLITE_MISUSE"; break;
808 default: zRc = "unknown"; break;
809 }
810 Tcl_AppendResult(interp, zRc, 0);
811 return TCL_OK;
812}
813
814/*
danielk1977106bb232004-05-21 10:08:53 +0000815** Usage: sqlite3_finalize STMT
drhb86ccfb2003-01-28 23:13:10 +0000816**
danielk1977106bb232004-05-21 10:08:53 +0000817** Finalize a statement handle.
drhb86ccfb2003-01-28 23:13:10 +0000818*/
819static int test_finalize(
danielk1977106bb232004-05-21 10:08:53 +0000820 void * clientData,
821 Tcl_Interp *interp,
822 int objc,
823 Tcl_Obj *CONST objv[]
drhb86ccfb2003-01-28 23:13:10 +0000824){
danielk1977106bb232004-05-21 10:08:53 +0000825 sqlite3_stmt *pStmt;
drhb86ccfb2003-01-28 23:13:10 +0000826 int rc;
danielk1977106bb232004-05-21 10:08:53 +0000827
828 if( objc!=2 ){
829 Tcl_AppendResult(interp, "wrong # args: should be \"",
830 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
drhb86ccfb2003-01-28 23:13:10 +0000831 return TCL_ERROR;
832 }
danielk1977106bb232004-05-21 10:08:53 +0000833
834 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
835
836 rc = sqlite3_finalize_new(pStmt);
drhb86ccfb2003-01-28 23:13:10 +0000837 if( rc ){
danielk1977106bb232004-05-21 10:08:53 +0000838 return TCL_ERROR;
839 }
840 return TCL_OK;
841}
842
843/*
844** Usage: sqlite3_reset STMT
845**
846** Finalize a statement handle.
847*/
848static int test_reset(
849 void * clientData,
850 Tcl_Interp *interp,
851 int objc,
852 Tcl_Obj *CONST objv[]
853){
854 sqlite3_stmt *pStmt;
855 int rc;
856
857 if( objc!=2 ){
858 Tcl_AppendResult(interp, "wrong # args: should be \"",
859 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
860 return TCL_ERROR;
861 }
862
863 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
864
865 rc = sqlite3_reset_new(pStmt);
866 if( rc ){
drhb86ccfb2003-01-28 23:13:10 +0000867 return TCL_ERROR;
868 }
869 return TCL_OK;
870}
871
drh5a387052003-01-11 14:19:51 +0000872/*
danielk19776f8a5032004-05-10 10:34:51 +0000873** Usage: sqlite3_reset VM
drh50457892003-09-06 01:10:47 +0000874**
875** Reset a virtual machine and prepare it to be run again.
876*/
drh50457892003-09-06 01:10:47 +0000877
878/*
drh7c972de2003-09-06 22:18:07 +0000879** This is the "static_bind_value" that variables are bound to when
danielk19776f8a5032004-05-10 10:34:51 +0000880** the FLAG option of sqlite3_bind is "static"
drh50457892003-09-06 01:10:47 +0000881*/
drh7c972de2003-09-06 22:18:07 +0000882static char *sqlite_static_bind_value = 0;
883
884/*
danielk19776f8a5032004-05-10 10:34:51 +0000885** Usage: sqlite3_bind VM IDX VALUE FLAGS
drh7c972de2003-09-06 22:18:07 +0000886**
887** Sets the value of the IDX-th occurance of "?" in the original SQL
888** string. VALUE is the new value. If FLAGS=="null" then VALUE is
889** ignored and the value is set to NULL. If FLAGS=="static" then
890** the value is set to the value of a static variable named
891** "sqlite_static_bind_value". If FLAGS=="normal" then a copy
892** of the VALUE is made.
893*/
894static int test_bind(
drh50457892003-09-06 01:10:47 +0000895 void *NotUsed,
896 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
897 int argc, /* Number of arguments */
898 char **argv /* Text of each argument */
899){
900 sqlite_vm *vm;
901 int rc;
drh7c972de2003-09-06 22:18:07 +0000902 int idx;
903 if( argc!=5 ){
drh50457892003-09-06 01:10:47 +0000904 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
drh7c972de2003-09-06 22:18:07 +0000905 " VM IDX VALUE (null|static|normal)\"", 0);
drh50457892003-09-06 01:10:47 +0000906 return TCL_ERROR;
907 }
908 if( getVmPointer(interp, argv[1], &vm) ) return TCL_ERROR;
drh7c972de2003-09-06 22:18:07 +0000909 if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR;
910 if( strcmp(argv[4],"null")==0 ){
danielk19776f8a5032004-05-10 10:34:51 +0000911 rc = sqlite3_bind(vm, idx, 0, 0, 0);
drh7c972de2003-09-06 22:18:07 +0000912 }else if( strcmp(argv[4],"static")==0 ){
danielk19776f8a5032004-05-10 10:34:51 +0000913 rc = sqlite3_bind(vm, idx, sqlite_static_bind_value, -1, 0);
drh7c972de2003-09-06 22:18:07 +0000914 }else if( strcmp(argv[4],"normal")==0 ){
danielk19776f8a5032004-05-10 10:34:51 +0000915 rc = sqlite3_bind(vm, idx, argv[3], -1, 1);
drh7c972de2003-09-06 22:18:07 +0000916 }else{
917 Tcl_AppendResult(interp, "4th argument should be "
918 "\"null\" or \"static\" or \"normal\"", 0);
919 return TCL_ERROR;
920 }
drh50457892003-09-06 01:10:47 +0000921 if( rc ){
922 char zBuf[50];
923 sprintf(zBuf, "(%d) ", rc);
danielk19776f8a5032004-05-10 10:34:51 +0000924 Tcl_AppendResult(interp, zBuf, sqlite3_error_string(rc), 0);
drh50457892003-09-06 01:10:47 +0000925 return TCL_ERROR;
926 }
927 return TCL_OK;
928}
929
930/*
drh99ee3602003-02-16 19:13:36 +0000931** Usage: breakpoint
932**
933** This routine exists for one purpose - to provide a place to put a
934** breakpoint with GDB that can be triggered using TCL code. The use
935** for this is when a particular test fails on (say) the 1485th iteration.
936** In the TCL test script, we can add code like this:
937**
938** if {$i==1485} breakpoint
939**
940** Then run testfixture in the debugger and wait for the breakpoint to
941** fire. Then additional breakpoints can be set to trace down the bug.
942*/
943static int test_breakpoint(
944 void *NotUsed,
945 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
946 int argc, /* Number of arguments */
947 char **argv /* Text of each argument */
948){
949 return TCL_OK; /* Do nothing */
950}
951
danielk197751e3d8e2004-05-20 01:12:34 +0000952static int test_bind_int32(
953 void * clientData,
954 Tcl_Interp *interp,
955 int objc,
956 Tcl_Obj *CONST objv[]
957){
958 sqlite3_stmt *pStmt;
959 int idx;
960 int value;
961 int rc;
962
963 if( objc!=4 ){
964 Tcl_AppendResult(interp, "wrong # args: should be \"",
965 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>", 0);
966 return TCL_ERROR;
967 }
968
969 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
970 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
971 if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
972
973 rc = sqlite3_bind_int32(pStmt, idx, value);
974 if( rc!=SQLITE_OK ){
975 return TCL_ERROR;
976 }
977
978 return TCL_OK;
979}
980
981static int test_bind_int64(
982 void * clientData,
983 Tcl_Interp *interp,
984 int objc,
985 Tcl_Obj *CONST objv[]
986){
987 sqlite3_stmt *pStmt;
988 int idx;
989 i64 value;
990 int rc;
991
992 if( objc!=4 ){
993 Tcl_AppendResult(interp, "wrong # args: should be \"",
994 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>", 0);
995 return TCL_ERROR;
996 }
997
998 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
999 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1000 if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
1001
1002 rc = sqlite3_bind_int64(pStmt, idx, value);
1003 if( rc!=SQLITE_OK ){
1004 return TCL_ERROR;
1005 }
1006
1007 return TCL_OK;
1008}
1009
1010static int test_bind_double(
1011 void * clientData,
1012 Tcl_Interp *interp,
1013 int objc,
1014 Tcl_Obj *CONST objv[]
1015){
1016 sqlite3_stmt *pStmt;
1017 int idx;
1018 double value;
1019 int rc;
1020
1021 if( objc!=4 ){
1022 Tcl_AppendResult(interp, "wrong # args: should be \"",
1023 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>", 0);
1024 return TCL_ERROR;
1025 }
1026
1027 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1028 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1029 if( Tcl_GetDoubleFromObj(interp, objv[3], &value) ) return TCL_ERROR;
1030
1031 rc = sqlite3_bind_double(pStmt, idx, value);
1032 if( rc!=SQLITE_OK ){
1033 return TCL_ERROR;
1034 }
1035
1036 return TCL_OK;
1037}
1038
1039static int test_bind_null(
1040 void * clientData,
1041 Tcl_Interp *interp,
1042 int objc,
1043 Tcl_Obj *CONST objv[]
1044){
1045 sqlite3_stmt *pStmt;
1046 int idx;
1047 int rc;
1048
1049 if( objc!=3 ){
1050 Tcl_AppendResult(interp, "wrong # args: should be \"",
1051 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.>", 0);
1052 return TCL_ERROR;
1053 }
1054
1055 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1056 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1057
1058 rc = sqlite3_bind_null(pStmt, idx);
1059 if( rc!=SQLITE_OK ){
1060 return TCL_ERROR;
1061 }
1062
1063 return TCL_OK;
1064}
1065
1066static int test_bind_text(
1067 void * clientData,
1068 Tcl_Interp *interp,
1069 int objc,
1070 Tcl_Obj *CONST objv[]
1071){
1072 sqlite3_stmt *pStmt;
1073 int idx;
1074 int bytes;
1075 char *value;
1076 int rc;
1077
1078 if( objc!=5 ){
1079 Tcl_AppendResult(interp, "wrong # args: should be \"",
1080 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>"
1081 " <bytes>", 0);
1082 return TCL_ERROR;
1083 }
1084
1085 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1086 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1087 value = Tcl_GetString(objv[3]);
1088 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
1089
1090 rc = sqlite3_bind_text(pStmt, idx, value, bytes, 1);
1091 if( rc!=SQLITE_OK ){
1092 return TCL_ERROR;
1093 }
1094
1095 return TCL_OK;
1096}
1097
1098static int test_bind_text16(
1099 void * clientData,
1100 Tcl_Interp *interp,
1101 int objc,
1102 Tcl_Obj *CONST objv[]
1103){
1104 sqlite3_stmt *pStmt;
1105 int idx;
1106 int bytes;
1107 char *value;
1108 int rc;
1109
1110 if( objc!=5 ){
1111 Tcl_AppendResult(interp, "wrong # args: should be \"",
1112 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>"
1113 " <bytes>", 0);
1114 return TCL_ERROR;
1115 }
1116
1117 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1118 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1119 value = Tcl_GetByteArrayFromObj(objv[3], 0);
1120 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
1121
1122 rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, 1);
1123 if( rc!=SQLITE_OK ){
1124 return TCL_ERROR;
1125 }
1126
1127 return TCL_OK;
1128}
1129
1130static int test_bind_blob(
1131 void * clientData,
1132 Tcl_Interp *interp,
1133 int objc,
1134 Tcl_Obj *CONST objv[]
1135){
1136 sqlite3_stmt *pStmt;
1137 int idx;
1138 int bytes;
1139 char *value;
1140 int rc;
1141
1142 if( objc!=5 ){
1143 Tcl_AppendResult(interp, "wrong # args: should be \"",
1144 Tcl_GetStringFromObj(objv[0], 0), " <STMT> <param no.> <value>"
1145 " <bytes>", 0);
1146 return TCL_ERROR;
1147 }
1148
1149 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1150 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1151 value = Tcl_GetString(objv[3]);
1152 if( Tcl_GetIntFromObj(interp, objv[2], &bytes) ) return TCL_ERROR;
1153
1154 rc = sqlite3_bind_blob(pStmt, idx, value, bytes, 1);
1155 if( rc!=SQLITE_OK ){
1156 return TCL_ERROR;
1157 }
1158
1159 return TCL_OK;
1160}
1161
drh99ee3602003-02-16 19:13:36 +00001162/*
danielk19776622cce2004-05-20 11:00:52 +00001163** Usage: sqlite3_errcode DB
1164**
1165** Return the string representation of the most recent sqlite3_* API
1166** error code. e.g. "SQLITE_ERROR".
1167*/
1168static int test_errcode(
1169 void * clientData,
1170 Tcl_Interp *interp,
1171 int objc,
1172 Tcl_Obj *CONST objv[]
1173){
1174 sqlite3 *db;
1175
1176 if( objc!=2 ){
1177 Tcl_AppendResult(interp, "wrong # args: should be \"",
1178 Tcl_GetString(objv[0]), " DB", 0);
1179 return TCL_ERROR;
1180 }
1181 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1182 Tcl_SetResult(interp, (char *)errorName(sqlite3_errcode(db)), 0);
1183 return TCL_OK;
1184}
1185
1186/*
1187** Usage: test_errmsg DB
1188**
1189** Returns the UTF-8 representation of the error message string for the
1190** most recent sqlite3_* API call.
1191*/
1192static int test_errmsg(
1193 void * clientData,
1194 Tcl_Interp *interp,
1195 int objc,
1196 Tcl_Obj *CONST objv[]
1197){
1198 sqlite *db;
1199 const char *zErr;
1200
1201 if( objc!=2 ){
1202 Tcl_AppendResult(interp, "wrong # args: should be \"",
1203 Tcl_GetString(objv[0]), " DB", 0);
1204 return TCL_ERROR;
1205 }
1206 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1207
1208 zErr = sqlite3_errmsg(db);
1209 Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
1210 return TCL_OK;
1211}
1212
1213/*
1214** Usage: test_errmsg16 DB
1215**
1216** Returns the UTF-16 representation of the error message string for the
1217** most recent sqlite3_* API call. This is a byte array object at the TCL
1218** level, and it includes the 0x00 0x00 terminator bytes at the end of the
1219** UTF-16 string.
1220*/
1221static int test_errmsg16(
1222 void * clientData,
1223 Tcl_Interp *interp,
1224 int objc,
1225 Tcl_Obj *CONST objv[]
1226){
1227 sqlite *db;
1228 const void *zErr;
1229 int bytes;
1230
1231 if( objc!=2 ){
1232 Tcl_AppendResult(interp, "wrong # args: should be \"",
1233 Tcl_GetString(objv[0]), " DB", 0);
1234 return TCL_ERROR;
1235 }
1236 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1237
1238 zErr = sqlite3_errmsg16(db);
1239 bytes = sqlite3utf16ByteLen(zErr, -1);
1240 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes));
1241 return TCL_OK;
1242}
1243
1244/*
1245** Usage: sqlite3_prepare DB sql bytes tailvar
1246**
1247** Compile up to <bytes> bytes of the supplied SQL string <sql> using
1248** database handle <DB>. The parameter <tailval> is the name of a global
1249** variable that is set to the unused portion of <sql> (if any). A
1250** STMT handle is returned.
1251*/
1252static int test_prepare(
1253 void * clientData,
1254 Tcl_Interp *interp,
1255 int objc,
1256 Tcl_Obj *CONST objv[]
1257){
1258 sqlite3 *db;
1259 const char *zSql;
1260 int bytes;
1261 const char *zTail = 0;
1262 sqlite3_stmt *pStmt = 0;
1263 char zBuf[50];
danielk19774ad17132004-05-21 01:47:26 +00001264 int rc;
danielk19776622cce2004-05-20 11:00:52 +00001265
1266 if( objc!=5 ){
1267 Tcl_AppendResult(interp, "wrong # args: should be \"",
1268 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
1269 return TCL_ERROR;
1270 }
1271 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1272 zSql = Tcl_GetString(objv[2]);
1273 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
1274
danielk19774ad17132004-05-21 01:47:26 +00001275 rc = sqlite3_prepare(db, zSql, bytes, &pStmt, &zTail);
danielk19776622cce2004-05-20 11:00:52 +00001276 if( zTail ){
1277 if( bytes>=0 ){
1278 bytes = bytes - (zTail-zSql);
1279 }
1280 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
1281 }
danielk19774ad17132004-05-21 01:47:26 +00001282 if( rc!=SQLITE_OK ){
1283 assert( pStmt==0 );
1284 sprintf(zBuf, "(%d) ", rc);
1285 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
1286 return TCL_ERROR;
1287 }
danielk19776622cce2004-05-20 11:00:52 +00001288
danielk19774ad17132004-05-21 01:47:26 +00001289 if( pStmt ){
1290 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
1291 Tcl_AppendResult(interp, zBuf, 0);
1292 }
danielk19776622cce2004-05-20 11:00:52 +00001293 return TCL_OK;
1294}
1295
1296/*
1297** Usage: sqlite3_prepare DB sql bytes tailvar
1298**
1299** Compile up to <bytes> bytes of the supplied SQL string <sql> using
1300** database handle <DB>. The parameter <tailval> is the name of a global
1301** variable that is set to the unused portion of <sql> (if any). A
1302** STMT handle is returned.
1303*/
1304static int test_prepare16(
1305 void * clientData,
1306 Tcl_Interp *interp,
1307 int objc,
1308 Tcl_Obj *CONST objv[]
1309){
1310 sqlite3 *db;
1311 const void *zSql;
1312 const void *zTail = 0;
1313 Tcl_Obj *pTail = 0;
1314 sqlite3_stmt *pStmt = 0;
1315 char zBuf[50];
1316 int bytes; /* The integer specified as arg 3 */
1317 int objlen; /* The byte-array length of arg 2 */
1318
1319 if( objc!=5 ){
1320 Tcl_AppendResult(interp, "wrong # args: should be \"",
1321 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
1322 return TCL_ERROR;
1323 }
1324 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1325 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
1326 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
1327
1328 if( SQLITE_OK!=sqlite3_prepare16(db, zSql, bytes, &pStmt, &zTail) ){
1329 return TCL_ERROR;
1330 }
1331
1332 if( zTail ){
1333 objlen = objlen - ((u8 *)zTail-(u8 *)zSql);
1334 }else{
1335 objlen = 0;
1336 }
1337 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
1338 Tcl_IncrRefCount(pTail);
1339 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
danielk19774ad17132004-05-21 01:47:26 +00001340 Tcl_DecrRefCount(pTail);
danielk19776622cce2004-05-20 11:00:52 +00001341
danielk19774ad17132004-05-21 01:47:26 +00001342 if( pStmt ){
1343 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
1344 }
danielk19776622cce2004-05-20 11:00:52 +00001345 Tcl_AppendResult(interp, zBuf, 0);
1346 return TCL_OK;
1347}
1348
danielk19774ad17132004-05-21 01:47:26 +00001349/*
1350** Usage: sqlite3_open filename ?options-list?
1351*/
1352static int test_open(
1353 void * clientData,
1354 Tcl_Interp *interp,
1355 int objc,
1356 Tcl_Obj *CONST objv[]
1357){
1358 const char *zFilename;
1359 sqlite3 *db;
1360 int rc;
1361 char zBuf[100];
1362
1363 if( objc!=3 && objc!=2 ){
1364 Tcl_AppendResult(interp, "wrong # args: should be \"",
1365 Tcl_GetString(objv[0]), " filename options-list", 0);
1366 return TCL_ERROR;
1367 }
1368
1369 zFilename = Tcl_GetString(objv[1]);
1370 rc = sqlite3_open_new(zFilename, &db, 0);
1371
1372 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR;
1373 Tcl_AppendResult(interp, zBuf, 0);
1374 return TCL_OK;
1375}
1376
1377/*
1378** Usage: sqlite3_open16 filename options
1379*/
1380static int test_open16(
1381 void * clientData,
1382 Tcl_Interp *interp,
1383 int objc,
1384 Tcl_Obj *CONST objv[]
1385){
1386 const void *zFilename;
1387 sqlite3 *db;
1388 int rc;
1389 char zBuf[100];
1390
1391 if( objc!=3 ){
1392 Tcl_AppendResult(interp, "wrong # args: should be \"",
1393 Tcl_GetString(objv[0]), " filename options-list", 0);
1394 return TCL_ERROR;
1395 }
1396
1397 zFilename = Tcl_GetByteArrayFromObj(objv[1], 0);
1398 rc = sqlite3_open16(zFilename, &db, 0);
1399
1400 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR;
1401 Tcl_AppendResult(interp, zBuf, 0);
1402 return TCL_OK;
1403}
drhd3d39e92004-05-20 22:16:29 +00001404
1405/*
danielk1977106bb232004-05-21 10:08:53 +00001406** Usage: sqlite3_step STMT
1407**
1408** Advance the statement to the next row.
1409*/
1410static int test_step_new(
1411 void * clientData,
1412 Tcl_Interp *interp,
1413 int objc,
1414 Tcl_Obj *CONST objv[]
1415){
1416 sqlite3_stmt *pStmt;
1417 int rc;
1418
1419 if( objc!=3 ){
1420 Tcl_AppendResult(interp, "wrong # args: should be \"",
1421 Tcl_GetString(objv[0]), " STMT", 0);
1422 return TCL_ERROR;
1423 }
1424
1425 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1426 rc = sqlite3_step_new(pStmt);
1427
1428 if( rc!=SQLITE_OK ) return TCL_ERROR;
1429 return TCL_OK;
1430}
1431
1432/*
drhd3d39e92004-05-20 22:16:29 +00001433** This is a collating function named "REVERSE" which sorts text
1434** in reverse order.
1435*/
1436static int reverseCollatingFunc(
1437 void *NotUsed,
1438 int nKey1, const void *pKey1,
1439 int nKey2, const void *pKey2
1440){
1441 int rc, n;
1442 n = nKey1<nKey2 ? nKey1 : nKey2;
1443 rc = memcmp(pKey1, pKey2, n);
1444 if( rc==0 ){
1445 rc = nKey1 - nKey2;
1446 }
1447 return -rc;
1448}
1449
1450/*
1451** Usage: add_reverse_collating_func DB
1452**
1453** This routine adds a collation named "REVERSE" to database given.
1454** REVERSE is used for testing only.
1455*/
1456static int reverse_collfunc(
1457 void * clientData,
1458 Tcl_Interp *interp,
1459 int objc,
1460 Tcl_Obj *CONST objv[]
1461){
1462 sqlite3 *db;
1463
1464 if( objc!=2 ){
1465 Tcl_WrongNumArgs(interp, 1, objv, "DB");
1466 return TCL_ERROR;
1467 }
1468 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1469 sqlite3ChangeCollatingFunction(db, "REVERSE", 7, 0, reverseCollatingFunc);
1470 return TCL_OK;
1471}
1472
1473
danielk19776622cce2004-05-20 11:00:52 +00001474/*
drhd1bf3512001-04-07 15:24:33 +00001475** Register commands with the TCL interpreter.
1476*/
1477int Sqlitetest1_Init(Tcl_Interp *interp){
danielk19776f8a5032004-05-10 10:34:51 +00001478 extern int sqlite3_search_count;
1479 extern int sqlite3_interrupt_count;
1480 extern int sqlite3_open_file_count;
1481 extern int sqlite3_current_time;
drhc2eef3b2002-08-31 18:53:06 +00001482 static struct {
1483 char *zName;
1484 Tcl_CmdProc *xProc;
1485 } aCmd[] = {
drhd3d39e92004-05-20 22:16:29 +00001486 { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int },
1487 { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str },
1488 { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double },
1489 { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled },
1490 { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z },
danielk19774ad17132004-05-21 01:47:26 +00001491// { "sqlite3_open", (Tcl_CmdProc*)sqlite_test_open },
drhd3d39e92004-05-20 22:16:29 +00001492 { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid },
1493 { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf },
1494 { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf },
1495 { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close },
1496 { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function },
1497 { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate },
1498 { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func },
1499 { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort },
1500 { "sqlite_datatypes", (Tcl_CmdProc*)sqlite_datatypes },
drhc2eef3b2002-08-31 18:53:06 +00001501#ifdef MEMORY_DEBUG
drhd3d39e92004-05-20 22:16:29 +00001502 { "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail },
1503 { "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat },
drhc2eef3b2002-08-31 18:53:06 +00001504#endif
danielk19774ad17132004-05-21 01:47:26 +00001505 { "sqlite_step", (Tcl_CmdProc*)test_step },
danielk1977106bb232004-05-21 10:08:53 +00001506// { "sqlite_finalize", (Tcl_CmdProc*)test_finalize },
danielk19774ad17132004-05-21 01:47:26 +00001507 { "sqlite_bind", (Tcl_CmdProc*)test_bind },
danielk1977106bb232004-05-21 10:08:53 +00001508// { "sqlite_reset", (Tcl_CmdProc*)test_reset },
danielk19774ad17132004-05-21 01:47:26 +00001509 { "breakpoint", (Tcl_CmdProc*)test_breakpoint },
drhc2eef3b2002-08-31 18:53:06 +00001510 };
danielk197751e3d8e2004-05-20 01:12:34 +00001511 static struct {
1512 char *zName;
1513 Tcl_ObjCmdProc *xProc;
1514 } aObjCmd[] = {
1515 { "sqlite3_bind_int32", (Tcl_ObjCmdProc*)test_bind_int32 },
1516 { "sqlite3_bind_int64", (Tcl_ObjCmdProc*)test_bind_int64 },
1517 { "sqlite3_bind_double", (Tcl_ObjCmdProc*)test_bind_double },
1518 { "sqlite3_bind_null", (Tcl_ObjCmdProc*)test_bind_null },
1519 { "sqlite3_bind_text", (Tcl_ObjCmdProc*)test_bind_text },
1520 { "sqlite3_bind_text16", (Tcl_ObjCmdProc*)test_bind_text16 },
1521 { "sqlite3_bind_blob", (Tcl_ObjCmdProc*)test_bind_blob },
danielk19776622cce2004-05-20 11:00:52 +00001522 { "sqlite3_errcode", (Tcl_ObjCmdProc*)test_errcode },
1523 { "sqlite3_errmsg", (Tcl_ObjCmdProc*)test_errmsg },
1524 { "sqlite3_errmsg16", (Tcl_ObjCmdProc*)test_errmsg16 },
1525 { "sqlite3_prepare", (Tcl_ObjCmdProc*)test_prepare },
1526 { "sqlite3_prepare16", (Tcl_ObjCmdProc*)test_prepare16 },
danielk19774ad17132004-05-21 01:47:26 +00001527 { "sqlite3_open", (Tcl_ObjCmdProc*)test_open },
1528 { "sqlite3_open16", (Tcl_ObjCmdProc*)test_open16 },
danielk1977106bb232004-05-21 10:08:53 +00001529 { "sqlite3_finalize", (Tcl_ObjCmdProc*)test_finalize },
1530 { "sqlite3_reset", (Tcl_ObjCmdProc*)test_reset },
1531 { "sqlite3_step", (Tcl_ObjCmdProc*)test_step_new },
drhd3d39e92004-05-20 22:16:29 +00001532 { "add_reverse_collating_func", (Tcl_ObjCmdProc*)reverse_collfunc },
danielk197751e3d8e2004-05-20 01:12:34 +00001533 };
drhc2eef3b2002-08-31 18:53:06 +00001534 int i;
1535
1536 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
1537 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
1538 }
danielk197751e3d8e2004-05-20 01:12:34 +00001539 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
1540 Tcl_CreateObjCommand(interp, aObjCmd[i].zName, aObjCmd[i].xProc, 0, 0);
1541 }
danielk19776490beb2004-05-11 06:17:21 +00001542 Tcl_LinkVar(interp, "sqlite_search_count",
danielk19776f8a5032004-05-10 10:34:51 +00001543 (char*)&sqlite3_search_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00001544 Tcl_LinkVar(interp, "sqlite_interrupt_count",
danielk19776f8a5032004-05-10 10:34:51 +00001545 (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00001546 Tcl_LinkVar(interp, "sqlite_open_file_count",
danielk19776f8a5032004-05-10 10:34:51 +00001547 (char*)&sqlite3_open_file_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00001548 Tcl_LinkVar(interp, "sqlite_current_time",
danielk19776f8a5032004-05-10 10:34:51 +00001549 (char*)&sqlite3_current_time, TCL_LINK_INT);
drh7c972de2003-09-06 22:18:07 +00001550 Tcl_LinkVar(interp, "sqlite_static_bind_value",
1551 (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
drhd1bf3512001-04-07 15:24:33 +00001552 return TCL_OK;
1553}