blob: 70c2482f70cdb4561441a9ca636bfa85fdf90190 [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**
drhfe63d1c2004-09-08 20:13:04 +000016** $Id: test1.c,v 1.103 2004/09/08 20:13:05 drh 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
danielk19776622cce2004-05-20 11:00:52 +000024static const char * errorName(int rc){
25 const char *zName = 0;
26 switch( rc ){
27 case SQLITE_OK: zName = "SQLITE_OK"; break;
28 case SQLITE_ERROR: zName = "SQLITE_ERROR"; break;
29 case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break;
30 case SQLITE_PERM: zName = "SQLITE_PERM"; break;
31 case SQLITE_ABORT: zName = "SQLITE_ABORT"; break;
32 case SQLITE_BUSY: zName = "SQLITE_BUSY"; break;
33 case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break;
34 case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break;
35 case SQLITE_READONLY: zName = "SQLITE_READONLY"; break;
36 case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break;
37 case SQLITE_IOERR: zName = "SQLITE_IOERR"; break;
38 case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break;
39 case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break;
40 case SQLITE_FULL: zName = "SQLITE_FULL"; break;
41 case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break;
42 case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
43 case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break;
44 case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break;
45 case SQLITE_TOOBIG: zName = "SQLITE_TOOBIG"; break;
46 case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break;
47 case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break;
48 case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break;
49 case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break;
50 case SQLITE_AUTH: zName = "SQLITE_AUTH"; break;
51 case SQLITE_FORMAT: zName = "SQLITE_FORMAT"; break;
52 case SQLITE_RANGE: zName = "SQLITE_RANGE"; break;
53 case SQLITE_ROW: zName = "SQLITE_ROW"; break;
54 case SQLITE_DONE: zName = "SQLITE_DONE"; break;
danielk1977312d6b32004-06-29 13:18:23 +000055 case SQLITE_NOTADB: zName = "SQLITE_NOTADB"; break;
danielk19776622cce2004-05-20 11:00:52 +000056 default: zName = "SQLITE_Unknown"; break;
57 }
58 return zName;
59}
60
drhd1bf3512001-04-07 15:24:33 +000061/*
drh9bb575f2004-09-06 17:24:11 +000062** Decode a pointer to an sqlite3 object.
drhb86ccfb2003-01-28 23:13:10 +000063*/
drh9bb575f2004-09-06 17:24:11 +000064static int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
drhfe63d1c2004-09-08 20:13:04 +000065 *ppDb = (sqlite3*)sqlite3TextToPtr(zA);
drhb86ccfb2003-01-28 23:13:10 +000066 return TCL_OK;
67}
68
69/*
danielk197751e3d8e2004-05-20 01:12:34 +000070** Decode a pointer to an sqlite3_stmt object.
71*/
72static int getStmtPointer(
73 Tcl_Interp *interp,
74 const char *zArg,
75 sqlite3_stmt **ppStmt
76){
drhfe63d1c2004-09-08 20:13:04 +000077 *ppStmt = (sqlite3_stmt*)sqlite3TextToPtr(zArg);
danielk197751e3d8e2004-05-20 01:12:34 +000078 return TCL_OK;
79}
80
81/*
danielk19779a1d0ab2004-06-01 14:09:28 +000082** Decode a pointer to an sqlite3_stmt object.
83*/
84static int getFilePointer(
85 Tcl_Interp *interp,
86 const char *zArg,
87 OsFile **ppFile
88){
drhfe63d1c2004-09-08 20:13:04 +000089 *ppFile = (OsFile*)sqlite3TextToPtr(zArg);
danielk19779a1d0ab2004-06-01 14:09:28 +000090 return TCL_OK;
91}
92
93/*
drh7d8085a2003-04-26 13:19:38 +000094** Generate a text representation of a pointer that can be understood
95** by the getDbPointer and getVmPointer routines above.
96**
97** The problem is, on some machines (Solaris) if you do a printf with
98** "%p" you cannot turn around and do a scanf with the same "%p" and
99** get your pointer back. You have to prepend a "0x" before it will
100** work. Or at least that is what is reported to me (drh). But this
101** behavior varies from machine to machine. The solution used her is
102** to test the string right after it is generated to see if it can be
103** understood by scanf, and if not, try prepending an "0x" to see if
104** that helps. If nothing works, a fatal error is generated.
105*/
106static int makePointerStr(Tcl_Interp *interp, char *zPtr, void *p){
drhfe63d1c2004-09-08 20:13:04 +0000107 sqlite3_snprintf(100, zPtr, "%p", p);
drh7d8085a2003-04-26 13:19:38 +0000108 return TCL_OK;
109}
110
111/*
danielk19776f8a5032004-05-10 10:34:51 +0000112** The callback routine for sqlite3_exec_printf().
drhd1bf3512001-04-07 15:24:33 +0000113*/
114static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){
115 Tcl_DString *str = (Tcl_DString*)pArg;
116 int i;
117
118 if( Tcl_DStringLength(str)==0 ){
119 for(i=0; i<argc; i++){
120 Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL");
121 }
122 }
123 for(i=0; i<argc; i++){
124 Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL");
125 }
126 return 0;
127}
128
129/*
danielk19776f8a5032004-05-10 10:34:51 +0000130** Usage: sqlite3_exec_printf DB FORMAT STRING
drhd1bf3512001-04-07 15:24:33 +0000131**
danielk19776f8a5032004-05-10 10:34:51 +0000132** Invoke the sqlite3_exec_printf() interface using the open database
drhd1bf3512001-04-07 15:24:33 +0000133** DB. The SQL is the string FORMAT. The format string should contain
134** one %s or %q. STRING is the value inserted into %s or %q.
135*/
136static int test_exec_printf(
137 void *NotUsed,
138 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
139 int argc, /* Number of arguments */
140 char **argv /* Text of each argument */
141){
drh9bb575f2004-09-06 17:24:11 +0000142 sqlite3 *db;
drhd1bf3512001-04-07 15:24:33 +0000143 Tcl_DString str;
144 int rc;
145 char *zErr = 0;
drh1211de32004-07-26 12:24:22 +0000146 char *zSql;
drhd1bf3512001-04-07 15:24:33 +0000147 char zBuf[30];
148 if( argc!=4 ){
149 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
150 " DB FORMAT STRING", 0);
151 return TCL_ERROR;
152 }
drhb86ccfb2003-01-28 23:13:10 +0000153 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000154 Tcl_DStringInit(&str);
drh1211de32004-07-26 12:24:22 +0000155 zSql = sqlite3_mprintf(argv[2], argv[3]);
156 rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
157 sqlite3_free(zSql);
drhd1bf3512001-04-07 15:24:33 +0000158 sprintf(zBuf, "%d", rc);
159 Tcl_AppendElement(interp, zBuf);
160 Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
161 Tcl_DStringFree(&str);
162 if( zErr ) free(zErr);
163 return TCL_OK;
164}
165
166/*
danielk19776f8a5032004-05-10 10:34:51 +0000167** Usage: sqlite3_mprintf_z_test SEPARATOR ARG0 ARG1 ...
drhd93d8a82003-06-16 03:08:18 +0000168**
169** Test the %z format of mprintf(). Use multiple mprintf() calls to
170** concatenate arg0 through argn using separator as the separator.
171** Return the result.
172*/
173static int test_mprintf_z(
174 void *NotUsed,
175 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
176 int argc, /* Number of arguments */
177 char **argv /* Text of each argument */
178){
179 char *zResult = 0;
180 int i;
181
182 for(i=2; i<argc; i++){
danielk19774adee202004-05-08 08:23:19 +0000183 zResult = sqlite3MPrintf("%z%s%s", zResult, argv[1], argv[i]);
drhd93d8a82003-06-16 03:08:18 +0000184 }
185 Tcl_AppendResult(interp, zResult, 0);
drh5f968432004-02-21 19:02:30 +0000186 sqliteFree(zResult);
drhd93d8a82003-06-16 03:08:18 +0000187 return TCL_OK;
188}
189
190/*
danielk19776f8a5032004-05-10 10:34:51 +0000191** Usage: sqlite3_get_table_printf DB FORMAT STRING
drhd1bf3512001-04-07 15:24:33 +0000192**
danielk19776f8a5032004-05-10 10:34:51 +0000193** Invoke the sqlite3_get_table_printf() interface using the open database
drhd1bf3512001-04-07 15:24:33 +0000194** DB. The SQL is the string FORMAT. The format string should contain
195** one %s or %q. STRING is the value inserted into %s or %q.
196*/
197static int test_get_table_printf(
198 void *NotUsed,
199 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
200 int argc, /* Number of arguments */
201 char **argv /* Text of each argument */
202){
drh9bb575f2004-09-06 17:24:11 +0000203 sqlite3 *db;
drhd1bf3512001-04-07 15:24:33 +0000204 Tcl_DString str;
205 int rc;
206 char *zErr = 0;
207 int nRow, nCol;
208 char **aResult;
209 int i;
210 char zBuf[30];
drh1211de32004-07-26 12:24:22 +0000211 char *zSql;
drhd1bf3512001-04-07 15:24:33 +0000212 if( argc!=4 ){
213 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
214 " DB FORMAT STRING", 0);
215 return TCL_ERROR;
216 }
drhb86ccfb2003-01-28 23:13:10 +0000217 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000218 Tcl_DStringInit(&str);
drh1211de32004-07-26 12:24:22 +0000219 zSql = sqlite3_mprintf(argv[2],argv[3]);
220 rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr);
221 sqlite3_free(zSql);
drhd1bf3512001-04-07 15:24:33 +0000222 sprintf(zBuf, "%d", rc);
223 Tcl_AppendElement(interp, zBuf);
224 if( rc==SQLITE_OK ){
225 sprintf(zBuf, "%d", nRow);
226 Tcl_AppendElement(interp, zBuf);
227 sprintf(zBuf, "%d", nCol);
228 Tcl_AppendElement(interp, zBuf);
229 for(i=0; i<(nRow+1)*nCol; i++){
230 Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL");
231 }
232 }else{
233 Tcl_AppendElement(interp, zErr);
234 }
danielk19776f8a5032004-05-10 10:34:51 +0000235 sqlite3_free_table(aResult);
drhd1bf3512001-04-07 15:24:33 +0000236 if( zErr ) free(zErr);
237 return TCL_OK;
238}
239
drhaf9ff332002-01-16 21:00:27 +0000240
241/*
danielk19776f8a5032004-05-10 10:34:51 +0000242** Usage: sqlite3_last_insert_rowid DB
drhaf9ff332002-01-16 21:00:27 +0000243**
244** Returns the integer ROWID of the most recent insert.
245*/
246static int test_last_rowid(
247 void *NotUsed,
248 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
249 int argc, /* Number of arguments */
250 char **argv /* Text of each argument */
251){
drh9bb575f2004-09-06 17:24:11 +0000252 sqlite3 *db;
drhaf9ff332002-01-16 21:00:27 +0000253 char zBuf[30];
254
255 if( argc!=2 ){
256 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0);
257 return TCL_ERROR;
258 }
drhb86ccfb2003-01-28 23:13:10 +0000259 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk1977c572ef72004-05-27 09:28:41 +0000260 sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db));
drhaf9ff332002-01-16 21:00:27 +0000261 Tcl_AppendResult(interp, zBuf, 0);
262 return SQLITE_OK;
263}
264
drhd1bf3512001-04-07 15:24:33 +0000265/*
drh25d65432004-07-22 15:02:25 +0000266** Usage: sqlite3_key DB KEY
267**
268** Set the codec key.
269*/
270static int test_key(
271 void *NotUsed,
272 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
273 int argc, /* Number of arguments */
274 char **argv /* Text of each argument */
275){
drh9bb575f2004-09-06 17:24:11 +0000276 sqlite3 *db;
drh25d65432004-07-22 15:02:25 +0000277 const char *zKey;
278 int nKey;
279 if( argc!=3 ){
280 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
281 " FILENAME\"", 0);
282 return TCL_ERROR;
283 }
284 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
285 zKey = argv[2];
286 nKey = strlen(zKey);
287#ifdef SQLITE_HAS_CODEC
288 sqlite3_key(db, zKey, nKey);
289#endif
290 return TCL_OK;
291}
292
293/*
294** Usage: sqlite3_rekey DB KEY
295**
296** Change the codec key.
297*/
298static int test_rekey(
299 void *NotUsed,
300 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
301 int argc, /* Number of arguments */
302 char **argv /* Text of each argument */
303){
drh9bb575f2004-09-06 17:24:11 +0000304 sqlite3 *db;
drh25d65432004-07-22 15:02:25 +0000305 const char *zKey;
306 int nKey;
307 if( argc!=3 ){
308 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
309 " FILENAME\"", 0);
310 return TCL_ERROR;
311 }
312 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
313 zKey = argv[2];
314 nKey = strlen(zKey);
315#ifdef SQLITE_HAS_CODEC
316 sqlite3_rekey(db, zKey, nKey);
317#endif
318 return TCL_OK;
319}
320
321/*
danielk19776f8a5032004-05-10 10:34:51 +0000322** Usage: sqlite3_close DB
drhd1bf3512001-04-07 15:24:33 +0000323**
danielk19776f8a5032004-05-10 10:34:51 +0000324** Closes the database opened by sqlite3_open.
drhd1bf3512001-04-07 15:24:33 +0000325*/
326static int sqlite_test_close(
327 void *NotUsed,
328 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
329 int argc, /* Number of arguments */
330 char **argv /* Text of each argument */
331){
drh9bb575f2004-09-06 17:24:11 +0000332 sqlite3 *db;
danielk197796d81f92004-06-19 03:33:57 +0000333 int rc;
drhd1bf3512001-04-07 15:24:33 +0000334 if( argc!=2 ){
335 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
336 " FILENAME\"", 0);
337 return TCL_ERROR;
338 }
drhb86ccfb2003-01-28 23:13:10 +0000339 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk197796d81f92004-06-19 03:33:57 +0000340 rc = sqlite3_close(db);
danielk1977f9d64d22004-06-19 08:18:07 +0000341 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
drhd1bf3512001-04-07 15:24:33 +0000342 return TCL_OK;
343}
344
345/*
drhc22bd472002-05-10 13:14:07 +0000346** Implementation of the x_coalesce() function.
347** Return the first argument non-NULL argument.
348*/
danielk19770ae8b832004-05-25 12:05:56 +0000349static void ifnullFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
drhc22bd472002-05-10 13:14:07 +0000350 int i;
351 for(i=0; i<argc; i++){
drh9c054832004-05-31 18:51:57 +0000352 if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
danielk1977d8123362004-06-12 09:25:12 +0000353 sqlite3_result_text(context, sqlite3_value_text(argv[i]), -1,
354 SQLITE_TRANSIENT);
drhc22bd472002-05-10 13:14:07 +0000355 break;
356 }
357 }
358}
359
360/*
drhd1d9fc32004-01-07 19:24:48 +0000361** A structure into which to accumulate text.
362*/
363struct dstr {
364 int nAlloc; /* Space allocated */
365 int nUsed; /* Space used */
366 char *z; /* The space */
367};
368
369/*
370** Append text to a dstr
371*/
372static void dstrAppend(struct dstr *p, const char *z, int divider){
373 int n = strlen(z);
374 if( p->nUsed + n + 2 > p->nAlloc ){
375 char *zNew;
376 p->nAlloc = p->nAlloc*2 + n + 200;
377 zNew = sqliteRealloc(p->z, p->nAlloc);
378 if( zNew==0 ){
379 sqliteFree(p->z);
380 memset(p, 0, sizeof(*p));
381 return;
382 }
383 p->z = zNew;
384 }
385 if( divider && p->nUsed>0 ){
386 p->z[p->nUsed++] = divider;
387 }
388 memcpy(&p->z[p->nUsed], z, n+1);
389 p->nUsed += n;
390}
391
392/*
danielk19774adee202004-05-08 08:23:19 +0000393** Invoked for each callback from sqlite3ExecFunc
drhd1d9fc32004-01-07 19:24:48 +0000394*/
395static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){
396 struct dstr *p = (struct dstr*)pData;
397 int i;
398 for(i=0; i<argc; i++){
399 if( argv[i]==0 ){
400 dstrAppend(p, "NULL", ' ');
401 }else{
402 dstrAppend(p, argv[i], ' ');
403 }
404 }
405 return 0;
406}
407
408/*
danielk1977e35ee192004-06-26 09:50:11 +0000409** Implementation of the x_sqlite_exec() function. This function takes
drhc22bd472002-05-10 13:14:07 +0000410** a single argument and attempts to execute that argument as SQL code.
drh6cbe1f12002-07-01 00:31:36 +0000411** This is illegal and should set the SQLITE_MISUSE flag on the database.
drhd1d9fc32004-01-07 19:24:48 +0000412**
danielk19776f8a5032004-05-10 10:34:51 +0000413** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec()
drhd1d9fc32004-01-07 19:24:48 +0000414** from within a function call.
drhc22bd472002-05-10 13:14:07 +0000415**
416** This routine simulates the effect of having two threads attempt to
417** use the same database at the same time.
418*/
danielk197751ad0ec2004-05-24 12:39:02 +0000419static void sqlite3ExecFunc(
danielk19770ae8b832004-05-25 12:05:56 +0000420 sqlite3_context *context,
danielk197751ad0ec2004-05-24 12:39:02 +0000421 int argc,
422 sqlite3_value **argv
423){
drhd1d9fc32004-01-07 19:24:48 +0000424 struct dstr x;
425 memset(&x, 0, sizeof(x));
drh9bb575f2004-09-06 17:24:11 +0000426 sqlite3_exec((sqlite3*)sqlite3_user_data(context),
drh4f26d6c2004-05-26 23:25:30 +0000427 sqlite3_value_text(argv[0]),
drhd1d9fc32004-01-07 19:24:48 +0000428 execFuncCallback, &x, 0);
danielk1977d8123362004-06-12 09:25:12 +0000429 sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT);
drhd1d9fc32004-01-07 19:24:48 +0000430 sqliteFree(x.z);
drhc22bd472002-05-10 13:14:07 +0000431}
432
433/*
434** Usage: sqlite_test_create_function DB
435**
danielk19776f8a5032004-05-10 10:34:51 +0000436** Call the sqlite3_create_function API on the given database in order
drhc22bd472002-05-10 13:14:07 +0000437** to create a function named "x_coalesce". This function does the same thing
438** as the "coalesce" function. This function also registers an SQL function
danielk1977e35ee192004-06-26 09:50:11 +0000439** named "x_sqlite_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec()
drhc22bd472002-05-10 13:14:07 +0000440** in this way is illegal recursion and should raise an SQLITE_MISUSE error.
441** The effect is similar to trying to use the same database connection from
442** two threads at the same time.
443**
444** The original motivation for this routine was to be able to call the
danielk19776f8a5032004-05-10 10:34:51 +0000445** sqlite3_create_function function while a query is in progress in order
drhc22bd472002-05-10 13:14:07 +0000446** to test the SQLITE_MISUSE detection logic.
447*/
drhc2eef3b2002-08-31 18:53:06 +0000448static int test_create_function(
drhc22bd472002-05-10 13:14:07 +0000449 void *NotUsed,
450 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
451 int argc, /* Number of arguments */
452 char **argv /* Text of each argument */
453){
drh9bb575f2004-09-06 17:24:11 +0000454 sqlite3 *db;
danielk1977312d6b32004-06-29 13:18:23 +0000455 sqlite3_value *pVal;
drh9bb575f2004-09-06 17:24:11 +0000456 extern void Md5_Register(sqlite3*);
danielk1977312d6b32004-06-29 13:18:23 +0000457
drhc22bd472002-05-10 13:14:07 +0000458 if( argc!=2 ){
459 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
460 " FILENAME\"", 0);
461 return TCL_ERROR;
462 }
drhb86ccfb2003-01-28 23:13:10 +0000463 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk1977312d6b32004-06-29 13:18:23 +0000464 sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0,
danielk1977d8123362004-06-12 09:25:12 +0000465 ifnullFunc, 0, 0);
danielk1977312d6b32004-06-29 13:18:23 +0000466
467 /* Use the sqlite3_create_function16() API here. Mainly for fun, but also
468 ** because it is not tested anywhere else. */
469 pVal = sqlite3ValueNew();
470 sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC);
471 sqlite3_create_function16(db, sqlite3ValueText(pVal, SQLITE_UTF16NATIVE),
472 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
473 sqlite3ValueFree(pVal);
drhc22bd472002-05-10 13:14:07 +0000474 return TCL_OK;
475}
476
477/*
478** Routines to implement the x_count() aggregate function.
479*/
480typedef struct CountCtx CountCtx;
481struct CountCtx {
482 int n;
483};
danielk19770ae8b832004-05-25 12:05:56 +0000484static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
drhc22bd472002-05-10 13:14:07 +0000485 CountCtx *p;
drh4f26d6c2004-05-26 23:25:30 +0000486 p = sqlite3_aggregate_context(context, sizeof(*p));
drh9c054832004-05-31 18:51:57 +0000487 if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){
drhc22bd472002-05-10 13:14:07 +0000488 p->n++;
489 }
490}
danielk19770ae8b832004-05-25 12:05:56 +0000491static void countFinalize(sqlite3_context *context){
drhc22bd472002-05-10 13:14:07 +0000492 CountCtx *p;
drh4f26d6c2004-05-26 23:25:30 +0000493 p = sqlite3_aggregate_context(context, sizeof(*p));
danielk1977c572ef72004-05-27 09:28:41 +0000494 sqlite3_result_int(context, p ? p->n : 0);
drhc22bd472002-05-10 13:14:07 +0000495}
496
497/*
498** Usage: sqlite_test_create_aggregate DB
499**
danielk19776f8a5032004-05-10 10:34:51 +0000500** Call the sqlite3_create_function API on the given database in order
drhc22bd472002-05-10 13:14:07 +0000501** to create a function named "x_count". This function does the same thing
502** as the "md5sum" function.
503**
504** The original motivation for this routine was to be able to call the
danielk19776f8a5032004-05-10 10:34:51 +0000505** sqlite3_create_aggregate function while a query is in progress in order
drhc22bd472002-05-10 13:14:07 +0000506** to test the SQLITE_MISUSE detection logic.
507*/
drhc2eef3b2002-08-31 18:53:06 +0000508static int test_create_aggregate(
drhc22bd472002-05-10 13:14:07 +0000509 void *NotUsed,
510 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
511 int argc, /* Number of arguments */
512 char **argv /* Text of each argument */
513){
drh9bb575f2004-09-06 17:24:11 +0000514 sqlite3 *db;
drhc22bd472002-05-10 13:14:07 +0000515 if( argc!=2 ){
516 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
517 " FILENAME\"", 0);
518 return TCL_ERROR;
519 }
drhb86ccfb2003-01-28 23:13:10 +0000520 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk1977f9d64d22004-06-19 08:18:07 +0000521 sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0,
danielk1977d8123362004-06-12 09:25:12 +0000522 countStep,countFinalize);
danielk1977f9d64d22004-06-19 08:18:07 +0000523 sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0,
danielk1977d8123362004-06-12 09:25:12 +0000524 countStep,countFinalize);
drhc22bd472002-05-10 13:14:07 +0000525 return TCL_OK;
526}
527
528
529
530/*
danielk19776f8a5032004-05-10 10:34:51 +0000531** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER
drhd1bf3512001-04-07 15:24:33 +0000532**
533** Call mprintf with three integer arguments
534*/
danielk19776f8a5032004-05-10 10:34:51 +0000535static int sqlite3_mprintf_int(
drhd1bf3512001-04-07 15:24:33 +0000536 void *NotUsed,
537 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
538 int argc, /* Number of arguments */
539 char **argv /* Text of each argument */
540){
541 int a[3], i;
542 char *z;
543 if( argc!=5 ){
544 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
545 " FORMAT INT INT INT\"", 0);
546 return TCL_ERROR;
547 }
548 for(i=2; i<5; i++){
549 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
550 }
danielk19776f8a5032004-05-10 10:34:51 +0000551 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
drhd1bf3512001-04-07 15:24:33 +0000552 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000553 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +0000554 return TCL_OK;
555}
556
557/*
drh9d213ef2004-06-30 04:02:11 +0000558** If zNum represents an integer that will fit in 64-bits, then set
559** *pValue to that integer and return true. Otherwise return false.
560*/
561static int sqlite3GetInt64(const char *zNum, i64 *pValue){
562 if( sqlite3FitsIn64Bits(zNum) ){
563 sqlite3atoi64(zNum, pValue);
564 return 1;
565 }
566 return 0;
567}
568
569/*
drhe9707672004-06-25 01:10:48 +0000570** Usage: sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER
571**
572** Call mprintf with three 64-bit integer arguments
573*/
574static int sqlite3_mprintf_int64(
575 void *NotUsed,
576 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
577 int argc, /* Number of arguments */
578 char **argv /* Text of each argument */
579){
580 int i;
581 sqlite_int64 a[3];
582 char *z;
583 if( argc!=5 ){
584 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
585 " FORMAT INT INT INT\"", 0);
586 return TCL_ERROR;
587 }
588 for(i=2; i<5; i++){
589 if( !sqlite3GetInt64(argv[i], &a[i-2]) ){
590 Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0);
591 return TCL_ERROR;
592 }
593 }
594 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
595 Tcl_AppendResult(interp, z, 0);
596 sqlite3_free(z);
597 return TCL_OK;
598}
599
600/*
danielk19776f8a5032004-05-10 10:34:51 +0000601** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING
drhd1bf3512001-04-07 15:24:33 +0000602**
603** Call mprintf with two integer arguments and one string argument
604*/
danielk19776f8a5032004-05-10 10:34:51 +0000605static int sqlite3_mprintf_str(
drhd1bf3512001-04-07 15:24:33 +0000606 void *NotUsed,
607 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
608 int argc, /* Number of arguments */
609 char **argv /* Text of each argument */
610){
611 int a[3], i;
612 char *z;
chwf220b242002-06-16 04:54:28 +0000613 if( argc<4 || argc>5 ){
drhd1bf3512001-04-07 15:24:33 +0000614 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
chwf220b242002-06-16 04:54:28 +0000615 " FORMAT INT INT ?STRING?\"", 0);
drhd1bf3512001-04-07 15:24:33 +0000616 return TCL_ERROR;
617 }
618 for(i=2; i<4; i++){
619 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
620 }
danielk19776f8a5032004-05-10 10:34:51 +0000621 z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL);
drhd1bf3512001-04-07 15:24:33 +0000622 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000623 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +0000624 return TCL_OK;
625}
626
627/*
danielk19776f8a5032004-05-10 10:34:51 +0000628** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER DOUBLE
drhd1bf3512001-04-07 15:24:33 +0000629**
630** Call mprintf with two integer arguments and one double argument
631*/
danielk19776f8a5032004-05-10 10:34:51 +0000632static int sqlite3_mprintf_double(
drhd1bf3512001-04-07 15:24:33 +0000633 void *NotUsed,
634 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
635 int argc, /* Number of arguments */
636 char **argv /* Text of each argument */
637){
638 int a[3], i;
639 double r;
640 char *z;
641 if( argc!=5 ){
642 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
643 " FORMAT INT INT STRING\"", 0);
644 return TCL_ERROR;
645 }
646 for(i=2; i<4; i++){
647 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
648 }
649 if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
danielk19776f8a5032004-05-10 10:34:51 +0000650 z = sqlite3_mprintf(argv[1], a[0], a[1], r);
drhd1bf3512001-04-07 15:24:33 +0000651 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000652 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +0000653 return TCL_OK;
654}
655
656/*
danielk19776f8a5032004-05-10 10:34:51 +0000657** Usage: sqlite3_mprintf_str FORMAT DOUBLE DOUBLE
drhb621c232004-02-21 19:41:04 +0000658**
659** Call mprintf with a single double argument which is the product of the
660** two arguments given above. This is used to generate overflow and underflow
661** doubles to test that they are converted properly.
662*/
danielk19776f8a5032004-05-10 10:34:51 +0000663static int sqlite3_mprintf_scaled(
drhb621c232004-02-21 19:41:04 +0000664 void *NotUsed,
665 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
666 int argc, /* Number of arguments */
667 char **argv /* Text of each argument */
668){
669 int i;
670 double r[2];
671 char *z;
672 if( argc!=4 ){
673 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
674 " FORMAT DOUBLE DOUBLE\"", 0);
675 return TCL_ERROR;
676 }
677 for(i=2; i<4; i++){
678 if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR;
679 }
danielk19776f8a5032004-05-10 10:34:51 +0000680 z = sqlite3_mprintf(argv[1], r[0]*r[1]);
drhb621c232004-02-21 19:41:04 +0000681 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000682 sqlite3_free(z);
drhb621c232004-02-21 19:41:04 +0000683 return TCL_OK;
684}
685
686/*
drhe29b1a02004-07-17 21:56:09 +0000687** Usage: sqlite3_mprintf_stronly FORMAT STRING
688**
689** Call mprintf with a single double argument which is the product of the
690** two arguments given above. This is used to generate overflow and underflow
691** doubles to test that they are converted properly.
692*/
693static int sqlite3_mprintf_stronly(
694 void *NotUsed,
695 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
696 int argc, /* Number of arguments */
697 char **argv /* Text of each argument */
698){
699 char *z;
700 if( argc!=3 ){
701 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
702 " FORMAT STRING\"", 0);
703 return TCL_ERROR;
704 }
705 z = sqlite3_mprintf(argv[1], argv[2]);
706 Tcl_AppendResult(interp, z, 0);
707 sqlite3_free(z);
708 return TCL_OK;
709}
710
711/*
drhdaffd0e2001-04-11 14:28:42 +0000712** Usage: sqlite_malloc_fail N
713**
drhafa4a022001-09-24 03:12:39 +0000714** Rig sqliteMalloc() to fail on the N-th call. Turn off this mechanism
danielk19776f8a5032004-05-10 10:34:51 +0000715** and reset the sqlite3_malloc_failed variable is N==0.
drhdaffd0e2001-04-11 14:28:42 +0000716*/
drhfaa57ac2004-06-09 14:01:51 +0000717#ifdef SQLITE_DEBUG
drhdaffd0e2001-04-11 14:28:42 +0000718static int sqlite_malloc_fail(
719 void *NotUsed,
720 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
721 int argc, /* Number of arguments */
722 char **argv /* Text of each argument */
723){
724 int n;
725 if( argc!=2 ){
726 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0);
727 return TCL_ERROR;
728 }
729 if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
danielk19776f8a5032004-05-10 10:34:51 +0000730 sqlite3_iMallocFail = n;
731 sqlite3_malloc_failed = 0;
drhdaffd0e2001-04-11 14:28:42 +0000732 return TCL_OK;
733}
734#endif
735
736/*
737** Usage: sqlite_malloc_stat
738**
739** Return the number of prior calls to sqliteMalloc() and sqliteFree().
740*/
drhfaa57ac2004-06-09 14:01:51 +0000741#ifdef SQLITE_DEBUG
drhdaffd0e2001-04-11 14:28:42 +0000742static int sqlite_malloc_stat(
743 void *NotUsed,
744 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
745 int argc, /* Number of arguments */
746 char **argv /* Text of each argument */
747){
748 char zBuf[200];
danielk19776f8a5032004-05-10 10:34:51 +0000749 sprintf(zBuf, "%d %d %d", sqlite3_nMalloc, sqlite3_nFree, sqlite3_iMallocFail);
drhdaffd0e2001-04-11 14:28:42 +0000750 Tcl_AppendResult(interp, zBuf, 0);
751 return TCL_OK;
752}
753#endif
754
755/*
drh28b4e482002-03-11 02:06:13 +0000756** Usage: sqlite_abort
757**
758** Shutdown the process immediately. This is not a clean shutdown.
759** This command is used to test the recoverability of a database in
760** the event of a program crash.
761*/
762static int sqlite_abort(
763 void *NotUsed,
764 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
765 int argc, /* Number of arguments */
766 char **argv /* Text of each argument */
767){
768 assert( interp==0 ); /* This will always fail */
769 return TCL_OK;
770}
771
772/*
drh6cbe1f12002-07-01 00:31:36 +0000773** The following routine is a user-defined SQL function whose purpose
774** is to test the sqlite_set_result() API.
775*/
danielk19770ae8b832004-05-25 12:05:56 +0000776static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
drh6cbe1f12002-07-01 00:31:36 +0000777 while( argc>=2 ){
drh4f26d6c2004-05-26 23:25:30 +0000778 const char *zArg0 = sqlite3_value_text(argv[0]);
danielk19776d88bad2004-05-27 14:23:36 +0000779 if( zArg0 ){
780 if( 0==sqlite3StrICmp(zArg0, "int") ){
781 sqlite3_result_int(context, sqlite3_value_int(argv[1]));
782 }else if( sqlite3StrICmp(zArg0,"int64")==0 ){
783 sqlite3_result_int64(context, sqlite3_value_int64(argv[1]));
784 }else if( sqlite3StrICmp(zArg0,"string")==0 ){
danielk1977d8123362004-06-12 09:25:12 +0000785 sqlite3_result_text(context, sqlite3_value_text(argv[1]), -1,
786 SQLITE_TRANSIENT);
danielk19776d88bad2004-05-27 14:23:36 +0000787 }else if( sqlite3StrICmp(zArg0,"double")==0 ){
788 sqlite3_result_double(context, sqlite3_value_double(argv[1]));
789 }else if( sqlite3StrICmp(zArg0,"null")==0 ){
790 sqlite3_result_null(context);
791 }else if( sqlite3StrICmp(zArg0,"value")==0 ){
792 sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]);
793 }else{
794 goto error_out;
795 }
drh6cbe1f12002-07-01 00:31:36 +0000796 }else{
danielk19776d88bad2004-05-27 14:23:36 +0000797 goto error_out;
drh6cbe1f12002-07-01 00:31:36 +0000798 }
799 argc -= 2;
800 argv += 2;
801 }
danielk19776d88bad2004-05-27 14:23:36 +0000802 return;
803
804error_out:
805 sqlite3_result_error(context,"first argument should be one of: "
806 "int int64 string double null value", -1);
drh6cbe1f12002-07-01 00:31:36 +0000807}
808
809/*
810** Usage: sqlite_register_test_function DB NAME
811**
812** Register the test SQL function on the database DB under the name NAME.
813*/
drhc2eef3b2002-08-31 18:53:06 +0000814static int test_register_func(
drh6cbe1f12002-07-01 00:31:36 +0000815 void *NotUsed,
816 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
817 int argc, /* Number of arguments */
818 char **argv /* Text of each argument */
819){
drh9bb575f2004-09-06 17:24:11 +0000820 sqlite3 *db;
drh6cbe1f12002-07-01 00:31:36 +0000821 int rc;
822 if( argc!=3 ){
823 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
824 " DB FUNCTION-NAME", 0);
825 return TCL_ERROR;
826 }
drhb86ccfb2003-01-28 23:13:10 +0000827 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk1977f9d64d22004-06-19 08:18:07 +0000828 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0,
danielk1977d8123362004-06-12 09:25:12 +0000829 testFunc, 0, 0);
drh6cbe1f12002-07-01 00:31:36 +0000830 if( rc!=0 ){
danielk1977f20b21c2004-05-31 23:56:42 +0000831 Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);
drh6cbe1f12002-07-01 00:31:36 +0000832 return TCL_ERROR;
833 }
834 return TCL_OK;
835}
836
837/*
danielk1977106bb232004-05-21 10:08:53 +0000838** Usage: sqlite3_finalize STMT
drhb86ccfb2003-01-28 23:13:10 +0000839**
danielk1977106bb232004-05-21 10:08:53 +0000840** Finalize a statement handle.
drhb86ccfb2003-01-28 23:13:10 +0000841*/
842static int test_finalize(
danielk1977106bb232004-05-21 10:08:53 +0000843 void * clientData,
844 Tcl_Interp *interp,
845 int objc,
846 Tcl_Obj *CONST objv[]
drhb86ccfb2003-01-28 23:13:10 +0000847){
danielk1977106bb232004-05-21 10:08:53 +0000848 sqlite3_stmt *pStmt;
drhb86ccfb2003-01-28 23:13:10 +0000849 int rc;
danielk1977106bb232004-05-21 10:08:53 +0000850
851 if( objc!=2 ){
852 Tcl_AppendResult(interp, "wrong # args: should be \"",
853 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
drhb86ccfb2003-01-28 23:13:10 +0000854 return TCL_ERROR;
855 }
danielk1977106bb232004-05-21 10:08:53 +0000856
857 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
858
danielk1977fc57d7b2004-05-26 02:04:57 +0000859 rc = sqlite3_finalize(pStmt);
danielk1977b77f5da2004-05-26 13:27:00 +0000860 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
danielk1977106bb232004-05-21 10:08:53 +0000861 return TCL_OK;
862}
863
864/*
865** Usage: sqlite3_reset STMT
866**
867** Finalize a statement handle.
868*/
869static int test_reset(
870 void * clientData,
871 Tcl_Interp *interp,
872 int objc,
873 Tcl_Obj *CONST objv[]
874){
875 sqlite3_stmt *pStmt;
876 int rc;
877
878 if( objc!=2 ){
879 Tcl_AppendResult(interp, "wrong # args: should be \"",
880 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
881 return TCL_ERROR;
882 }
883
884 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
885
danielk1977fc57d7b2004-05-26 02:04:57 +0000886 rc = sqlite3_reset(pStmt);
danielk1977106bb232004-05-21 10:08:53 +0000887 if( rc ){
drhb86ccfb2003-01-28 23:13:10 +0000888 return TCL_ERROR;
889 }
890 return TCL_OK;
891}
892
drh5a387052003-01-11 14:19:51 +0000893/*
danielk1977fbcd5852004-06-15 02:44:18 +0000894** Usage: sqlite3_changes DB
drh50457892003-09-06 01:10:47 +0000895**
danielk1977fbcd5852004-06-15 02:44:18 +0000896** Return the number of changes made to the database by the last SQL
897** execution.
drh50457892003-09-06 01:10:47 +0000898*/
danielk1977fbcd5852004-06-15 02:44:18 +0000899static int test_changes(
900 void * clientData,
901 Tcl_Interp *interp,
902 int objc,
903 Tcl_Obj *CONST objv[]
904){
905 sqlite3 *db;
906 if( objc!=2 ){
907 Tcl_AppendResult(interp, "wrong # args: should be \"",
908 Tcl_GetString(objv[0]), " DB", 0);
909 return TCL_ERROR;
910 }
911 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
912 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db)));
913 return TCL_OK;
914}
drh50457892003-09-06 01:10:47 +0000915
916/*
drh7c972de2003-09-06 22:18:07 +0000917** This is the "static_bind_value" that variables are bound to when
danielk19776f8a5032004-05-10 10:34:51 +0000918** the FLAG option of sqlite3_bind is "static"
drh50457892003-09-06 01:10:47 +0000919*/
drh7c972de2003-09-06 22:18:07 +0000920static char *sqlite_static_bind_value = 0;
921
922/*
danielk19776f8a5032004-05-10 10:34:51 +0000923** Usage: sqlite3_bind VM IDX VALUE FLAGS
drh7c972de2003-09-06 22:18:07 +0000924**
925** Sets the value of the IDX-th occurance of "?" in the original SQL
926** string. VALUE is the new value. If FLAGS=="null" then VALUE is
927** ignored and the value is set to NULL. If FLAGS=="static" then
928** the value is set to the value of a static variable named
929** "sqlite_static_bind_value". If FLAGS=="normal" then a copy
930** of the VALUE is made.
931*/
932static int test_bind(
drh50457892003-09-06 01:10:47 +0000933 void *NotUsed,
934 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
935 int argc, /* Number of arguments */
936 char **argv /* Text of each argument */
937){
danielk1977fc57d7b2004-05-26 02:04:57 +0000938 sqlite3_stmt *pStmt;
drh50457892003-09-06 01:10:47 +0000939 int rc;
drh7c972de2003-09-06 22:18:07 +0000940 int idx;
941 if( argc!=5 ){
drh50457892003-09-06 01:10:47 +0000942 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
drh7c972de2003-09-06 22:18:07 +0000943 " VM IDX VALUE (null|static|normal)\"", 0);
drh50457892003-09-06 01:10:47 +0000944 return TCL_ERROR;
945 }
danielk1977fc57d7b2004-05-26 02:04:57 +0000946 if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR;
drh7c972de2003-09-06 22:18:07 +0000947 if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR;
948 if( strcmp(argv[4],"null")==0 ){
danielk1977fc57d7b2004-05-26 02:04:57 +0000949 rc = sqlite3_bind_null(pStmt, idx);
drh7c972de2003-09-06 22:18:07 +0000950 }else if( strcmp(argv[4],"static")==0 ){
danielk1977fc57d7b2004-05-26 02:04:57 +0000951 rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0);
drh7c972de2003-09-06 22:18:07 +0000952 }else if( strcmp(argv[4],"normal")==0 ){
danielk1977d8123362004-06-12 09:25:12 +0000953 rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT);
drh7c972de2003-09-06 22:18:07 +0000954 }else{
955 Tcl_AppendResult(interp, "4th argument should be "
956 "\"null\" or \"static\" or \"normal\"", 0);
957 return TCL_ERROR;
958 }
drh50457892003-09-06 01:10:47 +0000959 if( rc ){
960 char zBuf[50];
961 sprintf(zBuf, "(%d) ", rc);
danielk1977f20b21c2004-05-31 23:56:42 +0000962 Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0);
drh50457892003-09-06 01:10:47 +0000963 return TCL_ERROR;
964 }
965 return TCL_OK;
966}
967
danielk19774e6af132004-06-10 14:01:08 +0000968
969/*
970** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be>
971**
972** This function is used to test that SQLite selects the correct collation
973** sequence callback when multiple versions (for different text encodings)
974** are available.
975**
976** Calling this routine registers the collation sequence "test_collate"
977** with database handle <db>. The second argument must be a list of three
978** boolean values. If the first is true, then a version of test_collate is
979** registered for UTF-8, if the second is true, a version is registered for
980** UTF-16le, if the third is true, a UTF-16be version is available.
981** Previous versions of test_collate are deleted.
982**
983** The collation sequence test_collate is implemented by calling the
984** following TCL script:
985**
986** "test_collate <enc> <lhs> <rhs>"
987**
988** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8.
989** The <enc> parameter is the encoding of the collation function that
990** SQLite selected to call. The TCL test script implements the
991** "test_collate" proc.
992**
993** Note that this will only work with one intepreter at a time, as the
994** interp pointer to use when evaluating the TCL script is stored in
995** pTestCollateInterp.
996*/
997static Tcl_Interp* pTestCollateInterp;
998static int test_collate_func(
999 void *pCtx,
1000 int nA, const void *zA,
1001 int nB, const void *zB
1002){
1003 Tcl_Interp *i = pTestCollateInterp;
1004 int encin = (int)pCtx;
1005 int res;
1006
1007 sqlite3_value *pVal;
1008 Tcl_Obj *pX;
1009
1010 pX = Tcl_NewStringObj("test_collate", -1);
1011 Tcl_IncrRefCount(pX);
1012
1013 switch( encin ){
1014 case SQLITE_UTF8:
1015 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1));
1016 break;
1017 case SQLITE_UTF16LE:
1018 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1));
1019 break;
1020 case SQLITE_UTF16BE:
1021 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1));
1022 break;
1023 default:
1024 assert(0);
1025 }
1026
1027 pVal = sqlite3ValueNew();
danielk1977bfd6cce2004-06-18 04:24:54 +00001028 sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC);
danielk19774e6af132004-06-10 14:01:08 +00001029 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),-1));
danielk1977bfd6cce2004-06-18 04:24:54 +00001030 sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC);
danielk19774e6af132004-06-10 14:01:08 +00001031 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),-1));
1032 sqlite3ValueFree(pVal);
1033
1034 Tcl_EvalObjEx(i, pX, 0);
1035 Tcl_DecrRefCount(pX);
1036 Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res);
1037 return res;
1038}
1039static int test_collate(
1040 void * clientData,
1041 Tcl_Interp *interp,
1042 int objc,
1043 Tcl_Obj *CONST objv[]
1044){
1045 sqlite3 *db;
1046 int val;
danielk1977312d6b32004-06-29 13:18:23 +00001047 sqlite3_value *pVal;
danielk19774e6af132004-06-10 14:01:08 +00001048
1049 if( objc!=5 ) goto bad_args;
1050 pTestCollateInterp = interp;
1051 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1052
1053 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
1054 sqlite3_create_collation(db, "test_collate", SQLITE_UTF8,
1055 (void *)SQLITE_UTF8, val?test_collate_func:0);
1056 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
1057 sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE,
1058 (void *)SQLITE_UTF16LE, val?test_collate_func:0);
1059 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
danielk1977312d6b32004-06-29 13:18:23 +00001060
1061 pVal = sqlite3ValueNew();
1062 sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC);
1063 sqlite3_create_collation16(db, sqlite3ValueText(pVal, SQLITE_UTF16NATIVE),
1064 SQLITE_UTF16BE, (void *)SQLITE_UTF16BE, val?test_collate_func:0);
1065 sqlite3ValueFree(pVal);
danielk19774e6af132004-06-10 14:01:08 +00001066
1067 return TCL_OK;
1068
1069bad_args:
1070 Tcl_AppendResult(interp, "wrong # args: should be \"",
1071 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
1072 return TCL_ERROR;
1073}
1074
danielk1977312d6b32004-06-29 13:18:23 +00001075static void test_collate_needed_cb(
1076 void *pCtx,
1077 sqlite3 *db,
1078 int eTextRep,
1079 const void *notUsed
1080){
1081 int enc = db->enc;
1082 sqlite3_create_collation(
1083 db, "test_collate", db->enc, (void *)enc, test_collate_func);
1084}
1085
1086/*
1087** Usage: add_test_collate_needed DB
1088*/
1089static int test_collate_needed(
1090 void * clientData,
1091 Tcl_Interp *interp,
1092 int objc,
1093 Tcl_Obj *CONST objv[]
1094){
1095 sqlite3 *db;
1096
1097 if( objc!=2 ) goto bad_args;
1098 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1099 sqlite3_collation_needed16(db, 0, test_collate_needed_cb);
1100 return TCL_OK;
1101
1102bad_args:
1103 Tcl_WrongNumArgs(interp, 1, objv, "DB");
1104 return TCL_ERROR;
1105}
1106
danielk1977c8e9a2d2004-06-25 12:08:46 +00001107/*
1108** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
1109**
1110** This function is used to test that SQLite selects the correct user
1111** function callback when multiple versions (for different text encodings)
1112** are available.
1113**
1114** Calling this routine registers up to three versions of the user function
1115** "test_function" with database handle <db>. If the second argument is
1116** true, then a version of test_function is registered for UTF-8, if the
1117** third is true, a version is registered for UTF-16le, if the fourth is
1118** true, a UTF-16be version is available. Previous versions of
1119** test_function are deleted.
1120**
1121** The user function is implemented by calling the following TCL script:
1122**
1123** "test_function <enc> <arg>"
1124**
1125** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the
1126** single argument passed to the SQL function. The value returned by
1127** the TCL script is used as the return value of the SQL function. It
1128** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8
1129** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
1130** prefers UTF-16BE.
1131*/
1132static void test_function_utf8(
1133 sqlite3_context *pCtx,
1134 int nArg,
1135 sqlite3_value **argv
1136){
1137 Tcl_Interp *interp;
1138 Tcl_Obj *pX;
1139 sqlite3_value *pVal;
1140 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1141 pX = Tcl_NewStringObj("test_function", -1);
1142 Tcl_IncrRefCount(pX);
1143 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1));
1144 Tcl_ListObjAppendElement(interp, pX,
1145 Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1));
1146 Tcl_EvalObjEx(interp, pX, 0);
1147 Tcl_DecrRefCount(pX);
1148 sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT);
1149 pVal = sqlite3ValueNew();
1150 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1151 SQLITE_UTF8, SQLITE_STATIC);
1152 sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal),
1153 -1, SQLITE_TRANSIENT);
1154 sqlite3ValueFree(pVal);
1155}
1156static void test_function_utf16le(
1157 sqlite3_context *pCtx,
1158 int nArg,
1159 sqlite3_value **argv
1160){
1161 Tcl_Interp *interp;
1162 Tcl_Obj *pX;
1163 sqlite3_value *pVal;
1164 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1165 pX = Tcl_NewStringObj("test_function", -1);
1166 Tcl_IncrRefCount(pX);
1167 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1));
1168 Tcl_ListObjAppendElement(interp, pX,
1169 Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1));
1170 Tcl_EvalObjEx(interp, pX, 0);
1171 Tcl_DecrRefCount(pX);
1172 pVal = sqlite3ValueNew();
1173 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1174 SQLITE_UTF8, SQLITE_STATIC);
1175 sqlite3_result_text(pCtx,sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT);
1176 sqlite3ValueFree(pVal);
1177}
1178static void test_function_utf16be(
1179 sqlite3_context *pCtx,
1180 int nArg,
1181 sqlite3_value **argv
1182){
1183 Tcl_Interp *interp;
1184 Tcl_Obj *pX;
1185 sqlite3_value *pVal;
1186 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1187 pX = Tcl_NewStringObj("test_function", -1);
1188 Tcl_IncrRefCount(pX);
1189 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1));
1190 Tcl_ListObjAppendElement(interp, pX,
1191 Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1));
1192 Tcl_EvalObjEx(interp, pX, 0);
1193 Tcl_DecrRefCount(pX);
1194 pVal = sqlite3ValueNew();
1195 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1196 SQLITE_UTF8, SQLITE_STATIC);
1197 sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal),
1198 -1, SQLITE_TRANSIENT);
1199 sqlite3ValueFree(pVal);
1200}
1201static int test_function(
1202 void * clientData,
1203 Tcl_Interp *interp,
1204 int objc,
1205 Tcl_Obj *CONST objv[]
1206){
1207 sqlite3 *db;
1208 int val;
1209
1210 if( objc!=5 ) goto bad_args;
1211 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1212
1213 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
1214 if( val ){
1215 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8,
1216 interp, test_function_utf8, 0, 0);
1217 }
1218 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
1219 if( val ){
1220 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE,
1221 interp, test_function_utf16le, 0, 0);
1222 }
1223 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
1224 if( val ){
1225 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE,
1226 interp, test_function_utf16be, 0, 0);
1227 }
1228
1229 return TCL_OK;
1230bad_args:
1231 Tcl_AppendResult(interp, "wrong # args: should be \"",
1232 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
1233 return TCL_ERROR;
1234}
1235
danielk1977312d6b32004-06-29 13:18:23 +00001236/*
1237** Usage: test_errstr <err code>
1238**
1239** Test that the english language string equivalents for sqlite error codes
1240** are sane. The parameter is an integer representing an sqlite error code.
1241** The result is a list of two elements, the string representation of the
1242** error code and the english language explanation.
1243*/
1244static int test_errstr(
1245 void * clientData,
1246 Tcl_Interp *interp,
1247 int objc,
1248 Tcl_Obj *CONST objv[]
1249){
1250 char *zCode;
1251 int i;
1252 if( objc!=1 ){
1253 Tcl_WrongNumArgs(interp, 1, objv, "<error code>");
1254 }
1255
1256 zCode = Tcl_GetString(objv[1]);
1257 for(i=0; i<200; i++){
1258 if( 0==strcmp(errorName(i), zCode) ) break;
1259 }
1260 Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0);
1261 return TCL_OK;
1262}
1263
danielk1977c8e9a2d2004-06-25 12:08:46 +00001264static int sqlite3_crashparams(
danielk19778a6c5502004-06-22 12:18:32 +00001265 void * clientData,
1266 Tcl_Interp *interp,
1267 int objc,
1268 Tcl_Obj *CONST objv[]
1269){
1270#ifdef OS_TEST
danielk1977c8e9a2d2004-06-25 12:08:46 +00001271 int delay;
1272 if( objc!=3 ) goto bad_args;
1273 if( Tcl_GetIntFromObj(interp, objv[1], &delay) ) return TCL_ERROR;
1274 sqlite3SetCrashParams(delay, Tcl_GetString(objv[2]));
danielk19778a6c5502004-06-22 12:18:32 +00001275#endif
1276 return TCL_OK;
1277
drh241db312004-06-22 12:46:53 +00001278#ifdef OS_TEST
danielk19778a6c5502004-06-22 12:18:32 +00001279bad_args:
1280 Tcl_AppendResult(interp, "wrong # args: should be \"",
danielk1977c8e9a2d2004-06-25 12:08:46 +00001281 Tcl_GetStringFromObj(objv[0], 0), "<delay> <filename>", 0);
danielk19778a6c5502004-06-22 12:18:32 +00001282 return TCL_ERROR;
drh241db312004-06-22 12:46:53 +00001283#endif
danielk19778a6c5502004-06-22 12:18:32 +00001284}
1285
1286
drh50457892003-09-06 01:10:47 +00001287/*
drh99ee3602003-02-16 19:13:36 +00001288** Usage: breakpoint
1289**
1290** This routine exists for one purpose - to provide a place to put a
1291** breakpoint with GDB that can be triggered using TCL code. The use
1292** for this is when a particular test fails on (say) the 1485th iteration.
1293** In the TCL test script, we can add code like this:
1294**
1295** if {$i==1485} breakpoint
1296**
1297** Then run testfixture in the debugger and wait for the breakpoint to
1298** fire. Then additional breakpoints can be set to trace down the bug.
1299*/
1300static int test_breakpoint(
1301 void *NotUsed,
1302 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1303 int argc, /* Number of arguments */
1304 char **argv /* Text of each argument */
1305){
1306 return TCL_OK; /* Do nothing */
1307}
1308
drh241db312004-06-22 12:46:53 +00001309/*
1310** Usage: sqlite3_bind_int STMT N VALUE
1311**
1312** Test the sqlite3_bind_int interface. STMT is a prepared statement.
1313** N is the index of a wildcard in the prepared statement. This command
1314** binds a 32-bit integer VALUE to that wildcard.
1315*/
1316static int test_bind_int(
danielk197751e3d8e2004-05-20 01:12:34 +00001317 void * clientData,
1318 Tcl_Interp *interp,
1319 int objc,
1320 Tcl_Obj *CONST objv[]
1321){
1322 sqlite3_stmt *pStmt;
1323 int idx;
1324 int value;
1325 int rc;
1326
1327 if( objc!=4 ){
1328 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001329 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001330 return TCL_ERROR;
1331 }
1332
1333 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1334 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1335 if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
1336
danielk1977c572ef72004-05-27 09:28:41 +00001337 rc = sqlite3_bind_int(pStmt, idx, value);
danielk197751e3d8e2004-05-20 01:12:34 +00001338 if( rc!=SQLITE_OK ){
1339 return TCL_ERROR;
1340 }
1341
1342 return TCL_OK;
1343}
1344
drh241db312004-06-22 12:46:53 +00001345
1346/*
1347** Usage: sqlite3_bind_int64 STMT N VALUE
1348**
1349** Test the sqlite3_bind_int64 interface. STMT is a prepared statement.
1350** N is the index of a wildcard in the prepared statement. This command
1351** binds a 64-bit integer VALUE to that wildcard.
1352*/
danielk197751e3d8e2004-05-20 01:12:34 +00001353static int test_bind_int64(
1354 void * clientData,
1355 Tcl_Interp *interp,
1356 int objc,
1357 Tcl_Obj *CONST objv[]
1358){
1359 sqlite3_stmt *pStmt;
1360 int idx;
1361 i64 value;
1362 int rc;
1363
1364 if( objc!=4 ){
1365 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001366 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001367 return TCL_ERROR;
1368 }
1369
1370 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1371 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1372 if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
1373
1374 rc = sqlite3_bind_int64(pStmt, idx, value);
1375 if( rc!=SQLITE_OK ){
1376 return TCL_ERROR;
1377 }
1378
1379 return TCL_OK;
1380}
1381
drh241db312004-06-22 12:46:53 +00001382
1383/*
1384** Usage: sqlite3_bind_double STMT N VALUE
1385**
1386** Test the sqlite3_bind_double interface. STMT is a prepared statement.
1387** N is the index of a wildcard in the prepared statement. This command
1388** binds a 64-bit integer VALUE to that wildcard.
1389*/
danielk197751e3d8e2004-05-20 01:12:34 +00001390static int test_bind_double(
1391 void * clientData,
1392 Tcl_Interp *interp,
1393 int objc,
1394 Tcl_Obj *CONST objv[]
1395){
1396 sqlite3_stmt *pStmt;
1397 int idx;
1398 double value;
1399 int rc;
1400
1401 if( objc!=4 ){
1402 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001403 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001404 return TCL_ERROR;
1405 }
1406
1407 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1408 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1409 if( Tcl_GetDoubleFromObj(interp, objv[3], &value) ) return TCL_ERROR;
1410
1411 rc = sqlite3_bind_double(pStmt, idx, value);
1412 if( rc!=SQLITE_OK ){
1413 return TCL_ERROR;
1414 }
1415
1416 return TCL_OK;
1417}
1418
drh241db312004-06-22 12:46:53 +00001419/*
1420** Usage: sqlite3_bind_null STMT N
1421**
1422** Test the sqlite3_bind_null interface. STMT is a prepared statement.
1423** N is the index of a wildcard in the prepared statement. This command
1424** binds a NULL to the wildcard.
1425*/
danielk197751e3d8e2004-05-20 01:12:34 +00001426static int test_bind_null(
1427 void * clientData,
1428 Tcl_Interp *interp,
1429 int objc,
1430 Tcl_Obj *CONST objv[]
1431){
1432 sqlite3_stmt *pStmt;
1433 int idx;
1434 int rc;
1435
1436 if( objc!=3 ){
1437 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001438 Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001439 return TCL_ERROR;
1440 }
1441
1442 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1443 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1444
1445 rc = sqlite3_bind_null(pStmt, idx);
1446 if( rc!=SQLITE_OK ){
1447 return TCL_ERROR;
1448 }
1449
1450 return TCL_OK;
1451}
1452
drh241db312004-06-22 12:46:53 +00001453/*
1454** Usage: sqlite3_bind_text STMT N STRING BYTES
1455**
1456** Test the sqlite3_bind_text interface. STMT is a prepared statement.
1457** N is the index of a wildcard in the prepared statement. This command
1458** binds a UTF-8 string STRING to the wildcard. The string is BYTES bytes
1459** long.
1460*/
danielk197751e3d8e2004-05-20 01:12:34 +00001461static int test_bind_text(
1462 void * clientData,
1463 Tcl_Interp *interp,
1464 int objc,
1465 Tcl_Obj *CONST objv[]
1466){
1467 sqlite3_stmt *pStmt;
1468 int idx;
1469 int bytes;
1470 char *value;
1471 int rc;
1472
1473 if( objc!=5 ){
1474 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001475 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001476 return TCL_ERROR;
1477 }
1478
1479 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1480 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1481 value = Tcl_GetString(objv[3]);
1482 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
1483
danielk1977d8123362004-06-12 09:25:12 +00001484 rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
danielk197751e3d8e2004-05-20 01:12:34 +00001485 if( rc!=SQLITE_OK ){
1486 return TCL_ERROR;
1487 }
1488
1489 return TCL_OK;
1490}
1491
drh241db312004-06-22 12:46:53 +00001492/*
1493** Usage: sqlite3_bind_text16 STMT N STRING BYTES
1494**
1495** Test the sqlite3_bind_text16 interface. STMT is a prepared statement.
1496** N is the index of a wildcard in the prepared statement. This command
1497** binds a UTF-16 string STRING to the wildcard. The string is BYTES bytes
1498** long.
1499*/
danielk197751e3d8e2004-05-20 01:12:34 +00001500static int test_bind_text16(
1501 void * clientData,
1502 Tcl_Interp *interp,
1503 int objc,
1504 Tcl_Obj *CONST objv[]
1505){
1506 sqlite3_stmt *pStmt;
1507 int idx;
1508 int bytes;
1509 char *value;
1510 int rc;
1511
1512 if( objc!=5 ){
1513 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001514 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001515 return TCL_ERROR;
1516 }
1517
1518 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1519 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1520 value = Tcl_GetByteArrayFromObj(objv[3], 0);
1521 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
1522
danielk1977d8123362004-06-12 09:25:12 +00001523 rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, SQLITE_TRANSIENT);
danielk197751e3d8e2004-05-20 01:12:34 +00001524 if( rc!=SQLITE_OK ){
1525 return TCL_ERROR;
1526 }
1527
1528 return TCL_OK;
1529}
1530
drh241db312004-06-22 12:46:53 +00001531/*
1532** Usage: sqlite3_bind_blob STMT N DATA BYTES
1533**
1534** Test the sqlite3_bind_blob interface. STMT is a prepared statement.
1535** N is the index of a wildcard in the prepared statement. This command
1536** binds a BLOB to the wildcard. The BLOB is BYTES bytes in size.
1537*/
danielk197751e3d8e2004-05-20 01:12:34 +00001538static int test_bind_blob(
1539 void * clientData,
1540 Tcl_Interp *interp,
1541 int objc,
1542 Tcl_Obj *CONST objv[]
1543){
1544 sqlite3_stmt *pStmt;
1545 int idx;
1546 int bytes;
1547 char *value;
1548 int rc;
1549
1550 if( objc!=5 ){
1551 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001552 Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001553 return TCL_ERROR;
1554 }
1555
1556 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1557 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1558 value = Tcl_GetString(objv[3]);
danielk197749e46432004-05-27 13:55:27 +00001559 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001560
danielk1977d8123362004-06-12 09:25:12 +00001561 rc = sqlite3_bind_blob(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
danielk197751e3d8e2004-05-20 01:12:34 +00001562 if( rc!=SQLITE_OK ){
1563 return TCL_ERROR;
1564 }
1565
1566 return TCL_OK;
1567}
1568
drh99ee3602003-02-16 19:13:36 +00001569/*
drh75f6a032004-07-15 14:15:00 +00001570** Usage: sqlite3_bind_parameter_count STMT
1571**
1572** Return the number of wildcards in the given statement.
1573*/
1574static int test_bind_parameter_count(
1575 void * clientData,
1576 Tcl_Interp *interp,
1577 int objc,
1578 Tcl_Obj *CONST objv[]
1579){
1580 sqlite3_stmt *pStmt;
1581
1582 if( objc!=2 ){
1583 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
1584 return TCL_ERROR;
1585 }
1586 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1587 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt)));
1588 return TCL_OK;
1589}
1590
1591/*
drh895d7472004-08-20 16:02:39 +00001592** Usage: sqlite3_bind_parameter_name STMT N
1593**
1594** Return the name of the Nth wildcard. The first wildcard is 1.
1595** An empty string is returned if N is out of range or if the wildcard
1596** is nameless.
1597*/
1598static int test_bind_parameter_name(
1599 void * clientData,
1600 Tcl_Interp *interp,
1601 int objc,
1602 Tcl_Obj *CONST objv[]
1603){
1604 sqlite3_stmt *pStmt;
1605 int i;
1606
1607 if( objc!=3 ){
1608 Tcl_WrongNumArgs(interp, 1, objv, "STMT N");
1609 return TCL_ERROR;
1610 }
1611 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1612 if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR;
1613 Tcl_SetObjResult(interp,
1614 Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1)
1615 );
1616 return TCL_OK;
1617}
1618
1619/*
drhfa6bc002004-09-07 16:19:52 +00001620** Usage: sqlite3_bind_parameter_index STMT NAME
1621**
1622** Return the index of the wildcard called NAME. Return 0 if there is
1623** no such wildcard.
1624*/
1625static int test_bind_parameter_index(
1626 void * clientData,
1627 Tcl_Interp *interp,
1628 int objc,
1629 Tcl_Obj *CONST objv[]
1630){
1631 sqlite3_stmt *pStmt;
1632
1633 if( objc!=3 ){
1634 Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME");
1635 return TCL_ERROR;
1636 }
1637 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1638 Tcl_SetObjResult(interp,
1639 Tcl_NewIntObj(
1640 sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2]))
1641 )
1642 );
1643 return TCL_OK;
1644}
1645
1646/*
danielk19776622cce2004-05-20 11:00:52 +00001647** Usage: sqlite3_errcode DB
1648**
1649** Return the string representation of the most recent sqlite3_* API
1650** error code. e.g. "SQLITE_ERROR".
1651*/
1652static int test_errcode(
1653 void * clientData,
1654 Tcl_Interp *interp,
1655 int objc,
1656 Tcl_Obj *CONST objv[]
1657){
1658 sqlite3 *db;
1659
1660 if( objc!=2 ){
1661 Tcl_AppendResult(interp, "wrong # args: should be \"",
1662 Tcl_GetString(objv[0]), " DB", 0);
1663 return TCL_ERROR;
1664 }
1665 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1666 Tcl_SetResult(interp, (char *)errorName(sqlite3_errcode(db)), 0);
1667 return TCL_OK;
1668}
1669
1670/*
1671** Usage: test_errmsg DB
1672**
1673** Returns the UTF-8 representation of the error message string for the
1674** most recent sqlite3_* API call.
1675*/
1676static int test_errmsg(
1677 void * clientData,
1678 Tcl_Interp *interp,
1679 int objc,
1680 Tcl_Obj *CONST objv[]
1681){
drh9bb575f2004-09-06 17:24:11 +00001682 sqlite3 *db;
danielk19776622cce2004-05-20 11:00:52 +00001683 const char *zErr;
1684
1685 if( objc!=2 ){
1686 Tcl_AppendResult(interp, "wrong # args: should be \"",
1687 Tcl_GetString(objv[0]), " DB", 0);
1688 return TCL_ERROR;
1689 }
1690 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1691
1692 zErr = sqlite3_errmsg(db);
1693 Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
1694 return TCL_OK;
1695}
1696
1697/*
1698** Usage: test_errmsg16 DB
1699**
1700** Returns the UTF-16 representation of the error message string for the
1701** most recent sqlite3_* API call. This is a byte array object at the TCL
1702** level, and it includes the 0x00 0x00 terminator bytes at the end of the
1703** UTF-16 string.
1704*/
1705static int test_errmsg16(
1706 void * clientData,
1707 Tcl_Interp *interp,
1708 int objc,
1709 Tcl_Obj *CONST objv[]
1710){
drh9bb575f2004-09-06 17:24:11 +00001711 sqlite3 *db;
danielk19776622cce2004-05-20 11:00:52 +00001712 const void *zErr;
1713 int bytes;
1714
1715 if( objc!=2 ){
1716 Tcl_AppendResult(interp, "wrong # args: should be \"",
1717 Tcl_GetString(objv[0]), " DB", 0);
1718 return TCL_ERROR;
1719 }
1720 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1721
1722 zErr = sqlite3_errmsg16(db);
1723 bytes = sqlite3utf16ByteLen(zErr, -1);
1724 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes));
1725 return TCL_OK;
1726}
1727
1728/*
1729** Usage: sqlite3_prepare DB sql bytes tailvar
1730**
1731** Compile up to <bytes> bytes of the supplied SQL string <sql> using
1732** database handle <DB>. The parameter <tailval> is the name of a global
1733** variable that is set to the unused portion of <sql> (if any). A
1734** STMT handle is returned.
1735*/
1736static int test_prepare(
1737 void * clientData,
1738 Tcl_Interp *interp,
1739 int objc,
1740 Tcl_Obj *CONST objv[]
1741){
1742 sqlite3 *db;
1743 const char *zSql;
1744 int bytes;
1745 const char *zTail = 0;
1746 sqlite3_stmt *pStmt = 0;
1747 char zBuf[50];
danielk19774ad17132004-05-21 01:47:26 +00001748 int rc;
danielk19776622cce2004-05-20 11:00:52 +00001749
1750 if( objc!=5 ){
1751 Tcl_AppendResult(interp, "wrong # args: should be \"",
1752 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
1753 return TCL_ERROR;
1754 }
1755 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1756 zSql = Tcl_GetString(objv[2]);
1757 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
1758
danielk19774ad17132004-05-21 01:47:26 +00001759 rc = sqlite3_prepare(db, zSql, bytes, &pStmt, &zTail);
danielk19776622cce2004-05-20 11:00:52 +00001760 if( zTail ){
1761 if( bytes>=0 ){
1762 bytes = bytes - (zTail-zSql);
1763 }
1764 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
1765 }
danielk19774ad17132004-05-21 01:47:26 +00001766 if( rc!=SQLITE_OK ){
1767 assert( pStmt==0 );
1768 sprintf(zBuf, "(%d) ", rc);
1769 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
1770 return TCL_ERROR;
1771 }
danielk19776622cce2004-05-20 11:00:52 +00001772
danielk19774ad17132004-05-21 01:47:26 +00001773 if( pStmt ){
1774 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
1775 Tcl_AppendResult(interp, zBuf, 0);
1776 }
danielk19776622cce2004-05-20 11:00:52 +00001777 return TCL_OK;
1778}
1779
1780/*
1781** Usage: sqlite3_prepare DB sql bytes tailvar
1782**
1783** Compile up to <bytes> bytes of the supplied SQL string <sql> using
1784** database handle <DB>. The parameter <tailval> is the name of a global
1785** variable that is set to the unused portion of <sql> (if any). A
1786** STMT handle is returned.
1787*/
1788static int test_prepare16(
1789 void * clientData,
1790 Tcl_Interp *interp,
1791 int objc,
1792 Tcl_Obj *CONST objv[]
1793){
1794 sqlite3 *db;
1795 const void *zSql;
1796 const void *zTail = 0;
1797 Tcl_Obj *pTail = 0;
1798 sqlite3_stmt *pStmt = 0;
1799 char zBuf[50];
1800 int bytes; /* The integer specified as arg 3 */
1801 int objlen; /* The byte-array length of arg 2 */
1802
1803 if( objc!=5 ){
1804 Tcl_AppendResult(interp, "wrong # args: should be \"",
1805 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
1806 return TCL_ERROR;
1807 }
1808 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1809 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
1810 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
1811
1812 if( SQLITE_OK!=sqlite3_prepare16(db, zSql, bytes, &pStmt, &zTail) ){
1813 return TCL_ERROR;
1814 }
1815
1816 if( zTail ){
1817 objlen = objlen - ((u8 *)zTail-(u8 *)zSql);
1818 }else{
1819 objlen = 0;
1820 }
1821 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
1822 Tcl_IncrRefCount(pTail);
1823 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
danielk19774ad17132004-05-21 01:47:26 +00001824 Tcl_DecrRefCount(pTail);
danielk19776622cce2004-05-20 11:00:52 +00001825
danielk19774ad17132004-05-21 01:47:26 +00001826 if( pStmt ){
1827 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
1828 }
danielk19776622cce2004-05-20 11:00:52 +00001829 Tcl_AppendResult(interp, zBuf, 0);
1830 return TCL_OK;
1831}
1832
danielk19774ad17132004-05-21 01:47:26 +00001833/*
1834** Usage: sqlite3_open filename ?options-list?
1835*/
1836static int test_open(
1837 void * clientData,
1838 Tcl_Interp *interp,
1839 int objc,
1840 Tcl_Obj *CONST objv[]
1841){
1842 const char *zFilename;
1843 sqlite3 *db;
1844 int rc;
1845 char zBuf[100];
1846
1847 if( objc!=3 && objc!=2 ){
1848 Tcl_AppendResult(interp, "wrong # args: should be \"",
1849 Tcl_GetString(objv[0]), " filename options-list", 0);
1850 return TCL_ERROR;
1851 }
1852
1853 zFilename = Tcl_GetString(objv[1]);
danielk19774f057f92004-06-08 00:02:33 +00001854 rc = sqlite3_open(zFilename, &db);
danielk19774ad17132004-05-21 01:47:26 +00001855
1856 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR;
1857 Tcl_AppendResult(interp, zBuf, 0);
1858 return TCL_OK;
1859}
1860
1861/*
1862** Usage: sqlite3_open16 filename options
1863*/
1864static int test_open16(
1865 void * clientData,
1866 Tcl_Interp *interp,
1867 int objc,
1868 Tcl_Obj *CONST objv[]
1869){
1870 const void *zFilename;
1871 sqlite3 *db;
1872 int rc;
1873 char zBuf[100];
1874
1875 if( objc!=3 ){
1876 Tcl_AppendResult(interp, "wrong # args: should be \"",
1877 Tcl_GetString(objv[0]), " filename options-list", 0);
1878 return TCL_ERROR;
1879 }
1880
1881 zFilename = Tcl_GetByteArrayFromObj(objv[1], 0);
danielk19774f057f92004-06-08 00:02:33 +00001882 rc = sqlite3_open16(zFilename, &db);
danielk19774ad17132004-05-21 01:47:26 +00001883
1884 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR;
1885 Tcl_AppendResult(interp, zBuf, 0);
1886 return TCL_OK;
1887}
drhd3d39e92004-05-20 22:16:29 +00001888
1889/*
danielk1977bc6ada42004-06-30 08:20:16 +00001890** Usage: sqlite3_complete16 <UTF-16 string>
1891**
1892** Return 1 if the supplied argument is a complete SQL statement, or zero
1893** otherwise.
1894*/
1895static int test_complete16(
1896 void * clientData,
1897 Tcl_Interp *interp,
1898 int objc,
1899 Tcl_Obj *CONST objv[]
1900){
1901 char *zBuf;
1902
1903 if( objc!=2 ){
1904 Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>");
1905 return TCL_ERROR;
1906 }
1907
1908 zBuf = Tcl_GetByteArrayFromObj(objv[1], 0);
1909 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf)));
1910 return TCL_OK;
1911}
1912
1913/*
danielk1977106bb232004-05-21 10:08:53 +00001914** Usage: sqlite3_step STMT
1915**
1916** Advance the statement to the next row.
1917*/
danielk197717240fd2004-05-26 00:07:25 +00001918static int test_step(
danielk1977106bb232004-05-21 10:08:53 +00001919 void * clientData,
1920 Tcl_Interp *interp,
1921 int objc,
1922 Tcl_Obj *CONST objv[]
1923){
1924 sqlite3_stmt *pStmt;
1925 int rc;
1926
danielk1977e1cd9872004-05-22 10:33:04 +00001927 if( objc!=2 ){
danielk1977106bb232004-05-21 10:08:53 +00001928 Tcl_AppendResult(interp, "wrong # args: should be \"",
1929 Tcl_GetString(objv[0]), " STMT", 0);
1930 return TCL_ERROR;
1931 }
1932
1933 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
danielk197717240fd2004-05-26 00:07:25 +00001934 rc = sqlite3_step(pStmt);
danielk1977106bb232004-05-21 10:08:53 +00001935
danielk1977fbcd5852004-06-15 02:44:18 +00001936 /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */
danielk197765904932004-05-26 06:18:37 +00001937 Tcl_SetResult(interp, (char *)errorName(rc), 0);
danielk1977e1cd9872004-05-22 10:33:04 +00001938 return TCL_OK;
1939}
1940
1941/*
danielk197717240fd2004-05-26 00:07:25 +00001942** Usage: sqlite3_column_count STMT
1943**
1944** Return the number of columns returned by the sql statement STMT.
1945*/
1946static int test_column_count(
1947 void * clientData,
1948 Tcl_Interp *interp,
1949 int objc,
1950 Tcl_Obj *CONST objv[]
1951){
1952 sqlite3_stmt *pStmt;
1953
1954 if( objc!=2 ){
1955 Tcl_AppendResult(interp, "wrong # args: should be \"",
1956 Tcl_GetString(objv[0]), " STMT column", 0);
1957 return TCL_ERROR;
1958 }
1959
1960 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1961
1962 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt)));
1963 return TCL_OK;
1964}
1965
1966/*
danielk19773cf86062004-05-26 10:11:05 +00001967** Usage: sqlite3_column_type STMT column
1968**
1969** Return the type of the data in column 'column' of the current row.
1970*/
1971static int test_column_type(
1972 void * clientData,
1973 Tcl_Interp *interp,
1974 int objc,
1975 Tcl_Obj *CONST objv[]
1976){
1977 sqlite3_stmt *pStmt;
1978 int col;
1979 int tp;
1980
1981 if( objc!=3 ){
1982 Tcl_AppendResult(interp, "wrong # args: should be \"",
1983 Tcl_GetString(objv[0]), " STMT column", 0);
1984 return TCL_ERROR;
1985 }
1986
1987 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1988 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
1989
1990 tp = sqlite3_column_type(pStmt, col);
1991 switch( tp ){
drh9c054832004-05-31 18:51:57 +00001992 case SQLITE_INTEGER:
danielk19773cf86062004-05-26 10:11:05 +00001993 Tcl_SetResult(interp, "INTEGER", TCL_STATIC);
1994 break;
drh9c054832004-05-31 18:51:57 +00001995 case SQLITE_NULL:
danielk19773cf86062004-05-26 10:11:05 +00001996 Tcl_SetResult(interp, "NULL", TCL_STATIC);
1997 break;
drh9c054832004-05-31 18:51:57 +00001998 case SQLITE_FLOAT:
danielk19773cf86062004-05-26 10:11:05 +00001999 Tcl_SetResult(interp, "FLOAT", TCL_STATIC);
2000 break;
drh9c054832004-05-31 18:51:57 +00002001 case SQLITE_TEXT:
danielk19773cf86062004-05-26 10:11:05 +00002002 Tcl_SetResult(interp, "TEXT", TCL_STATIC);
2003 break;
drh9c054832004-05-31 18:51:57 +00002004 case SQLITE_BLOB:
danielk19773cf86062004-05-26 10:11:05 +00002005 Tcl_SetResult(interp, "BLOB", TCL_STATIC);
2006 break;
2007 default:
2008 assert(0);
2009 }
2010
2011 return TCL_OK;
2012}
2013
2014/*
danielk197704f2e682004-05-27 01:04:07 +00002015** Usage: sqlite3_column_int64 STMT column
danielk19773cf86062004-05-26 10:11:05 +00002016**
2017** Return the data in column 'column' of the current row cast as an
danielk197704f2e682004-05-27 01:04:07 +00002018** wide (64-bit) integer.
danielk19773cf86062004-05-26 10:11:05 +00002019*/
danielk197704f2e682004-05-27 01:04:07 +00002020static int test_column_int64(
danielk19773cf86062004-05-26 10:11:05 +00002021 void * clientData,
2022 Tcl_Interp *interp,
2023 int objc,
2024 Tcl_Obj *CONST objv[]
2025){
2026 sqlite3_stmt *pStmt;
2027 int col;
danielk197704f2e682004-05-27 01:04:07 +00002028 i64 iVal;
danielk19773cf86062004-05-26 10:11:05 +00002029
2030 if( objc!=3 ){
2031 Tcl_AppendResult(interp, "wrong # args: should be \"",
2032 Tcl_GetString(objv[0]), " STMT column", 0);
2033 return TCL_ERROR;
2034 }
2035
2036 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2037 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2038
danielk197704f2e682004-05-27 01:04:07 +00002039 iVal = sqlite3_column_int64(pStmt, col);
2040 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal));
2041 return TCL_OK;
2042}
2043
2044/*
danielk1977ea61b2c2004-05-27 01:49:51 +00002045** Usage: sqlite3_column_blob STMT column
2046*/
2047static int test_column_blob(
2048 void * clientData,
2049 Tcl_Interp *interp,
2050 int objc,
2051 Tcl_Obj *CONST objv[]
2052){
2053 sqlite3_stmt *pStmt;
2054 int col;
2055
2056 int len;
danielk1977c572ef72004-05-27 09:28:41 +00002057 const void *pBlob;
danielk1977ea61b2c2004-05-27 01:49:51 +00002058
2059 if( objc!=3 ){
2060 Tcl_AppendResult(interp, "wrong # args: should be \"",
2061 Tcl_GetString(objv[0]), " STMT column", 0);
2062 return TCL_ERROR;
2063 }
2064
2065 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2066 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2067
2068 pBlob = sqlite3_column_blob(pStmt, col);
2069 len = sqlite3_column_bytes(pStmt, col);
2070 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len));
2071 return TCL_OK;
2072}
2073
2074/*
danielk197704f2e682004-05-27 01:04:07 +00002075** Usage: sqlite3_column_double STMT column
2076**
2077** Return the data in column 'column' of the current row cast as a double.
2078*/
2079static int test_column_double(
2080 void * clientData,
2081 Tcl_Interp *interp,
2082 int objc,
2083 Tcl_Obj *CONST objv[]
2084){
2085 sqlite3_stmt *pStmt;
2086 int col;
2087 double rVal;
2088
2089 if( objc!=3 ){
2090 Tcl_AppendResult(interp, "wrong # args: should be \"",
2091 Tcl_GetString(objv[0]), " STMT column", 0);
2092 return TCL_ERROR;
2093 }
2094
2095 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2096 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2097
2098 rVal = sqlite3_column_double(pStmt, col);
danielk1977c572ef72004-05-27 09:28:41 +00002099 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal));
danielk19773cf86062004-05-26 10:11:05 +00002100 return TCL_OK;
2101}
2102
2103/*
danielk197717240fd2004-05-26 00:07:25 +00002104** Usage: sqlite3_data_count STMT
2105**
2106** Return the number of columns returned by the sql statement STMT.
2107*/
2108static int test_data_count(
2109 void * clientData,
2110 Tcl_Interp *interp,
2111 int objc,
2112 Tcl_Obj *CONST objv[]
2113){
2114 sqlite3_stmt *pStmt;
2115
2116 if( objc!=2 ){
2117 Tcl_AppendResult(interp, "wrong # args: should be \"",
2118 Tcl_GetString(objv[0]), " STMT column", 0);
2119 return TCL_ERROR;
2120 }
2121
2122 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2123
2124 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt)));
2125 return TCL_OK;
2126}
2127
2128/*
danielk197704f2e682004-05-27 01:04:07 +00002129** Usage: sqlite3_column_text STMT column
2130**
2131** Usage: sqlite3_column_decltype STMT column
2132**
2133** Usage: sqlite3_column_name STMT column
2134*/
2135static int test_stmt_utf8(
drh241db312004-06-22 12:46:53 +00002136 void * clientData, /* Pointer to SQLite API function to be invoke */
danielk197704f2e682004-05-27 01:04:07 +00002137 Tcl_Interp *interp,
2138 int objc,
2139 Tcl_Obj *CONST objv[]
2140){
2141 sqlite3_stmt *pStmt;
2142 int col;
danielk1977c572ef72004-05-27 09:28:41 +00002143 const char *(*xFunc)(sqlite3_stmt*, int) = clientData;
danielk1977f93bbbe2004-05-27 10:30:52 +00002144 const char *zRet;
danielk197704f2e682004-05-27 01:04:07 +00002145
2146 if( objc!=3 ){
2147 Tcl_AppendResult(interp, "wrong # args: should be \"",
2148 Tcl_GetString(objv[0]), " STMT column", 0);
2149 return TCL_ERROR;
2150 }
2151
2152 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2153 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
danielk1977f93bbbe2004-05-27 10:30:52 +00002154 zRet = xFunc(pStmt, col);
2155 if( zRet ){
2156 Tcl_SetResult(interp, (char *)zRet, 0);
2157 }
danielk197704f2e682004-05-27 01:04:07 +00002158 return TCL_OK;
2159}
2160
2161/*
2162** Usage: sqlite3_column_text STMT column
2163**
2164** Usage: sqlite3_column_decltype STMT column
2165**
2166** Usage: sqlite3_column_name STMT column
2167*/
2168static int test_stmt_utf16(
drh241db312004-06-22 12:46:53 +00002169 void * clientData, /* Pointer to SQLite API function to be invoked */
danielk197704f2e682004-05-27 01:04:07 +00002170 Tcl_Interp *interp,
2171 int objc,
2172 Tcl_Obj *CONST objv[]
2173){
2174 sqlite3_stmt *pStmt;
2175 int col;
2176 Tcl_Obj *pRet;
2177 const void *zName16;
danielk1977c572ef72004-05-27 09:28:41 +00002178 const void *(*xFunc)(sqlite3_stmt*, int) = clientData;
danielk197704f2e682004-05-27 01:04:07 +00002179
2180 if( objc!=3 ){
2181 Tcl_AppendResult(interp, "wrong # args: should be \"",
2182 Tcl_GetString(objv[0]), " STMT column", 0);
2183 return TCL_ERROR;
2184 }
2185
2186 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2187 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2188
2189 zName16 = xFunc(pStmt, col);
danielk1977f93bbbe2004-05-27 10:30:52 +00002190 if( zName16 ){
2191 pRet = Tcl_NewByteArrayObj(zName16, sqlite3utf16ByteLen(zName16, -1)+2);
2192 Tcl_SetObjResult(interp, pRet);
2193 }
danielk197704f2e682004-05-27 01:04:07 +00002194
2195 return TCL_OK;
2196}
2197
2198/*
2199** Usage: sqlite3_column_int STMT column
2200**
2201** Usage: sqlite3_column_bytes STMT column
2202**
2203** Usage: sqlite3_column_bytes16 STMT column
2204**
2205*/
2206static int test_stmt_int(
drh241db312004-06-22 12:46:53 +00002207 void * clientData, /* Pointer to SQLite API function to be invoked */
danielk197704f2e682004-05-27 01:04:07 +00002208 Tcl_Interp *interp,
2209 int objc,
2210 Tcl_Obj *CONST objv[]
2211){
2212 sqlite3_stmt *pStmt;
2213 int col;
danielk1977c572ef72004-05-27 09:28:41 +00002214 int (*xFunc)(sqlite3_stmt*, int) = clientData;
danielk197704f2e682004-05-27 01:04:07 +00002215
2216 if( objc!=3 ){
2217 Tcl_AppendResult(interp, "wrong # args: should be \"",
2218 Tcl_GetString(objv[0]), " STMT column", 0);
2219 return TCL_ERROR;
2220 }
2221
2222 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2223 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2224
2225 Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col)));
2226 return TCL_OK;
2227}
2228
danielk19779a1d0ab2004-06-01 14:09:28 +00002229/*
2230** Usage: sqlite3OsOpenReadWrite <filename>
2231*/
2232static int test_sqlite3OsOpenReadWrite(
2233 void * clientData,
2234 Tcl_Interp *interp,
2235 int objc,
2236 Tcl_Obj *CONST objv[]
2237){
2238 OsFile * pFile;
2239 int rc;
2240 int dummy;
2241 char zBuf[100];
danielk197704f2e682004-05-27 01:04:07 +00002242
danielk19779a1d0ab2004-06-01 14:09:28 +00002243 if( objc!=2 ){
2244 Tcl_AppendResult(interp, "wrong # args: should be \"",
2245 Tcl_GetString(objv[0]), " filename", 0);
2246 return TCL_ERROR;
2247 }
2248
2249 pFile = sqliteMalloc(sizeof(OsFile));
2250 rc = sqlite3OsOpenReadWrite(Tcl_GetString(objv[1]), pFile, &dummy);
2251 if( rc!=SQLITE_OK ){
2252 sqliteFree(pFile);
2253 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2254 return TCL_ERROR;
2255 }
2256 makePointerStr(interp, zBuf, pFile);
2257 Tcl_SetResult(interp, zBuf, 0);
2258 return TCL_ERROR;
2259}
2260
2261/*
2262** Usage: sqlite3OsClose <file handle>
2263*/
2264static int test_sqlite3OsClose(
2265 void * clientData,
2266 Tcl_Interp *interp,
2267 int objc,
2268 Tcl_Obj *CONST objv[]
2269){
2270 OsFile * pFile;
2271 int rc;
2272
2273 if( objc!=2 ){
2274 Tcl_AppendResult(interp, "wrong # args: should be \"",
2275 Tcl_GetString(objv[0]), " filehandle", 0);
2276 return TCL_ERROR;
2277 }
2278
2279 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
2280 return TCL_ERROR;
2281 }
2282 rc = sqlite3OsClose(pFile);
2283 if( rc!=SQLITE_OK ){
2284 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2285 return TCL_ERROR;
2286 }
2287 sqliteFree(pFile);
2288 return TCL_OK;
2289}
2290
2291/*
2292** Usage: sqlite3OsLock <file handle> <locktype>
2293*/
2294static int test_sqlite3OsLock(
2295 void * clientData,
2296 Tcl_Interp *interp,
2297 int objc,
2298 Tcl_Obj *CONST objv[]
2299){
2300 OsFile * pFile;
2301 int rc;
2302
2303 if( objc!=3 ){
2304 Tcl_AppendResult(interp, "wrong # args: should be \"",
2305 Tcl_GetString(objv[0]),
2306 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
2307 return TCL_ERROR;
2308 }
2309
2310 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
2311 return TCL_ERROR;
2312 }
2313
2314 if( 0==strcmp("SHARED", Tcl_GetString(objv[2])) ){
2315 rc = sqlite3OsLock(pFile, SHARED_LOCK);
2316 }
2317 else if( 0==strcmp("RESERVED", Tcl_GetString(objv[2])) ){
2318 rc = sqlite3OsLock(pFile, RESERVED_LOCK);
2319 }
2320 else if( 0==strcmp("PENDING", Tcl_GetString(objv[2])) ){
2321 rc = sqlite3OsLock(pFile, PENDING_LOCK);
2322 }
2323 else if( 0==strcmp("EXCLUSIVE", Tcl_GetString(objv[2])) ){
2324 rc = sqlite3OsLock(pFile, EXCLUSIVE_LOCK);
2325 }else{
2326 Tcl_AppendResult(interp, "wrong # args: should be \"",
2327 Tcl_GetString(objv[0]),
2328 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
2329 return TCL_ERROR;
2330 }
2331
2332 if( rc!=SQLITE_OK ){
2333 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2334 return TCL_ERROR;
2335 }
2336 return TCL_OK;
2337}
2338
2339/*
2340** Usage: sqlite3OsUnlock <file handle>
2341*/
2342static int test_sqlite3OsUnlock(
2343 void * clientData,
2344 Tcl_Interp *interp,
2345 int objc,
2346 Tcl_Obj *CONST objv[]
2347){
2348 OsFile * pFile;
2349 int rc;
2350
2351 if( objc!=2 ){
2352 Tcl_AppendResult(interp, "wrong # args: should be \"",
2353 Tcl_GetString(objv[0]), " filehandle", 0);
2354 return TCL_ERROR;
2355 }
2356
2357 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
2358 return TCL_ERROR;
2359 }
drha6abd042004-06-09 17:37:22 +00002360 rc = sqlite3OsUnlock(pFile, NO_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00002361 if( rc!=SQLITE_OK ){
2362 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2363 return TCL_ERROR;
2364 }
2365 return TCL_OK;
2366}
drhd3d39e92004-05-20 22:16:29 +00002367
drhab3f9fe2004-08-14 17:10:10 +00002368/*
2369** Usage: sqlite3OsTempFileName
2370*/
2371static int test_sqlite3OsTempFileName(
2372 void * clientData,
2373 Tcl_Interp *interp,
2374 int objc,
2375 Tcl_Obj *CONST objv[]
2376){
2377 char zFile[SQLITE_TEMPNAME_SIZE];
2378 int rc;
2379
2380 rc = sqlite3OsTempFileName(zFile);
2381 if( rc!=SQLITE_OK ){
2382 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2383 return TCL_ERROR;
2384 }
2385 Tcl_AppendResult(interp, zFile, 0);
2386 return TCL_OK;
2387}
danielk1977d8123362004-06-12 09:25:12 +00002388
danielk19776622cce2004-05-20 11:00:52 +00002389/*
drh92febd92004-08-20 18:34:20 +00002390** Usage: tcl_variable_type VARIABLENAME
2391**
2392** Return the name of the internal representation for the
2393** value of the given variable.
2394*/
2395static int tcl_variable_type(
2396 void * clientData,
2397 Tcl_Interp *interp,
2398 int objc,
2399 Tcl_Obj *CONST objv[]
2400){
2401 Tcl_Obj *pVar;
2402 if( objc!=2 ){
2403 Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE");
2404 return TCL_ERROR;
2405 }
2406 pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG);
2407 if( pVar==0 ) return TCL_ERROR;
2408 if( pVar->typePtr ){
2409 Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1));
2410 }
2411 return TCL_OK;
2412}
2413
2414/*
drhd1bf3512001-04-07 15:24:33 +00002415** Register commands with the TCL interpreter.
2416*/
2417int Sqlitetest1_Init(Tcl_Interp *interp){
danielk19776f8a5032004-05-10 10:34:51 +00002418 extern int sqlite3_search_count;
2419 extern int sqlite3_interrupt_count;
2420 extern int sqlite3_open_file_count;
2421 extern int sqlite3_current_time;
drhc2eef3b2002-08-31 18:53:06 +00002422 static struct {
2423 char *zName;
2424 Tcl_CmdProc *xProc;
2425 } aCmd[] = {
drhd3d39e92004-05-20 22:16:29 +00002426 { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int },
drhe9707672004-06-25 01:10:48 +00002427 { "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 },
drhd3d39e92004-05-20 22:16:29 +00002428 { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str },
drhe29b1a02004-07-17 21:56:09 +00002429 { "sqlite3_mprintf_stronly", (Tcl_CmdProc*)sqlite3_mprintf_stronly},
drhd3d39e92004-05-20 22:16:29 +00002430 { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double },
2431 { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled },
2432 { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z },
drhd3d39e92004-05-20 22:16:29 +00002433 { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid },
2434 { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf },
2435 { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf },
2436 { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close },
2437 { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function },
2438 { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate },
2439 { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func },
2440 { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort },
drhfaa57ac2004-06-09 14:01:51 +00002441#ifdef SQLITE_DEBUG
drhd3d39e92004-05-20 22:16:29 +00002442 { "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail },
2443 { "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat },
drhc2eef3b2002-08-31 18:53:06 +00002444#endif
drh25d65432004-07-22 15:02:25 +00002445 { "sqlite_bind", (Tcl_CmdProc*)test_bind },
2446 { "breakpoint", (Tcl_CmdProc*)test_breakpoint },
2447 { "sqlite3_key", (Tcl_CmdProc*)test_key },
2448 { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey },
drhc2eef3b2002-08-31 18:53:06 +00002449 };
danielk197751e3d8e2004-05-20 01:12:34 +00002450 static struct {
2451 char *zName;
2452 Tcl_ObjCmdProc *xProc;
danielk197704f2e682004-05-27 01:04:07 +00002453 void *clientData;
danielk197751e3d8e2004-05-20 01:12:34 +00002454 } aObjCmd[] = {
drh241db312004-06-22 12:46:53 +00002455 { "sqlite3_bind_int", test_bind_int, 0 },
2456 { "sqlite3_bind_int64", test_bind_int64, 0 },
2457 { "sqlite3_bind_double", test_bind_double, 0 },
danielk197704f2e682004-05-27 01:04:07 +00002458 { "sqlite3_bind_null", test_bind_null ,0 },
2459 { "sqlite3_bind_text", test_bind_text ,0 },
2460 { "sqlite3_bind_text16", test_bind_text16 ,0 },
2461 { "sqlite3_bind_blob", test_bind_blob ,0 },
drh75f6a032004-07-15 14:15:00 +00002462 { "sqlite3_bind_parameter_count", test_bind_parameter_count, 0},
drh895d7472004-08-20 16:02:39 +00002463 { "sqlite3_bind_parameter_name", test_bind_parameter_name, 0},
drhfa6bc002004-09-07 16:19:52 +00002464 { "sqlite3_bind_parameter_index", test_bind_parameter_index, 0},
danielk197704f2e682004-05-27 01:04:07 +00002465 { "sqlite3_errcode", test_errcode ,0 },
2466 { "sqlite3_errmsg", test_errmsg ,0 },
2467 { "sqlite3_errmsg16", test_errmsg16 ,0 },
2468 { "sqlite3_open", test_open ,0 },
2469 { "sqlite3_open16", test_open16 ,0 },
danielk1977bc6ada42004-06-30 08:20:16 +00002470 { "sqlite3_complete16", test_complete16 ,0 },
danielk197704f2e682004-05-27 01:04:07 +00002471
2472 { "sqlite3_prepare", test_prepare ,0 },
2473 { "sqlite3_prepare16", test_prepare16 ,0 },
2474 { "sqlite3_finalize", test_finalize ,0 },
2475 { "sqlite3_reset", test_reset ,0 },
danielk1977fbcd5852004-06-15 02:44:18 +00002476 { "sqlite3_changes", test_changes ,0 },
2477 { "sqlite3_step", test_step ,0 },
danielk197704f2e682004-05-27 01:04:07 +00002478
2479 /* sqlite3_column_*() API */
2480 { "sqlite3_column_count", test_column_count ,0 },
2481 { "sqlite3_data_count", test_data_count ,0 },
2482 { "sqlite3_column_type", test_column_type ,0 },
danielk1977ea61b2c2004-05-27 01:49:51 +00002483 { "sqlite3_column_blob", test_column_blob ,0 },
danielk197704f2e682004-05-27 01:04:07 +00002484 { "sqlite3_column_double", test_column_double ,0 },
2485 { "sqlite3_column_int64", test_column_int64 ,0 },
drh241db312004-06-22 12:46:53 +00002486 { "sqlite3_column_int", test_stmt_int, sqlite3_column_int },
2487 { "sqlite3_column_bytes", test_stmt_int, sqlite3_column_bytes },
2488 { "sqlite3_column_bytes16", test_stmt_int, sqlite3_column_bytes16 },
2489 { "sqlite3_column_text", test_stmt_utf8, sqlite3_column_text },
2490 { "sqlite3_column_decltype", test_stmt_utf8, sqlite3_column_decltype },
2491 { "sqlite3_column_name", test_stmt_utf8, sqlite3_column_name },
2492 { "sqlite3_column_text16", test_stmt_utf16, sqlite3_column_text16 },
2493 { "sqlite3_column_decltype16", test_stmt_utf16, sqlite3_column_decltype16},
2494 { "sqlite3_column_name16", test_stmt_utf16, sqlite3_column_name16 },
danielk197704f2e682004-05-27 01:04:07 +00002495
danielk19779a1d0ab2004-06-01 14:09:28 +00002496 /* Functions from os.h */
2497 { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 },
2498 { "sqlite3OsClose", test_sqlite3OsClose, 0 },
2499 { "sqlite3OsLock", test_sqlite3OsLock, 0 },
drhab3f9fe2004-08-14 17:10:10 +00002500 { "sqlite3OsTempFileName", test_sqlite3OsTempFileName, 0 },
danielk1977312d6b32004-06-29 13:18:23 +00002501
2502 /* Custom test interfaces */
2503 { "sqlite3OsUnlock", test_sqlite3OsUnlock, 0 },
2504 { "add_test_collate", test_collate, 0 },
2505 { "add_test_collate_needed", test_collate_needed, 0 },
2506 { "add_test_function", test_function, 0 },
2507 { "sqlite3_crashparams", sqlite3_crashparams, 0 },
2508 { "sqlite3_test_errstr", test_errstr, 0 },
drh92febd92004-08-20 18:34:20 +00002509 { "tcl_variable_type", tcl_variable_type, 0 },
danielk19779a1d0ab2004-06-01 14:09:28 +00002510
danielk197751e3d8e2004-05-20 01:12:34 +00002511 };
drhc2eef3b2002-08-31 18:53:06 +00002512 int i;
drh2ac3ee92004-06-07 16:27:46 +00002513 extern int sqlite3_os_trace;
drhc2eef3b2002-08-31 18:53:06 +00002514
2515 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
2516 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
2517 }
danielk197751e3d8e2004-05-20 01:12:34 +00002518 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
danielk1977c572ef72004-05-27 09:28:41 +00002519 Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
2520 aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
danielk197751e3d8e2004-05-20 01:12:34 +00002521 }
danielk19776490beb2004-05-11 06:17:21 +00002522 Tcl_LinkVar(interp, "sqlite_search_count",
danielk19776f8a5032004-05-10 10:34:51 +00002523 (char*)&sqlite3_search_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00002524 Tcl_LinkVar(interp, "sqlite_interrupt_count",
danielk19776f8a5032004-05-10 10:34:51 +00002525 (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00002526 Tcl_LinkVar(interp, "sqlite_open_file_count",
danielk19776f8a5032004-05-10 10:34:51 +00002527 (char*)&sqlite3_open_file_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00002528 Tcl_LinkVar(interp, "sqlite_current_time",
danielk19776f8a5032004-05-10 10:34:51 +00002529 (char*)&sqlite3_current_time, TCL_LINK_INT);
drh2ac3ee92004-06-07 16:27:46 +00002530 Tcl_LinkVar(interp, "sqlite_os_trace",
2531 (char*)&sqlite3_os_trace, TCL_LINK_INT);
drh7c972de2003-09-06 22:18:07 +00002532 Tcl_LinkVar(interp, "sqlite_static_bind_value",
2533 (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
drhab3f9fe2004-08-14 17:10:10 +00002534 Tcl_LinkVar(interp, "sqlite_temp_directory",
drheffd02b2004-08-29 23:42:13 +00002535 (char*)&sqlite3_temp_directory, TCL_LINK_STRING);
drhd1bf3512001-04-07 15:24:33 +00002536 return TCL_OK;
2537}