blob: 108de7a64097e5d6c126215050a820b2ef61ea0f [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*************************************************************************
drh05a82982006-03-19 13:00:25 +000012** Code for testing all sorts of SQLite interfaces. This code
drhd1bf3512001-04-07 15:24:33 +000013** is not included in the SQLite library. It is used for automated
14** testing of the SQLite library.
15**
drhdd735212007-02-24 13:53:05 +000016** $Id: test1.c,v 1.229 2007/02/24 13:53: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
drhdddca282006-01-03 00:33:50 +000024/*
25** This is a copy of the first part of the SqliteDb structure in
26** tclsqlite.c. We need it here so that the get_sqlite_pointer routine
27** can extract the sqlite3* pointer from an existing Tcl SQLite
28** connection.
29*/
30struct SqliteDb {
31 sqlite3 *db;
32};
33
34/*
35** A TCL command that returns the address of the sqlite* pointer
36** for an sqlite connection instance. Bad things happen if the
37** input is not an sqlite connection.
38*/
39static int get_sqlite_pointer(
40 void * clientData,
41 Tcl_Interp *interp,
42 int objc,
43 Tcl_Obj *CONST objv[]
44){
45 struct SqliteDb *p;
46 Tcl_CmdInfo cmdInfo;
47 char zBuf[100];
48 if( objc!=2 ){
49 Tcl_WrongNumArgs(interp, 1, objv, "SQLITE-CONNECTION");
50 return TCL_ERROR;
51 }
52 if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
53 Tcl_AppendResult(interp, "command not found: ",
54 Tcl_GetString(objv[1]), (char*)0);
55 return TCL_ERROR;
56 }
57 p = (struct SqliteDb*)cmdInfo.objClientData;
58 sprintf(zBuf, "%p", p->db);
59 if( strncmp(zBuf,"0x",2) ){
60 sprintf(zBuf, "0x%p", p->db);
61 }
62 Tcl_AppendResult(interp, zBuf, 0);
63 return TCL_OK;
64}
65
drhb62c3352006-11-23 09:39:16 +000066/*
67** Decode a pointer to an sqlite3 object.
68*/
69static int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
70 struct SqliteDb *p;
71 Tcl_CmdInfo cmdInfo;
72 if( Tcl_GetCommandInfo(interp, zA, &cmdInfo) ){
73 p = (struct SqliteDb*)cmdInfo.objClientData;
74 *ppDb = p->db;
75 }else{
76 *ppDb = (sqlite3*)sqlite3TextToPtr(zA);
77 }
78 return TCL_OK;
79}
80
81
drh2e66f0b2005-04-28 17:18:48 +000082const char *sqlite3TestErrorName(int rc){
danielk19776622cce2004-05-20 11:00:52 +000083 const char *zName = 0;
drh4ac285a2006-09-15 07:28:50 +000084 switch( rc & 0xff ){
danielk19776622cce2004-05-20 11:00:52 +000085 case SQLITE_OK: zName = "SQLITE_OK"; break;
86 case SQLITE_ERROR: zName = "SQLITE_ERROR"; break;
danielk19776622cce2004-05-20 11:00:52 +000087 case SQLITE_PERM: zName = "SQLITE_PERM"; break;
88 case SQLITE_ABORT: zName = "SQLITE_ABORT"; break;
89 case SQLITE_BUSY: zName = "SQLITE_BUSY"; break;
90 case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break;
91 case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break;
92 case SQLITE_READONLY: zName = "SQLITE_READONLY"; break;
93 case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break;
94 case SQLITE_IOERR: zName = "SQLITE_IOERR"; break;
95 case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break;
danielk19776622cce2004-05-20 11:00:52 +000096 case SQLITE_FULL: zName = "SQLITE_FULL"; break;
97 case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break;
98 case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
99 case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break;
100 case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break;
danielk19776622cce2004-05-20 11:00:52 +0000101 case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break;
102 case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break;
103 case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break;
104 case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break;
105 case SQLITE_AUTH: zName = "SQLITE_AUTH"; break;
106 case SQLITE_FORMAT: zName = "SQLITE_FORMAT"; break;
107 case SQLITE_RANGE: zName = "SQLITE_RANGE"; break;
108 case SQLITE_ROW: zName = "SQLITE_ROW"; break;
109 case SQLITE_DONE: zName = "SQLITE_DONE"; break;
drhc60d0442004-09-30 13:43:13 +0000110 case SQLITE_NOTADB: zName = "SQLITE_NOTADB"; break;
danielk19776622cce2004-05-20 11:00:52 +0000111 default: zName = "SQLITE_Unknown"; break;
112 }
113 return zName;
114}
drh2e66f0b2005-04-28 17:18:48 +0000115#define errorName sqlite3TestErrorName
danielk19776622cce2004-05-20 11:00:52 +0000116
drhd1bf3512001-04-07 15:24:33 +0000117/*
drhc60d0442004-09-30 13:43:13 +0000118** Convert an sqlite3_stmt* into an sqlite3*. This depends on the
119** fact that the sqlite3* is the first field in the Vdbe structure.
120*/
drh51942bc2005-06-12 22:01:42 +0000121#define StmtToDb(X) sqlite3_db_handle(X)
drhc60d0442004-09-30 13:43:13 +0000122
123/*
124** Check a return value to make sure it agrees with the results
125** from sqlite3_errcode.
126*/
127int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){
128 if( rc!=SQLITE_MISUSE && rc!=SQLITE_OK && sqlite3_errcode(db)!=rc ){
129 char zBuf[200];
130 int r2 = sqlite3_errcode(db);
131 sprintf(zBuf, "error code %s (%d) does not match sqlite3_errcode %s (%d)",
132 errorName(rc), rc, errorName(r2), r2);
133 Tcl_ResetResult(interp);
134 Tcl_AppendResult(interp, zBuf, 0);
135 return 1;
136 }
137 return 0;
138}
139
140/*
danielk197751e3d8e2004-05-20 01:12:34 +0000141** Decode a pointer to an sqlite3_stmt object.
142*/
143static int getStmtPointer(
144 Tcl_Interp *interp,
145 const char *zArg,
146 sqlite3_stmt **ppStmt
147){
drhfe63d1c2004-09-08 20:13:04 +0000148 *ppStmt = (sqlite3_stmt*)sqlite3TextToPtr(zArg);
danielk197751e3d8e2004-05-20 01:12:34 +0000149 return TCL_OK;
150}
151
152/*
danielk19779a1d0ab2004-06-01 14:09:28 +0000153** Decode a pointer to an sqlite3_stmt object.
154*/
155static int getFilePointer(
156 Tcl_Interp *interp,
157 const char *zArg,
158 OsFile **ppFile
159){
drhfe63d1c2004-09-08 20:13:04 +0000160 *ppFile = (OsFile*)sqlite3TextToPtr(zArg);
danielk19779a1d0ab2004-06-01 14:09:28 +0000161 return TCL_OK;
162}
163
164/*
drh7d8085a2003-04-26 13:19:38 +0000165** Generate a text representation of a pointer that can be understood
166** by the getDbPointer and getVmPointer routines above.
167**
168** The problem is, on some machines (Solaris) if you do a printf with
169** "%p" you cannot turn around and do a scanf with the same "%p" and
170** get your pointer back. You have to prepend a "0x" before it will
171** work. Or at least that is what is reported to me (drh). But this
172** behavior varies from machine to machine. The solution used her is
173** to test the string right after it is generated to see if it can be
174** understood by scanf, and if not, try prepending an "0x" to see if
175** that helps. If nothing works, a fatal error is generated.
176*/
drh64b1bea2006-01-15 02:30:57 +0000177int sqlite3TestMakePointerStr(Tcl_Interp *interp, char *zPtr, void *p){
drhfe63d1c2004-09-08 20:13:04 +0000178 sqlite3_snprintf(100, zPtr, "%p", p);
drh7d8085a2003-04-26 13:19:38 +0000179 return TCL_OK;
180}
181
182/*
danielk19776f8a5032004-05-10 10:34:51 +0000183** The callback routine for sqlite3_exec_printf().
drhd1bf3512001-04-07 15:24:33 +0000184*/
185static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){
186 Tcl_DString *str = (Tcl_DString*)pArg;
187 int i;
188
189 if( Tcl_DStringLength(str)==0 ){
190 for(i=0; i<argc; i++){
191 Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL");
192 }
193 }
194 for(i=0; i<argc; i++){
195 Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL");
196 }
197 return 0;
198}
199
200/*
danielk19776f8a5032004-05-10 10:34:51 +0000201** Usage: sqlite3_exec_printf DB FORMAT STRING
drhd1bf3512001-04-07 15:24:33 +0000202**
danielk19776f8a5032004-05-10 10:34:51 +0000203** Invoke the sqlite3_exec_printf() interface using the open database
drhd1bf3512001-04-07 15:24:33 +0000204** DB. The SQL is the string FORMAT. The format string should contain
205** one %s or %q. STRING is the value inserted into %s or %q.
206*/
207static int test_exec_printf(
208 void *NotUsed,
209 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
210 int argc, /* Number of arguments */
211 char **argv /* Text of each argument */
212){
drh9bb575f2004-09-06 17:24:11 +0000213 sqlite3 *db;
drhd1bf3512001-04-07 15:24:33 +0000214 Tcl_DString str;
215 int rc;
216 char *zErr = 0;
drh1211de32004-07-26 12:24:22 +0000217 char *zSql;
drhd1bf3512001-04-07 15:24:33 +0000218 char zBuf[30];
219 if( argc!=4 ){
220 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
221 " DB FORMAT STRING", 0);
222 return TCL_ERROR;
223 }
drhb86ccfb2003-01-28 23:13:10 +0000224 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000225 Tcl_DStringInit(&str);
drh1211de32004-07-26 12:24:22 +0000226 zSql = sqlite3_mprintf(argv[2], argv[3]);
227 rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
228 sqlite3_free(zSql);
drhd1bf3512001-04-07 15:24:33 +0000229 sprintf(zBuf, "%d", rc);
230 Tcl_AppendElement(interp, zBuf);
231 Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
232 Tcl_DStringFree(&str);
danielk1977926aab22006-06-27 07:34:40 +0000233 if( zErr ) sqlite3_free(zErr);
drhc60d0442004-09-30 13:43:13 +0000234 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000235 return TCL_OK;
236}
237
238/*
drhb62c3352006-11-23 09:39:16 +0000239** Usage: sqlite3_exec DB SQL
240**
241** Invoke the sqlite3_exec interface using the open database DB
242*/
243static int test_exec(
244 void *NotUsed,
245 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
246 int argc, /* Number of arguments */
247 char **argv /* Text of each argument */
248){
249 sqlite3 *db;
250 Tcl_DString str;
251 int rc;
252 char *zErr = 0;
253 char zBuf[30];
254 if( argc!=3 ){
255 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
256 " DB SQL", 0);
257 return TCL_ERROR;
258 }
259 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
260 Tcl_DStringInit(&str);
261 rc = sqlite3_exec(db, argv[2], exec_printf_cb, &str, &zErr);
262 sprintf(zBuf, "%d", rc);
263 Tcl_AppendElement(interp, zBuf);
264 Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
265 Tcl_DStringFree(&str);
266 if( zErr ) sqlite3_free(zErr);
267 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
268 return TCL_OK;
269}
270
271/*
272** Usage: sqlite3_exec_nr DB SQL
273**
274** Invoke the sqlite3_exec interface using the open database DB. Discard
275** all results
276*/
277static int test_exec_nr(
278 void *NotUsed,
279 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
280 int argc, /* Number of arguments */
281 char **argv /* Text of each argument */
282){
283 sqlite3 *db;
284 int rc;
285 char *zErr = 0;
286 if( argc!=3 ){
287 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
288 " DB SQL", 0);
289 return TCL_ERROR;
290 }
291 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
292 rc = sqlite3_exec(db, argv[2], 0, 0, &zErr);
293 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
294 return TCL_OK;
295}
296
297/*
danielk19776f8a5032004-05-10 10:34:51 +0000298** Usage: sqlite3_mprintf_z_test SEPARATOR ARG0 ARG1 ...
drhd93d8a82003-06-16 03:08:18 +0000299**
drh05a82982006-03-19 13:00:25 +0000300** Test the %z format of sqliteMPrintf(). Use multiple mprintf() calls to
drhd93d8a82003-06-16 03:08:18 +0000301** concatenate arg0 through argn using separator as the separator.
302** Return the result.
303*/
304static int test_mprintf_z(
305 void *NotUsed,
306 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
307 int argc, /* Number of arguments */
308 char **argv /* Text of each argument */
309){
310 char *zResult = 0;
311 int i;
312
313 for(i=2; i<argc; i++){
danielk19774adee202004-05-08 08:23:19 +0000314 zResult = sqlite3MPrintf("%z%s%s", zResult, argv[1], argv[i]);
drhd93d8a82003-06-16 03:08:18 +0000315 }
316 Tcl_AppendResult(interp, zResult, 0);
drh5f968432004-02-21 19:02:30 +0000317 sqliteFree(zResult);
drhd93d8a82003-06-16 03:08:18 +0000318 return TCL_OK;
319}
320
321/*
drh05a82982006-03-19 13:00:25 +0000322** Usage: sqlite3_mprintf_n_test STRING
323**
324** Test the %n format of sqliteMPrintf(). Return the length of the
325** input string.
326*/
327static int test_mprintf_n(
328 void *NotUsed,
329 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
330 int argc, /* Number of arguments */
331 char **argv /* Text of each argument */
332){
333 char *zStr;
334 int n = 0;
335 zStr = sqlite3MPrintf("%s%n", argv[1], &n);
336 sqliteFree(zStr);
337 Tcl_SetObjResult(interp, Tcl_NewIntObj(n));
338 return TCL_OK;
339}
340
341/*
danielk19776f8a5032004-05-10 10:34:51 +0000342** Usage: sqlite3_get_table_printf DB FORMAT STRING
drhd1bf3512001-04-07 15:24:33 +0000343**
danielk19776f8a5032004-05-10 10:34:51 +0000344** Invoke the sqlite3_get_table_printf() interface using the open database
drhd1bf3512001-04-07 15:24:33 +0000345** DB. The SQL is the string FORMAT. The format string should contain
346** one %s or %q. STRING is the value inserted into %s or %q.
347*/
348static int test_get_table_printf(
349 void *NotUsed,
350 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
351 int argc, /* Number of arguments */
352 char **argv /* Text of each argument */
353){
drh9bb575f2004-09-06 17:24:11 +0000354 sqlite3 *db;
drhd1bf3512001-04-07 15:24:33 +0000355 Tcl_DString str;
356 int rc;
357 char *zErr = 0;
358 int nRow, nCol;
359 char **aResult;
360 int i;
361 char zBuf[30];
drh1211de32004-07-26 12:24:22 +0000362 char *zSql;
drhd1bf3512001-04-07 15:24:33 +0000363 if( argc!=4 ){
364 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
365 " DB FORMAT STRING", 0);
366 return TCL_ERROR;
367 }
drhb86ccfb2003-01-28 23:13:10 +0000368 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000369 Tcl_DStringInit(&str);
drh1211de32004-07-26 12:24:22 +0000370 zSql = sqlite3_mprintf(argv[2],argv[3]);
371 rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr);
372 sqlite3_free(zSql);
drhd1bf3512001-04-07 15:24:33 +0000373 sprintf(zBuf, "%d", rc);
374 Tcl_AppendElement(interp, zBuf);
375 if( rc==SQLITE_OK ){
376 sprintf(zBuf, "%d", nRow);
377 Tcl_AppendElement(interp, zBuf);
378 sprintf(zBuf, "%d", nCol);
379 Tcl_AppendElement(interp, zBuf);
380 for(i=0; i<(nRow+1)*nCol; i++){
381 Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL");
382 }
383 }else{
384 Tcl_AppendElement(interp, zErr);
385 }
danielk19776f8a5032004-05-10 10:34:51 +0000386 sqlite3_free_table(aResult);
danielk1977926aab22006-06-27 07:34:40 +0000387 if( zErr ) sqlite3_free(zErr);
drhc60d0442004-09-30 13:43:13 +0000388 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000389 return TCL_OK;
390}
391
drhaf9ff332002-01-16 21:00:27 +0000392
393/*
danielk19776f8a5032004-05-10 10:34:51 +0000394** Usage: sqlite3_last_insert_rowid DB
drhaf9ff332002-01-16 21:00:27 +0000395**
396** Returns the integer ROWID of the most recent insert.
397*/
398static int test_last_rowid(
399 void *NotUsed,
400 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
401 int argc, /* Number of arguments */
402 char **argv /* Text of each argument */
403){
drh9bb575f2004-09-06 17:24:11 +0000404 sqlite3 *db;
drhaf9ff332002-01-16 21:00:27 +0000405 char zBuf[30];
406
407 if( argc!=2 ){
408 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0);
409 return TCL_ERROR;
410 }
drhb86ccfb2003-01-28 23:13:10 +0000411 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk1977c572ef72004-05-27 09:28:41 +0000412 sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db));
drhaf9ff332002-01-16 21:00:27 +0000413 Tcl_AppendResult(interp, zBuf, 0);
414 return SQLITE_OK;
415}
416
drhd1bf3512001-04-07 15:24:33 +0000417/*
drh25d65432004-07-22 15:02:25 +0000418** Usage: sqlite3_key DB KEY
419**
420** Set the codec key.
421*/
422static int test_key(
423 void *NotUsed,
424 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
425 int argc, /* Number of arguments */
426 char **argv /* Text of each argument */
427){
drh9bb575f2004-09-06 17:24:11 +0000428 sqlite3 *db;
drh25d65432004-07-22 15:02:25 +0000429 const char *zKey;
430 int nKey;
431 if( argc!=3 ){
432 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
433 " FILENAME\"", 0);
434 return TCL_ERROR;
435 }
436 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
437 zKey = argv[2];
438 nKey = strlen(zKey);
439#ifdef SQLITE_HAS_CODEC
440 sqlite3_key(db, zKey, nKey);
441#endif
442 return TCL_OK;
443}
444
445/*
446** Usage: sqlite3_rekey DB KEY
447**
448** Change the codec key.
449*/
450static int test_rekey(
451 void *NotUsed,
452 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
453 int argc, /* Number of arguments */
454 char **argv /* Text of each argument */
455){
drh9bb575f2004-09-06 17:24:11 +0000456 sqlite3 *db;
drh25d65432004-07-22 15:02:25 +0000457 const char *zKey;
458 int nKey;
459 if( argc!=3 ){
460 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
461 " FILENAME\"", 0);
462 return TCL_ERROR;
463 }
464 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
465 zKey = argv[2];
466 nKey = strlen(zKey);
467#ifdef SQLITE_HAS_CODEC
468 sqlite3_rekey(db, zKey, nKey);
469#endif
470 return TCL_OK;
471}
472
473/*
danielk19776f8a5032004-05-10 10:34:51 +0000474** Usage: sqlite3_close DB
drhd1bf3512001-04-07 15:24:33 +0000475**
danielk19776f8a5032004-05-10 10:34:51 +0000476** Closes the database opened by sqlite3_open.
drhd1bf3512001-04-07 15:24:33 +0000477*/
478static int sqlite_test_close(
479 void *NotUsed,
480 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
481 int argc, /* Number of arguments */
482 char **argv /* Text of each argument */
483){
drh9bb575f2004-09-06 17:24:11 +0000484 sqlite3 *db;
danielk197796d81f92004-06-19 03:33:57 +0000485 int rc;
drhd1bf3512001-04-07 15:24:33 +0000486 if( argc!=2 ){
487 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
488 " FILENAME\"", 0);
489 return TCL_ERROR;
490 }
drhb86ccfb2003-01-28 23:13:10 +0000491 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk197796d81f92004-06-19 03:33:57 +0000492 rc = sqlite3_close(db);
danielk1977f9d64d22004-06-19 08:18:07 +0000493 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
drhd1bf3512001-04-07 15:24:33 +0000494 return TCL_OK;
495}
496
497/*
drhc22bd472002-05-10 13:14:07 +0000498** Implementation of the x_coalesce() function.
499** Return the first argument non-NULL argument.
500*/
danielk19770ae8b832004-05-25 12:05:56 +0000501static void ifnullFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
drhc22bd472002-05-10 13:14:07 +0000502 int i;
503 for(i=0; i<argc; i++){
drh9c054832004-05-31 18:51:57 +0000504 if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
drh03d847e2005-12-09 20:21:58 +0000505 sqlite3_result_text(context, (char*)sqlite3_value_text(argv[i]),
drh5c434b72005-12-05 13:20:01 +0000506 sqlite3_value_bytes(argv[i]), SQLITE_TRANSIENT);
drhc22bd472002-05-10 13:14:07 +0000507 break;
508 }
509 }
510}
511
512/*
drhf0313812006-09-04 15:53:53 +0000513** These are test functions. hex8() interprets its argument as
514** UTF8 and returns a hex encoding. hex16le() interprets its argument
515** as UTF16le and returns a hex encoding.
516*/
517static void hex8Func(sqlite3_context *p, int argc, sqlite3_value **argv){
518 const unsigned char *z;
519 int i;
520 char zBuf[200];
521 z = sqlite3_value_text(argv[0]);
522 for(i=0; i<sizeof(zBuf)/2 - 2 && z[i]; i++){
523 sprintf(&zBuf[i*2], "%02x", z[i]&0xff);
524 }
525 zBuf[i*2] = 0;
526 sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
527}
528static void hex16Func(sqlite3_context *p, int argc, sqlite3_value **argv){
529 const unsigned short int *z;
530 int i;
531 char zBuf[400];
532 z = sqlite3_value_text16(argv[0]);
533 for(i=0; i<sizeof(zBuf)/4 - 4 && z[i]; i++){
534 sprintf(&zBuf[i*4], "%04x", z[i]&0xff);
535 }
536 zBuf[i*4] = 0;
537 sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
538}
539
540/*
drhd1d9fc32004-01-07 19:24:48 +0000541** A structure into which to accumulate text.
542*/
543struct dstr {
544 int nAlloc; /* Space allocated */
545 int nUsed; /* Space used */
546 char *z; /* The space */
547};
548
549/*
550** Append text to a dstr
551*/
552static void dstrAppend(struct dstr *p, const char *z, int divider){
553 int n = strlen(z);
554 if( p->nUsed + n + 2 > p->nAlloc ){
555 char *zNew;
556 p->nAlloc = p->nAlloc*2 + n + 200;
557 zNew = sqliteRealloc(p->z, p->nAlloc);
558 if( zNew==0 ){
559 sqliteFree(p->z);
560 memset(p, 0, sizeof(*p));
561 return;
562 }
563 p->z = zNew;
564 }
565 if( divider && p->nUsed>0 ){
566 p->z[p->nUsed++] = divider;
567 }
568 memcpy(&p->z[p->nUsed], z, n+1);
569 p->nUsed += n;
570}
571
572/*
danielk19774adee202004-05-08 08:23:19 +0000573** Invoked for each callback from sqlite3ExecFunc
drhd1d9fc32004-01-07 19:24:48 +0000574*/
575static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){
576 struct dstr *p = (struct dstr*)pData;
577 int i;
578 for(i=0; i<argc; i++){
579 if( argv[i]==0 ){
580 dstrAppend(p, "NULL", ' ');
581 }else{
582 dstrAppend(p, argv[i], ' ');
583 }
584 }
585 return 0;
586}
587
588/*
danielk1977e35ee192004-06-26 09:50:11 +0000589** Implementation of the x_sqlite_exec() function. This function takes
drhc22bd472002-05-10 13:14:07 +0000590** a single argument and attempts to execute that argument as SQL code.
drh6cbe1f12002-07-01 00:31:36 +0000591** This is illegal and should set the SQLITE_MISUSE flag on the database.
drhd1d9fc32004-01-07 19:24:48 +0000592**
danielk19776f8a5032004-05-10 10:34:51 +0000593** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec()
drhd1d9fc32004-01-07 19:24:48 +0000594** from within a function call.
drhc22bd472002-05-10 13:14:07 +0000595**
596** This routine simulates the effect of having two threads attempt to
597** use the same database at the same time.
598*/
danielk197751ad0ec2004-05-24 12:39:02 +0000599static void sqlite3ExecFunc(
danielk19770ae8b832004-05-25 12:05:56 +0000600 sqlite3_context *context,
danielk197751ad0ec2004-05-24 12:39:02 +0000601 int argc,
602 sqlite3_value **argv
603){
drhd1d9fc32004-01-07 19:24:48 +0000604 struct dstr x;
605 memset(&x, 0, sizeof(x));
drh37527852006-03-16 16:19:56 +0000606 (void)sqlite3_exec((sqlite3*)sqlite3_user_data(context),
drh03d847e2005-12-09 20:21:58 +0000607 (char*)sqlite3_value_text(argv[0]),
drhd1d9fc32004-01-07 19:24:48 +0000608 execFuncCallback, &x, 0);
danielk1977d8123362004-06-12 09:25:12 +0000609 sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT);
drhd1d9fc32004-01-07 19:24:48 +0000610 sqliteFree(x.z);
drhc22bd472002-05-10 13:14:07 +0000611}
612
613/*
danielk1977d7263922007-02-05 14:21:47 +0000614** Implementation of tkt2213func(), a scalar function that takes exactly
615** one argument. It has two interesting features:
616**
617** * It calls sqlite3_value_text() 3 times on the argument sqlite3_value*.
618** If the three pointers returned are not the same an SQL error is raised.
619**
620** * Otherwise it returns a copy of the text representation of it's
621** argument in such a way as the VDBE representation is a Mem* cell
622** with the MEM_Term flag clear.
623**
624** Ticket #2213 can therefore be tested by evaluating the following
625** SQL expression:
626**
627** tkt2213func(tkt2213func('a string'));
628*/
629static void tkt2213Function(
630 sqlite3_context *context,
631 int argc,
632 sqlite3_value **argv
633){
634 int nText;
635 unsigned char const *zText1;
636 unsigned char const *zText2;
637 unsigned char const *zText3;
638
639 nText = sqlite3_value_bytes(argv[0]);
640 zText1 = sqlite3_value_text(argv[0]);
641 zText2 = sqlite3_value_text(argv[0]);
642 zText3 = sqlite3_value_text(argv[0]);
643
644 if( zText1!=zText2 || zText2!=zText3 ){
645 sqlite3_result_error(context, "tkt2213 is not fixed", -1);
646 }else{
647 char *zCopy = (char *)sqlite3_malloc(nText);
648 memcpy(zCopy, zText1, nText);
649 sqlite3_result_text(context, zCopy, nText, sqlite3_free);
650 }
651}
652
653/*
drhc22bd472002-05-10 13:14:07 +0000654** Usage: sqlite_test_create_function DB
655**
danielk19776f8a5032004-05-10 10:34:51 +0000656** Call the sqlite3_create_function API on the given database in order
drhc22bd472002-05-10 13:14:07 +0000657** to create a function named "x_coalesce". This function does the same thing
658** as the "coalesce" function. This function also registers an SQL function
danielk1977e35ee192004-06-26 09:50:11 +0000659** named "x_sqlite_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec()
drhc22bd472002-05-10 13:14:07 +0000660** in this way is illegal recursion and should raise an SQLITE_MISUSE error.
661** The effect is similar to trying to use the same database connection from
662** two threads at the same time.
663**
664** The original motivation for this routine was to be able to call the
danielk19776f8a5032004-05-10 10:34:51 +0000665** sqlite3_create_function function while a query is in progress in order
drhc22bd472002-05-10 13:14:07 +0000666** to test the SQLITE_MISUSE detection logic.
667*/
drhc2eef3b2002-08-31 18:53:06 +0000668static int test_create_function(
drhc22bd472002-05-10 13:14:07 +0000669 void *NotUsed,
670 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
671 int argc, /* Number of arguments */
672 char **argv /* Text of each argument */
673){
drhc60d0442004-09-30 13:43:13 +0000674 int rc;
drh9bb575f2004-09-06 17:24:11 +0000675 sqlite3 *db;
drh9bb575f2004-09-06 17:24:11 +0000676 extern void Md5_Register(sqlite3*);
danielk1977312d6b32004-06-29 13:18:23 +0000677
drhc22bd472002-05-10 13:14:07 +0000678 if( argc!=2 ){
679 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
danielk19774397de52005-01-12 12:44:03 +0000680 " DB\"", 0);
drhc22bd472002-05-10 13:14:07 +0000681 return TCL_ERROR;
682 }
drhb86ccfb2003-01-28 23:13:10 +0000683 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +0000684 rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0,
685 ifnullFunc, 0, 0);
drh235a8182006-09-13 19:21:28 +0000686 if( rc==SQLITE_OK ){
687 rc = sqlite3_create_function(db, "hex8", 1, SQLITE_ANY, 0,
688 hex8Func, 0, 0);
689 }
690 if( rc==SQLITE_OK ){
691 rc = sqlite3_create_function(db, "hex16", 1, SQLITE_ANY, 0,
692 hex16Func, 0, 0);
693 }
danielk1977d7263922007-02-05 14:21:47 +0000694 if( rc==SQLITE_OK ){
695 rc = sqlite3_create_function(db, "tkt2213func", 1, SQLITE_ANY, 0,
696 tkt2213Function, 0, 0);
697 }
danielk1977312d6b32004-06-29 13:18:23 +0000698
drh5436dc22004-11-14 04:04:17 +0000699#ifndef SQLITE_OMIT_UTF16
danielk1977312d6b32004-06-29 13:18:23 +0000700 /* Use the sqlite3_create_function16() API here. Mainly for fun, but also
701 ** because it is not tested anywhere else. */
drhc60d0442004-09-30 13:43:13 +0000702 if( rc==SQLITE_OK ){
danielk1977576ec6b2005-01-21 11:55:25 +0000703 sqlite3_value *pVal;
danielk1977771151b2006-01-17 13:21:40 +0000704#ifdef SQLITE_MEMDEBUG
705 if( sqlite3_iMallocFail>0 ){
706 sqlite3_iMallocFail++;
707 }
708#endif
drhc60d0442004-09-30 13:43:13 +0000709 pVal = sqlite3ValueNew();
710 sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC);
711 rc = sqlite3_create_function16(db,
712 sqlite3ValueText(pVal, SQLITE_UTF16NATIVE),
713 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
714 sqlite3ValueFree(pVal);
715 }
drh5436dc22004-11-14 04:04:17 +0000716#endif
717
drhc60d0442004-09-30 13:43:13 +0000718 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk19774397de52005-01-12 12:44:03 +0000719 Tcl_SetResult(interp, (char *)errorName(rc), 0);
drhc22bd472002-05-10 13:14:07 +0000720 return TCL_OK;
721}
722
723/*
724** Routines to implement the x_count() aggregate function.
drh90669c12006-01-20 15:45:36 +0000725**
726** x_count() counts the number of non-null arguments. But there are
727** some twists for testing purposes.
728**
729** If the argument to x_count() is 40 then a UTF-8 error is reported
730** on the step function. If x_count(41) is seen, then a UTF-16 error
731** is reported on the step function. If the total count is 42, then
732** a UTF-8 error is reported on the finalize function.
drhc22bd472002-05-10 13:14:07 +0000733*/
734typedef struct CountCtx CountCtx;
735struct CountCtx {
736 int n;
737};
danielk19770ae8b832004-05-25 12:05:56 +0000738static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
drhc22bd472002-05-10 13:14:07 +0000739 CountCtx *p;
drh4f26d6c2004-05-26 23:25:30 +0000740 p = sqlite3_aggregate_context(context, sizeof(*p));
drh9c054832004-05-31 18:51:57 +0000741 if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){
drhc22bd472002-05-10 13:14:07 +0000742 p->n++;
743 }
drh90669c12006-01-20 15:45:36 +0000744 if( argc>0 ){
745 int v = sqlite3_value_int(argv[0]);
746 if( v==40 ){
747 sqlite3_result_error(context, "value of 40 handed to x_count", -1);
danielk1977a1686c92006-01-23 07:52:37 +0000748#ifndef SQLITE_OMIT_UTF16
drh90669c12006-01-20 15:45:36 +0000749 }else if( v==41 ){
750 const char zUtf16ErrMsg[] = { 0, 0x61, 0, 0x62, 0, 0x63, 0, 0, 0};
751 sqlite3_result_error16(context, &zUtf16ErrMsg[1-SQLITE_BIGENDIAN], -1);
danielk1977a1686c92006-01-23 07:52:37 +0000752#endif
drh90669c12006-01-20 15:45:36 +0000753 }
754 }
drhc22bd472002-05-10 13:14:07 +0000755}
danielk19770ae8b832004-05-25 12:05:56 +0000756static void countFinalize(sqlite3_context *context){
drhc22bd472002-05-10 13:14:07 +0000757 CountCtx *p;
drh4f26d6c2004-05-26 23:25:30 +0000758 p = sqlite3_aggregate_context(context, sizeof(*p));
drh90669c12006-01-20 15:45:36 +0000759 if( p ){
760 if( p->n==42 ){
761 sqlite3_result_error(context, "x_count totals to 42", -1);
762 }else{
763 sqlite3_result_int(context, p ? p->n : 0);
764 }
765 }
drhc22bd472002-05-10 13:14:07 +0000766}
767
768/*
769** Usage: sqlite_test_create_aggregate DB
770**
danielk19776f8a5032004-05-10 10:34:51 +0000771** Call the sqlite3_create_function API on the given database in order
drhc22bd472002-05-10 13:14:07 +0000772** to create a function named "x_count". This function does the same thing
773** as the "md5sum" function.
774**
775** The original motivation for this routine was to be able to call the
danielk19776f8a5032004-05-10 10:34:51 +0000776** sqlite3_create_aggregate function while a query is in progress in order
drh90669c12006-01-20 15:45:36 +0000777** to test the SQLITE_MISUSE detection logic. See misuse.test.
778**
779** This routine was later extended to test the use of sqlite3_result_error()
780** within aggregate functions.
drhc22bd472002-05-10 13:14:07 +0000781*/
drhc2eef3b2002-08-31 18:53:06 +0000782static int test_create_aggregate(
drhc22bd472002-05-10 13:14:07 +0000783 void *NotUsed,
784 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
785 int argc, /* Number of arguments */
786 char **argv /* Text of each argument */
787){
drh9bb575f2004-09-06 17:24:11 +0000788 sqlite3 *db;
drhc60d0442004-09-30 13:43:13 +0000789 int rc;
drhc22bd472002-05-10 13:14:07 +0000790 if( argc!=2 ){
791 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
792 " FILENAME\"", 0);
793 return TCL_ERROR;
794 }
drhb86ccfb2003-01-28 23:13:10 +0000795 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +0000796 rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0,
danielk1977d8123362004-06-12 09:25:12 +0000797 countStep,countFinalize);
drhc60d0442004-09-30 13:43:13 +0000798 if( rc==SQLITE_OK ){
799 sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0,
800 countStep,countFinalize);
801 }
802 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drhc22bd472002-05-10 13:14:07 +0000803 return TCL_OK;
804}
805
806
drh3c23a882007-01-09 14:01:13 +0000807/*
808** Usage: printf TEXT
809**
810** Send output to printf. Use this rather than puts to merge the output
811** in the correct sequence with debugging printfs inserted into C code.
812** Puts uses a separate buffer and debugging statements will be out of
813** sequence if it is used.
814*/
815static int test_printf(
816 void *NotUsed,
817 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
818 int argc, /* Number of arguments */
819 char **argv /* Text of each argument */
820){
821 if( argc!=2 ){
822 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
823 " TEXT\"", 0);
824 return TCL_ERROR;
825 }
826 printf("%s\n", argv[1]);
827 return TCL_OK;
828}
829
830
drhc22bd472002-05-10 13:14:07 +0000831
832/*
danielk19776f8a5032004-05-10 10:34:51 +0000833** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER
drhd1bf3512001-04-07 15:24:33 +0000834**
835** Call mprintf with three integer arguments
836*/
danielk19776f8a5032004-05-10 10:34:51 +0000837static int sqlite3_mprintf_int(
drhd1bf3512001-04-07 15:24:33 +0000838 void *NotUsed,
839 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
840 int argc, /* Number of arguments */
841 char **argv /* Text of each argument */
842){
843 int a[3], i;
844 char *z;
845 if( argc!=5 ){
846 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
847 " FORMAT INT INT INT\"", 0);
848 return TCL_ERROR;
849 }
850 for(i=2; i<5; i++){
851 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
852 }
danielk19776f8a5032004-05-10 10:34:51 +0000853 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
drhd1bf3512001-04-07 15:24:33 +0000854 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000855 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +0000856 return TCL_OK;
857}
858
859/*
drh9d213ef2004-06-30 04:02:11 +0000860** If zNum represents an integer that will fit in 64-bits, then set
861** *pValue to that integer and return true. Otherwise return false.
862*/
863static int sqlite3GetInt64(const char *zNum, i64 *pValue){
864 if( sqlite3FitsIn64Bits(zNum) ){
865 sqlite3atoi64(zNum, pValue);
866 return 1;
867 }
868 return 0;
869}
870
871/*
drhe9707672004-06-25 01:10:48 +0000872** Usage: sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER
873**
874** Call mprintf with three 64-bit integer arguments
875*/
876static int sqlite3_mprintf_int64(
877 void *NotUsed,
878 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
879 int argc, /* Number of arguments */
880 char **argv /* Text of each argument */
881){
882 int i;
883 sqlite_int64 a[3];
884 char *z;
885 if( argc!=5 ){
886 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
887 " FORMAT INT INT INT\"", 0);
888 return TCL_ERROR;
889 }
890 for(i=2; i<5; i++){
891 if( !sqlite3GetInt64(argv[i], &a[i-2]) ){
892 Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0);
893 return TCL_ERROR;
894 }
895 }
896 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
897 Tcl_AppendResult(interp, z, 0);
898 sqlite3_free(z);
899 return TCL_OK;
900}
901
902/*
danielk19776f8a5032004-05-10 10:34:51 +0000903** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING
drhd1bf3512001-04-07 15:24:33 +0000904**
905** Call mprintf with two integer arguments and one string argument
906*/
danielk19776f8a5032004-05-10 10:34:51 +0000907static int sqlite3_mprintf_str(
drhd1bf3512001-04-07 15:24:33 +0000908 void *NotUsed,
909 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
910 int argc, /* Number of arguments */
911 char **argv /* Text of each argument */
912){
913 int a[3], i;
914 char *z;
chwf220b242002-06-16 04:54:28 +0000915 if( argc<4 || argc>5 ){
drhd1bf3512001-04-07 15:24:33 +0000916 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
chwf220b242002-06-16 04:54:28 +0000917 " FORMAT INT INT ?STRING?\"", 0);
drhd1bf3512001-04-07 15:24:33 +0000918 return TCL_ERROR;
919 }
920 for(i=2; i<4; i++){
921 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
922 }
danielk19776f8a5032004-05-10 10:34:51 +0000923 z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL);
drhd1bf3512001-04-07 15:24:33 +0000924 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000925 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +0000926 return TCL_OK;
927}
928
929/*
drh63782852005-08-30 19:30:59 +0000930** Usage: sqlite3_mprintf_double FORMAT INTEGER INTEGER DOUBLE
drhd1bf3512001-04-07 15:24:33 +0000931**
932** Call mprintf with two integer arguments and one double argument
933*/
danielk19776f8a5032004-05-10 10:34:51 +0000934static int sqlite3_mprintf_double(
drhd1bf3512001-04-07 15:24:33 +0000935 void *NotUsed,
936 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
937 int argc, /* Number of arguments */
938 char **argv /* Text of each argument */
939){
940 int a[3], i;
941 double r;
942 char *z;
943 if( argc!=5 ){
944 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
drh63782852005-08-30 19:30:59 +0000945 " FORMAT INT INT DOUBLE\"", 0);
drhd1bf3512001-04-07 15:24:33 +0000946 return TCL_ERROR;
947 }
948 for(i=2; i<4; i++){
949 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
950 }
951 if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
danielk19776f8a5032004-05-10 10:34:51 +0000952 z = sqlite3_mprintf(argv[1], a[0], a[1], r);
drhd1bf3512001-04-07 15:24:33 +0000953 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000954 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +0000955 return TCL_OK;
956}
957
958/*
drh63782852005-08-30 19:30:59 +0000959** Usage: sqlite3_mprintf_scaled FORMAT DOUBLE DOUBLE
drhb621c232004-02-21 19:41:04 +0000960**
961** Call mprintf with a single double argument which is the product of the
962** two arguments given above. This is used to generate overflow and underflow
963** doubles to test that they are converted properly.
964*/
danielk19776f8a5032004-05-10 10:34:51 +0000965static int sqlite3_mprintf_scaled(
drhb621c232004-02-21 19:41:04 +0000966 void *NotUsed,
967 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
968 int argc, /* Number of arguments */
969 char **argv /* Text of each argument */
970){
971 int i;
972 double r[2];
973 char *z;
974 if( argc!=4 ){
975 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
976 " FORMAT DOUBLE DOUBLE\"", 0);
977 return TCL_ERROR;
978 }
979 for(i=2; i<4; i++){
980 if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR;
981 }
danielk19776f8a5032004-05-10 10:34:51 +0000982 z = sqlite3_mprintf(argv[1], r[0]*r[1]);
drhb621c232004-02-21 19:41:04 +0000983 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000984 sqlite3_free(z);
drhb621c232004-02-21 19:41:04 +0000985 return TCL_OK;
986}
987
988/*
drhe29b1a02004-07-17 21:56:09 +0000989** Usage: sqlite3_mprintf_stronly FORMAT STRING
990**
991** Call mprintf with a single double argument which is the product of the
992** two arguments given above. This is used to generate overflow and underflow
993** doubles to test that they are converted properly.
994*/
995static int sqlite3_mprintf_stronly(
996 void *NotUsed,
997 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
998 int argc, /* Number of arguments */
999 char **argv /* Text of each argument */
1000){
1001 char *z;
1002 if( argc!=3 ){
1003 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1004 " FORMAT STRING\"", 0);
1005 return TCL_ERROR;
1006 }
1007 z = sqlite3_mprintf(argv[1], argv[2]);
1008 Tcl_AppendResult(interp, z, 0);
1009 sqlite3_free(z);
1010 return TCL_OK;
1011}
1012
1013/*
drh63782852005-08-30 19:30:59 +00001014** Usage: sqlite3_mprintf_hexdouble FORMAT HEX
1015**
1016** Call mprintf with a single double argument which is derived from the
1017** hexadecimal encoding of an IEEE double.
1018*/
1019static int sqlite3_mprintf_hexdouble(
1020 void *NotUsed,
1021 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1022 int argc, /* Number of arguments */
1023 char **argv /* Text of each argument */
1024){
1025 char *z;
1026 double r;
1027 unsigned x1, x2;
1028 long long unsigned d;
1029 if( argc!=3 ){
1030 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1031 " FORMAT STRING\"", 0);
1032 return TCL_ERROR;
1033 }
1034 if( sscanf(argv[2], "%08x%08x", &x2, &x1)!=2 ){
1035 Tcl_AppendResult(interp, "2nd argument should be 16-characters of hex", 0);
1036 return TCL_ERROR;
1037 }
1038 d = x2;
1039 d = (d<<32) + x1;
1040 memcpy(&r, &d, sizeof(r));
1041 z = sqlite3_mprintf(argv[1], r);
1042 Tcl_AppendResult(interp, z, 0);
1043 sqlite3_free(z);
1044 return TCL_OK;
1045}
1046
1047/*
drh46934232004-11-20 19:18:00 +00001048** Usage: sqlite_malloc_fail N ?REPEAT-INTERVAL?
drhdaffd0e2001-04-11 14:28:42 +00001049**
drh46934232004-11-20 19:18:00 +00001050** Rig sqliteMalloc() to fail on the N-th call and every REPEAT-INTERVAL call
1051** after that. If REPEAT-INTERVAL is 0 or is omitted, then only a single
1052** malloc will fail. If REPEAT-INTERVAL is 1 then all mallocs after the
1053** first failure will continue to fail on every call. If REPEAT-INTERVAL is
1054** 2 then every other malloc will fail. And so forth.
1055**
danielk19779e128002006-01-18 16:51:35 +00001056** Turn off this mechanism and reset the sqlite3ThreadData()->mallocFailed
1057** variable if N==0.
drhdaffd0e2001-04-11 14:28:42 +00001058*/
danielk19772c336542005-01-13 02:14:23 +00001059#ifdef SQLITE_MEMDEBUG
drhdaffd0e2001-04-11 14:28:42 +00001060static int sqlite_malloc_fail(
1061 void *NotUsed,
1062 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1063 int argc, /* Number of arguments */
1064 char **argv /* Text of each argument */
1065){
1066 int n;
drh46934232004-11-20 19:18:00 +00001067 int rep;
1068 if( argc!=2 && argc!=3 ){
drhdaffd0e2001-04-11 14:28:42 +00001069 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0);
1070 return TCL_ERROR;
1071 }
1072 if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
drh46934232004-11-20 19:18:00 +00001073 if( argc==3 ){
1074 if( Tcl_GetInt(interp, argv[2], &rep) ) return TCL_ERROR;
1075 }else{
1076 rep = 0;
1077 }
danielk19776f8a5032004-05-10 10:34:51 +00001078 sqlite3_iMallocFail = n;
drh46934232004-11-20 19:18:00 +00001079 sqlite3_iMallocReset = rep;
drhdaffd0e2001-04-11 14:28:42 +00001080 return TCL_OK;
1081}
1082#endif
1083
1084/*
1085** Usage: sqlite_malloc_stat
1086**
1087** Return the number of prior calls to sqliteMalloc() and sqliteFree().
1088*/
danielk19772c336542005-01-13 02:14:23 +00001089#ifdef SQLITE_MEMDEBUG
drhdaffd0e2001-04-11 14:28:42 +00001090static int sqlite_malloc_stat(
1091 void *NotUsed,
1092 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1093 int argc, /* Number of arguments */
1094 char **argv /* Text of each argument */
1095){
1096 char zBuf[200];
danielk19775591df52005-12-20 09:19:37 +00001097 sprintf(zBuf, "%d %d %d", sqlite3_nMalloc,sqlite3_nFree,sqlite3_iMallocFail);
drhdaffd0e2001-04-11 14:28:42 +00001098 Tcl_AppendResult(interp, zBuf, 0);
1099 return TCL_OK;
1100}
danielk19775591df52005-12-20 09:19:37 +00001101
1102/*
1103** This function implements a Tcl command that may be invoked using any of
1104** the four forms enumerated below.
1105**
1106** sqlite_malloc_outstanding
1107** Return a summary of all unfreed blocks of memory allocated by the
1108** current thread. See comments above function sqlite3OutstandingMallocs()
1109** in util.c for a description of the returned value.
1110**
1111** sqlite_malloc_outstanding -bytes
1112** Return the total amount of unfreed memory (in bytes) allocated by
1113** this thread.
1114**
1115** sqlite_malloc_outstanding -maxbytes
1116** Return the maximum amount of dynamic memory in use at one time
1117** by this thread.
1118**
1119** sqlite_malloc_outstanding -clearmaxbytes
1120** Set the value returned by [sqlite_malloc_outstanding -maxbytes]
1121** to the current value of [sqlite_malloc_outstanding -bytes].
1122*/
danielk19772e588c72005-12-09 14:25:08 +00001123static int sqlite_malloc_outstanding(
danielk19775591df52005-12-20 09:19:37 +00001124 ClientData clientData,
danielk19772e588c72005-12-09 14:25:08 +00001125 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
danielk19775591df52005-12-20 09:19:37 +00001126 int objc, /* Number of arguments */
1127 Tcl_Obj *CONST objv[] /* Command arguments */
danielk19772e588c72005-12-09 14:25:08 +00001128){
1129 extern int sqlite3OutstandingMallocs(Tcl_Interp *interp);
danielk19775591df52005-12-20 09:19:37 +00001130
drhdab97c12006-01-19 11:28:06 +00001131#if defined(SQLITE_DEBUG) && defined(SQLITE_MEMDEBUG) && SQLITE_MEMDEBUG>1
danielk19775591df52005-12-20 09:19:37 +00001132 if( objc==2 ){
1133 const char *zArg = Tcl_GetString(objv[1]);
danielk1977191c3e72006-01-19 07:18:14 +00001134#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
1135 ThreadData const *pTd = sqlite3ThreadDataReadOnly();
danielk19775591df52005-12-20 09:19:37 +00001136 if( 0==strcmp(zArg, "-bytes") ){
danielk197752622822006-01-09 09:59:49 +00001137 Tcl_SetObjResult(interp, Tcl_NewIntObj(pTd->nAlloc));
danielk19775591df52005-12-20 09:19:37 +00001138 }else if( 0==strcmp(zArg, "-clearmaxbytes") ){
danielk19779e128002006-01-18 16:51:35 +00001139 sqlite3_nMaxAlloc = pTd->nAlloc;
danielk1977191c3e72006-01-19 07:18:14 +00001140 }else
1141#endif
1142 if( 0==strcmp(zArg, "-maxbytes") ){
1143 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sqlite3_nMaxAlloc));
danielk19775591df52005-12-20 09:19:37 +00001144 }else{
1145 Tcl_AppendResult(interp, "bad option \"", zArg,
1146 "\": must be -bytes, -maxbytes or -clearmaxbytes", 0
1147 );
1148 return TCL_ERROR;
1149 }
1150
1151 return TCL_OK;
1152 }
danielk197752622822006-01-09 09:59:49 +00001153
1154 if( objc!=1 ){
1155 Tcl_WrongNumArgs(interp, 1, objv, "?-bytes?");
1156 return TCL_ERROR;
1157 }
danielk19775591df52005-12-20 09:19:37 +00001158
danielk19772e588c72005-12-09 14:25:08 +00001159 return sqlite3OutstandingMallocs(interp);
danielk1977191c3e72006-01-19 07:18:14 +00001160#else
1161 return TCL_OK;
1162#endif
danielk19772e588c72005-12-09 14:25:08 +00001163}
drhdaffd0e2001-04-11 14:28:42 +00001164#endif
1165
1166/*
danielk197752622822006-01-09 09:59:49 +00001167** Usage: sqlite3_enable_shared_cache BOOLEAN
danielk1977aef0bf62005-12-30 16:28:01 +00001168**
1169*/
drh6f7adc82006-01-11 21:41:20 +00001170#if !defined(SQLITE_OMIT_SHARED_CACHE)
1171static int test_enable_shared(
danielk197752622822006-01-09 09:59:49 +00001172 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
danielk1977aef0bf62005-12-30 16:28:01 +00001173 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1174 int objc, /* Number of arguments */
1175 Tcl_Obj *CONST objv[] /* Command arguments */
1176){
1177 int rc;
1178 int enable;
danielk197752622822006-01-09 09:59:49 +00001179 int ret = 0;
danielk1977aef0bf62005-12-30 16:28:01 +00001180
1181 if( objc!=2 ){
1182 Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
1183 return TCL_ERROR;
1184 }
1185 if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){
1186 return TCL_ERROR;
1187 }
drh6f7adc82006-01-11 21:41:20 +00001188 ret = sqlite3ThreadDataReadOnly()->useSharedData;
1189 rc = sqlite3_enable_shared_cache(enable);
danielk1977aef0bf62005-12-30 16:28:01 +00001190 if( rc!=SQLITE_OK ){
1191 Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
1192 return TCL_ERROR;
1193 }
danielk197752622822006-01-09 09:59:49 +00001194 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ret));
danielk1977aef0bf62005-12-30 16:28:01 +00001195 return TCL_OK;
1196}
1197#endif
1198
1199/*
drh4ac285a2006-09-15 07:28:50 +00001200** Usage: sqlite3_extended_result_codes DB BOOLEAN
1201**
1202*/
1203static int test_extended_result_codes(
1204 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1205 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1206 int objc, /* Number of arguments */
1207 Tcl_Obj *CONST objv[] /* Command arguments */
1208){
1209 int enable;
1210 sqlite3 *db;
1211
1212 if( objc!=3 ){
1213 Tcl_WrongNumArgs(interp, 1, objv, "DB BOOLEAN");
1214 return TCL_ERROR;
1215 }
1216 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1217 if( Tcl_GetBooleanFromObj(interp, objv[2], &enable) ) return TCL_ERROR;
1218 sqlite3_extended_result_codes(db, enable);
1219 return TCL_OK;
1220}
1221
1222/*
danielk1977161fb792006-01-24 10:58:21 +00001223** Usage: sqlite3_libversion_number
1224**
1225*/
1226static int test_libversion_number(
1227 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1228 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1229 int objc, /* Number of arguments */
1230 Tcl_Obj *CONST objv[] /* Command arguments */
1231){
1232 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_libversion_number()));
1233 return TCL_OK;
1234}
1235
1236/*
danielk1977deb802c2006-02-09 13:43:28 +00001237** Usage: sqlite3_table_column_metadata DB dbname tblname colname
1238**
1239*/
1240#ifdef SQLITE_ENABLE_COLUMN_METADATA
1241static int test_table_column_metadata(
1242 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1243 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1244 int objc, /* Number of arguments */
1245 Tcl_Obj *CONST objv[] /* Command arguments */
1246){
1247 sqlite3 *db;
1248 const char *zDb;
1249 const char *zTbl;
1250 const char *zCol;
1251 int rc;
1252 Tcl_Obj *pRet;
1253
1254 const char *zDatatype;
1255 const char *zCollseq;
1256 int notnull;
1257 int primarykey;
1258 int autoincrement;
1259
1260 if( objc!=5 ){
1261 Tcl_WrongNumArgs(interp, 1, objv, "DB dbname tblname colname");
1262 return TCL_ERROR;
1263 }
1264 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1265 zDb = Tcl_GetString(objv[2]);
1266 zTbl = Tcl_GetString(objv[3]);
1267 zCol = Tcl_GetString(objv[4]);
1268
1269 if( strlen(zDb)==0 ) zDb = 0;
1270
1271 rc = sqlite3_table_column_metadata(db, zDb, zTbl, zCol,
1272 &zDatatype, &zCollseq, &notnull, &primarykey, &autoincrement);
1273
1274 if( rc!=SQLITE_OK ){
1275 Tcl_AppendResult(interp, sqlite3_errmsg(db), 0);
1276 return TCL_ERROR;
1277 }
1278
1279 pRet = Tcl_NewObj();
1280 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zDatatype, -1));
1281 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zCollseq, -1));
1282 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(notnull));
1283 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(primarykey));
1284 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(autoincrement));
1285 Tcl_SetObjResult(interp, pRet);
1286
1287 return TCL_OK;
1288}
1289#endif
1290
drhc2e87a32006-06-27 15:16:14 +00001291
danielk1977deb802c2006-02-09 13:43:28 +00001292/*
danielk197769e777f2006-06-14 10:38:02 +00001293** Usage: sqlite3_load_extension DB-HANDLE FILE ?PROC?
1294*/
1295static int test_load_extension(
1296 ClientData clientData, /* Not used */
1297 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1298 int objc, /* Number of arguments */
1299 Tcl_Obj *CONST objv[] /* Command arguments */
1300){
1301 Tcl_CmdInfo cmdInfo;
1302 sqlite3 *db;
1303 int rc;
1304 char *zDb;
1305 char *zFile;
1306 char *zProc = 0;
1307 char *zErr = 0;
1308
1309 if( objc!=4 && objc!=3 ){
1310 Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE FILE ?PROC?");
1311 return TCL_ERROR;
1312 }
1313 zDb = Tcl_GetString(objv[1]);
1314 zFile = Tcl_GetString(objv[2]);
1315 if( objc==4 ){
1316 zProc = Tcl_GetString(objv[3]);
1317 }
1318
1319 /* Extract the C database handle from the Tcl command name */
1320 if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
1321 Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0);
1322 return TCL_ERROR;
1323 }
1324 db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
1325 assert(db);
1326
1327 /* Call the underlying C function. If an error occurs, set rc to
1328 ** TCL_ERROR and load any error string into the interpreter. If no
1329 ** error occurs, set rc to TCL_OK.
1330 */
drhc2e87a32006-06-27 15:16:14 +00001331#ifdef SQLITE_OMIT_LOAD_EXTENSION
1332 rc = SQLITE_ERROR;
1333 zErr = sqlite3_mprintf("this build omits sqlite3_load_extension()");
1334#else
danielk197769e777f2006-06-14 10:38:02 +00001335 rc = sqlite3_load_extension(db, zFile, zProc, &zErr);
drhc2e87a32006-06-27 15:16:14 +00001336#endif
danielk197769e777f2006-06-14 10:38:02 +00001337 if( rc!=SQLITE_OK ){
1338 Tcl_SetResult(interp, zErr ? zErr : "", TCL_VOLATILE);
1339 rc = TCL_ERROR;
1340 }else{
1341 rc = TCL_OK;
1342 }
1343 sqlite3_free(zErr);
1344
1345 return rc;
1346}
1347
1348/*
drhc2e87a32006-06-27 15:16:14 +00001349** Usage: sqlite3_enable_load_extension DB-HANDLE ONOFF
1350*/
1351static int test_enable_load(
1352 ClientData clientData, /* Not used */
1353 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1354 int objc, /* Number of arguments */
1355 Tcl_Obj *CONST objv[] /* Command arguments */
1356){
1357 Tcl_CmdInfo cmdInfo;
1358 sqlite3 *db;
1359 char *zDb;
1360 int onoff;
1361
1362 if( objc!=3 ){
1363 Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE ONOFF");
1364 return TCL_ERROR;
1365 }
1366 zDb = Tcl_GetString(objv[1]);
1367
1368 /* Extract the C database handle from the Tcl command name */
1369 if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
1370 Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0);
1371 return TCL_ERROR;
1372 }
1373 db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
1374 assert(db);
1375
1376 /* Get the onoff parameter */
1377 if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){
1378 return TCL_ERROR;
1379 }
1380
1381#ifdef SQLITE_OMIT_LOAD_EXTENSION
1382 Tcl_AppendResult(interp, "this build omits sqlite3_load_extension()");
1383 return TCL_ERROR;
1384#else
1385 sqlite3_enable_load_extension(db, onoff);
1386 return TCL_OK;
1387#endif
1388}
1389
1390/*
drh28b4e482002-03-11 02:06:13 +00001391** Usage: sqlite_abort
1392**
1393** Shutdown the process immediately. This is not a clean shutdown.
1394** This command is used to test the recoverability of a database in
1395** the event of a program crash.
1396*/
1397static int sqlite_abort(
1398 void *NotUsed,
1399 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1400 int argc, /* Number of arguments */
1401 char **argv /* Text of each argument */
1402){
1403 assert( interp==0 ); /* This will always fail */
1404 return TCL_OK;
1405}
1406
1407/*
drh6cbe1f12002-07-01 00:31:36 +00001408** The following routine is a user-defined SQL function whose purpose
1409** is to test the sqlite_set_result() API.
1410*/
danielk19770ae8b832004-05-25 12:05:56 +00001411static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
drh6cbe1f12002-07-01 00:31:36 +00001412 while( argc>=2 ){
drh03d847e2005-12-09 20:21:58 +00001413 const char *zArg0 = (char*)sqlite3_value_text(argv[0]);
danielk19776d88bad2004-05-27 14:23:36 +00001414 if( zArg0 ){
1415 if( 0==sqlite3StrICmp(zArg0, "int") ){
1416 sqlite3_result_int(context, sqlite3_value_int(argv[1]));
1417 }else if( sqlite3StrICmp(zArg0,"int64")==0 ){
1418 sqlite3_result_int64(context, sqlite3_value_int64(argv[1]));
1419 }else if( sqlite3StrICmp(zArg0,"string")==0 ){
drh03d847e2005-12-09 20:21:58 +00001420 sqlite3_result_text(context, (char*)sqlite3_value_text(argv[1]), -1,
danielk1977d8123362004-06-12 09:25:12 +00001421 SQLITE_TRANSIENT);
danielk19776d88bad2004-05-27 14:23:36 +00001422 }else if( sqlite3StrICmp(zArg0,"double")==0 ){
1423 sqlite3_result_double(context, sqlite3_value_double(argv[1]));
1424 }else if( sqlite3StrICmp(zArg0,"null")==0 ){
1425 sqlite3_result_null(context);
1426 }else if( sqlite3StrICmp(zArg0,"value")==0 ){
1427 sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]);
1428 }else{
1429 goto error_out;
1430 }
drh6cbe1f12002-07-01 00:31:36 +00001431 }else{
danielk19776d88bad2004-05-27 14:23:36 +00001432 goto error_out;
drh6cbe1f12002-07-01 00:31:36 +00001433 }
1434 argc -= 2;
1435 argv += 2;
1436 }
danielk19776d88bad2004-05-27 14:23:36 +00001437 return;
1438
1439error_out:
1440 sqlite3_result_error(context,"first argument should be one of: "
1441 "int int64 string double null value", -1);
drh6cbe1f12002-07-01 00:31:36 +00001442}
1443
1444/*
1445** Usage: sqlite_register_test_function DB NAME
1446**
1447** Register the test SQL function on the database DB under the name NAME.
1448*/
drhc2eef3b2002-08-31 18:53:06 +00001449static int test_register_func(
drh6cbe1f12002-07-01 00:31:36 +00001450 void *NotUsed,
1451 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1452 int argc, /* Number of arguments */
1453 char **argv /* Text of each argument */
1454){
drh9bb575f2004-09-06 17:24:11 +00001455 sqlite3 *db;
drh6cbe1f12002-07-01 00:31:36 +00001456 int rc;
1457 if( argc!=3 ){
1458 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1459 " DB FUNCTION-NAME", 0);
1460 return TCL_ERROR;
1461 }
drhb86ccfb2003-01-28 23:13:10 +00001462 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk1977f9d64d22004-06-19 08:18:07 +00001463 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0,
danielk1977d8123362004-06-12 09:25:12 +00001464 testFunc, 0, 0);
drh6cbe1f12002-07-01 00:31:36 +00001465 if( rc!=0 ){
danielk1977f20b21c2004-05-31 23:56:42 +00001466 Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);
drh6cbe1f12002-07-01 00:31:36 +00001467 return TCL_ERROR;
1468 }
drhc60d0442004-09-30 13:43:13 +00001469 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drh6cbe1f12002-07-01 00:31:36 +00001470 return TCL_OK;
1471}
1472
1473/*
danielk1977106bb232004-05-21 10:08:53 +00001474** Usage: sqlite3_finalize STMT
drhb86ccfb2003-01-28 23:13:10 +00001475**
danielk1977106bb232004-05-21 10:08:53 +00001476** Finalize a statement handle.
drhb86ccfb2003-01-28 23:13:10 +00001477*/
1478static int test_finalize(
danielk1977106bb232004-05-21 10:08:53 +00001479 void * clientData,
1480 Tcl_Interp *interp,
1481 int objc,
1482 Tcl_Obj *CONST objv[]
drhb86ccfb2003-01-28 23:13:10 +00001483){
danielk1977106bb232004-05-21 10:08:53 +00001484 sqlite3_stmt *pStmt;
drhb86ccfb2003-01-28 23:13:10 +00001485 int rc;
drhdddb2f22007-01-03 23:37:28 +00001486 sqlite3 *db = 0;
danielk1977106bb232004-05-21 10:08:53 +00001487
1488 if( objc!=2 ){
1489 Tcl_AppendResult(interp, "wrong # args: should be \"",
1490 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
drhb86ccfb2003-01-28 23:13:10 +00001491 return TCL_ERROR;
1492 }
danielk1977106bb232004-05-21 10:08:53 +00001493
1494 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1495
danielk19774397de52005-01-12 12:44:03 +00001496 if( pStmt ){
1497 db = StmtToDb(pStmt);
1498 }
danielk1977fc57d7b2004-05-26 02:04:57 +00001499 rc = sqlite3_finalize(pStmt);
danielk1977b77f5da2004-05-26 13:27:00 +00001500 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
danielk19774397de52005-01-12 12:44:03 +00001501 if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk1977106bb232004-05-21 10:08:53 +00001502 return TCL_OK;
1503}
1504
1505/*
1506** Usage: sqlite3_reset STMT
1507**
danielk1977261919c2005-12-06 12:52:59 +00001508** Reset a statement handle.
danielk1977106bb232004-05-21 10:08:53 +00001509*/
1510static int test_reset(
1511 void * clientData,
1512 Tcl_Interp *interp,
1513 int objc,
1514 Tcl_Obj *CONST objv[]
1515){
1516 sqlite3_stmt *pStmt;
1517 int rc;
1518
1519 if( objc!=2 ){
1520 Tcl_AppendResult(interp, "wrong # args: should be \"",
1521 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
1522 return TCL_ERROR;
1523 }
1524
1525 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1526
danielk1977fc57d7b2004-05-26 02:04:57 +00001527 rc = sqlite3_reset(pStmt);
danielk1977261919c2005-12-06 12:52:59 +00001528 if( pStmt && sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ){
1529 return TCL_ERROR;
1530 }
danielk19774397de52005-01-12 12:44:03 +00001531 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
danielk1977261919c2005-12-06 12:52:59 +00001532/*
danielk1977106bb232004-05-21 10:08:53 +00001533 if( rc ){
drhb86ccfb2003-01-28 23:13:10 +00001534 return TCL_ERROR;
1535 }
danielk1977261919c2005-12-06 12:52:59 +00001536*/
drhb86ccfb2003-01-28 23:13:10 +00001537 return TCL_OK;
1538}
1539
drh5a387052003-01-11 14:19:51 +00001540/*
drhd89bd002005-01-22 03:03:54 +00001541** Usage: sqlite3_expired STMT
1542**
1543** Return TRUE if a recompilation of the statement is recommended.
1544*/
1545static int test_expired(
1546 void * clientData,
1547 Tcl_Interp *interp,
1548 int objc,
1549 Tcl_Obj *CONST objv[]
1550){
1551 sqlite3_stmt *pStmt;
1552 if( objc!=2 ){
1553 Tcl_AppendResult(interp, "wrong # args: should be \"",
1554 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
1555 return TCL_ERROR;
1556 }
1557 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1558 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite3_expired(pStmt)));
1559 return TCL_OK;
1560}
1561
1562/*
drhf8db1bc2005-04-22 02:38:37 +00001563** Usage: sqlite3_transfer_bindings FROMSTMT TOSTMT
1564**
1565** Transfer all bindings from FROMSTMT over to TOSTMT
1566*/
1567static int test_transfer_bind(
1568 void * clientData,
1569 Tcl_Interp *interp,
1570 int objc,
1571 Tcl_Obj *CONST objv[]
1572){
1573 sqlite3_stmt *pStmt1, *pStmt2;
1574 if( objc!=3 ){
1575 Tcl_AppendResult(interp, "wrong # args: should be \"",
1576 Tcl_GetStringFromObj(objv[0], 0), " FROM-STMT TO-STMT", 0);
1577 return TCL_ERROR;
1578 }
1579 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt1)) return TCL_ERROR;
1580 if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt2)) return TCL_ERROR;
1581 Tcl_SetObjResult(interp,
1582 Tcl_NewIntObj(sqlite3_transfer_bindings(pStmt1,pStmt2)));
1583 return TCL_OK;
1584}
1585
1586/*
danielk1977fbcd5852004-06-15 02:44:18 +00001587** Usage: sqlite3_changes DB
drh50457892003-09-06 01:10:47 +00001588**
danielk1977fbcd5852004-06-15 02:44:18 +00001589** Return the number of changes made to the database by the last SQL
1590** execution.
drh50457892003-09-06 01:10:47 +00001591*/
danielk1977fbcd5852004-06-15 02:44:18 +00001592static int test_changes(
1593 void * clientData,
1594 Tcl_Interp *interp,
1595 int objc,
1596 Tcl_Obj *CONST objv[]
1597){
1598 sqlite3 *db;
1599 if( objc!=2 ){
1600 Tcl_AppendResult(interp, "wrong # args: should be \"",
1601 Tcl_GetString(objv[0]), " DB", 0);
1602 return TCL_ERROR;
1603 }
1604 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1605 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db)));
1606 return TCL_OK;
1607}
drh50457892003-09-06 01:10:47 +00001608
1609/*
drh7c972de2003-09-06 22:18:07 +00001610** This is the "static_bind_value" that variables are bound to when
danielk19776f8a5032004-05-10 10:34:51 +00001611** the FLAG option of sqlite3_bind is "static"
drh50457892003-09-06 01:10:47 +00001612*/
drh7c972de2003-09-06 22:18:07 +00001613static char *sqlite_static_bind_value = 0;
drhf0313812006-09-04 15:53:53 +00001614static int sqlite_static_bind_nbyte = 0;
drh7c972de2003-09-06 22:18:07 +00001615
1616/*
danielk19776f8a5032004-05-10 10:34:51 +00001617** Usage: sqlite3_bind VM IDX VALUE FLAGS
drh7c972de2003-09-06 22:18:07 +00001618**
1619** Sets the value of the IDX-th occurance of "?" in the original SQL
1620** string. VALUE is the new value. If FLAGS=="null" then VALUE is
1621** ignored and the value is set to NULL. If FLAGS=="static" then
1622** the value is set to the value of a static variable named
1623** "sqlite_static_bind_value". If FLAGS=="normal" then a copy
drhbf8aa2a2005-12-02 02:44:05 +00001624** of the VALUE is made. If FLAGS=="blob10" then a VALUE is ignored
1625** an a 10-byte blob "abc\000xyz\000pq" is inserted.
drh7c972de2003-09-06 22:18:07 +00001626*/
1627static int test_bind(
drh50457892003-09-06 01:10:47 +00001628 void *NotUsed,
1629 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1630 int argc, /* Number of arguments */
1631 char **argv /* Text of each argument */
1632){
danielk1977fc57d7b2004-05-26 02:04:57 +00001633 sqlite3_stmt *pStmt;
drh50457892003-09-06 01:10:47 +00001634 int rc;
drh7c972de2003-09-06 22:18:07 +00001635 int idx;
1636 if( argc!=5 ){
drh50457892003-09-06 01:10:47 +00001637 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
drh7c972de2003-09-06 22:18:07 +00001638 " VM IDX VALUE (null|static|normal)\"", 0);
drh50457892003-09-06 01:10:47 +00001639 return TCL_ERROR;
1640 }
danielk1977fc57d7b2004-05-26 02:04:57 +00001641 if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR;
drh7c972de2003-09-06 22:18:07 +00001642 if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR;
1643 if( strcmp(argv[4],"null")==0 ){
danielk1977fc57d7b2004-05-26 02:04:57 +00001644 rc = sqlite3_bind_null(pStmt, idx);
drh7c972de2003-09-06 22:18:07 +00001645 }else if( strcmp(argv[4],"static")==0 ){
danielk1977fc57d7b2004-05-26 02:04:57 +00001646 rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0);
drhf0313812006-09-04 15:53:53 +00001647 }else if( strcmp(argv[4],"static-nbytes")==0 ){
1648 rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value,
1649 sqlite_static_bind_nbyte, 0);
drh7c972de2003-09-06 22:18:07 +00001650 }else if( strcmp(argv[4],"normal")==0 ){
danielk1977d8123362004-06-12 09:25:12 +00001651 rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT);
drhbf8aa2a2005-12-02 02:44:05 +00001652 }else if( strcmp(argv[4],"blob10")==0 ){
1653 rc = sqlite3_bind_text(pStmt, idx, "abc\000xyz\000pq", 10, SQLITE_STATIC);
drh7c972de2003-09-06 22:18:07 +00001654 }else{
1655 Tcl_AppendResult(interp, "4th argument should be "
1656 "\"null\" or \"static\" or \"normal\"", 0);
1657 return TCL_ERROR;
1658 }
drhc60d0442004-09-30 13:43:13 +00001659 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
drh50457892003-09-06 01:10:47 +00001660 if( rc ){
1661 char zBuf[50];
1662 sprintf(zBuf, "(%d) ", rc);
danielk1977f20b21c2004-05-31 23:56:42 +00001663 Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0);
drh50457892003-09-06 01:10:47 +00001664 return TCL_ERROR;
1665 }
1666 return TCL_OK;
1667}
1668
drh5436dc22004-11-14 04:04:17 +00001669#ifndef SQLITE_OMIT_UTF16
danielk19774e6af132004-06-10 14:01:08 +00001670/*
1671** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be>
1672**
1673** This function is used to test that SQLite selects the correct collation
1674** sequence callback when multiple versions (for different text encodings)
1675** are available.
1676**
1677** Calling this routine registers the collation sequence "test_collate"
1678** with database handle <db>. The second argument must be a list of three
1679** boolean values. If the first is true, then a version of test_collate is
1680** registered for UTF-8, if the second is true, a version is registered for
1681** UTF-16le, if the third is true, a UTF-16be version is available.
1682** Previous versions of test_collate are deleted.
1683**
1684** The collation sequence test_collate is implemented by calling the
1685** following TCL script:
1686**
1687** "test_collate <enc> <lhs> <rhs>"
1688**
1689** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8.
1690** The <enc> parameter is the encoding of the collation function that
1691** SQLite selected to call. The TCL test script implements the
1692** "test_collate" proc.
1693**
1694** Note that this will only work with one intepreter at a time, as the
1695** interp pointer to use when evaluating the TCL script is stored in
1696** pTestCollateInterp.
1697*/
1698static Tcl_Interp* pTestCollateInterp;
1699static int test_collate_func(
1700 void *pCtx,
1701 int nA, const void *zA,
1702 int nB, const void *zB
1703){
1704 Tcl_Interp *i = pTestCollateInterp;
1705 int encin = (int)pCtx;
1706 int res;
drh4db38a72005-09-01 12:16:28 +00001707 int n;
danielk19774e6af132004-06-10 14:01:08 +00001708
1709 sqlite3_value *pVal;
1710 Tcl_Obj *pX;
1711
1712 pX = Tcl_NewStringObj("test_collate", -1);
1713 Tcl_IncrRefCount(pX);
1714
1715 switch( encin ){
1716 case SQLITE_UTF8:
1717 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1));
1718 break;
1719 case SQLITE_UTF16LE:
1720 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1));
1721 break;
1722 case SQLITE_UTF16BE:
1723 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1));
1724 break;
1725 default:
1726 assert(0);
1727 }
1728
1729 pVal = sqlite3ValueNew();
danielk1977bfd6cce2004-06-18 04:24:54 +00001730 sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC);
drh4db38a72005-09-01 12:16:28 +00001731 n = sqlite3_value_bytes(pVal);
drh03d847e2005-12-09 20:21:58 +00001732 Tcl_ListObjAppendElement(i,pX,
1733 Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
danielk1977bfd6cce2004-06-18 04:24:54 +00001734 sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC);
drh4db38a72005-09-01 12:16:28 +00001735 n = sqlite3_value_bytes(pVal);
drh03d847e2005-12-09 20:21:58 +00001736 Tcl_ListObjAppendElement(i,pX,
1737 Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
danielk19774e6af132004-06-10 14:01:08 +00001738 sqlite3ValueFree(pVal);
1739
1740 Tcl_EvalObjEx(i, pX, 0);
1741 Tcl_DecrRefCount(pX);
1742 Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res);
1743 return res;
1744}
1745static int test_collate(
1746 void * clientData,
1747 Tcl_Interp *interp,
1748 int objc,
1749 Tcl_Obj *CONST objv[]
1750){
1751 sqlite3 *db;
1752 int val;
danielk1977312d6b32004-06-29 13:18:23 +00001753 sqlite3_value *pVal;
drhc60d0442004-09-30 13:43:13 +00001754 int rc;
danielk19774e6af132004-06-10 14:01:08 +00001755
1756 if( objc!=5 ) goto bad_args;
1757 pTestCollateInterp = interp;
1758 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1759
1760 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +00001761 rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8,
1762 (void *)SQLITE_UTF8, val?test_collate_func:0);
1763 if( rc==SQLITE_OK ){
1764 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
1765 rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE,
1766 (void *)SQLITE_UTF16LE, val?test_collate_func:0);
1767 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
danielk1977312d6b32004-06-29 13:18:23 +00001768
danielk19779a30cf62006-01-18 04:26:07 +00001769#ifdef SQLITE_MEMDEBUG
1770 if( sqlite3_iMallocFail>0 ){
1771 sqlite3_iMallocFail++;
1772 }
1773#endif
drhc60d0442004-09-30 13:43:13 +00001774 pVal = sqlite3ValueNew();
1775 sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC);
danielk19779a30cf62006-01-18 04:26:07 +00001776 rc = sqlite3_create_collation16(db,
1777 sqlite3ValueText(pVal, SQLITE_UTF16NATIVE), SQLITE_UTF16BE,
1778 (void *)SQLITE_UTF16BE, val?test_collate_func:0);
drhc60d0442004-09-30 13:43:13 +00001779 sqlite3ValueFree(pVal);
1780 }
1781 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk19779a30cf62006-01-18 04:26:07 +00001782
1783 if( rc!=SQLITE_OK ){
1784 Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
1785 return TCL_ERROR;
1786 }
danielk19774e6af132004-06-10 14:01:08 +00001787 return TCL_OK;
1788
1789bad_args:
1790 Tcl_AppendResult(interp, "wrong # args: should be \"",
1791 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
1792 return TCL_ERROR;
1793}
1794
drh268803a2005-12-14 20:11:30 +00001795/*
1796** When the collation needed callback is invoked, record the name of
1797** the requested collating function here. The recorded name is linked
1798** to a TCL variable and used to make sure that the requested collation
1799** name is correct.
1800*/
1801static char zNeededCollation[200];
1802static char *pzNeededCollation = zNeededCollation;
1803
1804
1805/*
1806** Called when a collating sequence is needed. Registered using
1807** sqlite3_collation_needed16().
1808*/
danielk1977312d6b32004-06-29 13:18:23 +00001809static void test_collate_needed_cb(
1810 void *pCtx,
1811 sqlite3 *db,
1812 int eTextRep,
drh268803a2005-12-14 20:11:30 +00001813 const void *pName
danielk1977312d6b32004-06-29 13:18:23 +00001814){
danielk197714db2662006-01-09 16:12:04 +00001815 int enc = ENC(db);
drh268803a2005-12-14 20:11:30 +00001816 int i;
1817 char *z;
1818 for(z = (char*)pName, i=0; *z || z[1]; z++){
1819 if( *z ) zNeededCollation[i++] = *z;
1820 }
1821 zNeededCollation[i] = 0;
danielk1977312d6b32004-06-29 13:18:23 +00001822 sqlite3_create_collation(
danielk197714db2662006-01-09 16:12:04 +00001823 db, "test_collate", ENC(db), (void *)enc, test_collate_func);
danielk1977312d6b32004-06-29 13:18:23 +00001824}
1825
1826/*
1827** Usage: add_test_collate_needed DB
1828*/
1829static int test_collate_needed(
1830 void * clientData,
1831 Tcl_Interp *interp,
1832 int objc,
1833 Tcl_Obj *CONST objv[]
1834){
1835 sqlite3 *db;
drhc60d0442004-09-30 13:43:13 +00001836 int rc;
danielk1977312d6b32004-06-29 13:18:23 +00001837
1838 if( objc!=2 ) goto bad_args;
1839 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +00001840 rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb);
drh268803a2005-12-14 20:11:30 +00001841 zNeededCollation[0] = 0;
drhc60d0442004-09-30 13:43:13 +00001842 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk1977312d6b32004-06-29 13:18:23 +00001843 return TCL_OK;
1844
1845bad_args:
1846 Tcl_WrongNumArgs(interp, 1, objv, "DB");
1847 return TCL_ERROR;
1848}
drh7d9bd4e2006-02-16 18:16:36 +00001849
1850/*
1851** tclcmd: add_alignment_test_collations DB
1852**
1853** Add two new collating sequences to the database DB
1854**
1855** utf16_aligned
1856** utf16_unaligned
1857**
1858** Both collating sequences use the same sort order as BINARY.
1859** The only difference is that the utf16_aligned collating
1860** sequence is declared with the SQLITE_UTF16_ALIGNED flag.
1861** Both collating functions increment the unaligned utf16 counter
1862** whenever they see a string that begins on an odd byte boundary.
1863*/
1864static int unaligned_string_counter = 0;
1865static int alignmentCollFunc(
1866 void *NotUsed,
1867 int nKey1, const void *pKey1,
1868 int nKey2, const void *pKey2
1869){
1870 int rc, n;
1871 n = nKey1<nKey2 ? nKey1 : nKey2;
1872 if( nKey1>0 && 1==(1&(int)pKey1) ) unaligned_string_counter++;
1873 if( nKey2>0 && 1==(1&(int)pKey2) ) unaligned_string_counter++;
1874 rc = memcmp(pKey1, pKey2, n);
1875 if( rc==0 ){
1876 rc = nKey1 - nKey2;
1877 }
1878 return rc;
1879}
1880static int add_alignment_test_collations(
1881 void * clientData,
1882 Tcl_Interp *interp,
1883 int objc,
1884 Tcl_Obj *CONST objv[]
1885){
1886 sqlite3 *db;
1887 if( objc>=2 ){
1888 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1889 sqlite3_create_collation(db, "utf16_unaligned",
1890 SQLITE_UTF16,
1891 0, alignmentCollFunc);
1892 sqlite3_create_collation(db, "utf16_aligned",
1893 SQLITE_UTF16 | SQLITE_UTF16_ALIGNED,
1894 0, alignmentCollFunc);
1895 }
1896 return SQLITE_OK;
1897}
1898#endif /* !defined(SQLITE_OMIT_UTF16) */
danielk1977312d6b32004-06-29 13:18:23 +00001899
danielk1977c8e9a2d2004-06-25 12:08:46 +00001900/*
1901** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
1902**
1903** This function is used to test that SQLite selects the correct user
1904** function callback when multiple versions (for different text encodings)
1905** are available.
1906**
1907** Calling this routine registers up to three versions of the user function
1908** "test_function" with database handle <db>. If the second argument is
1909** true, then a version of test_function is registered for UTF-8, if the
1910** third is true, a version is registered for UTF-16le, if the fourth is
1911** true, a UTF-16be version is available. Previous versions of
1912** test_function are deleted.
1913**
1914** The user function is implemented by calling the following TCL script:
1915**
1916** "test_function <enc> <arg>"
1917**
1918** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the
1919** single argument passed to the SQL function. The value returned by
1920** the TCL script is used as the return value of the SQL function. It
1921** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8
1922** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
1923** prefers UTF-16BE.
1924*/
drh5436dc22004-11-14 04:04:17 +00001925#ifndef SQLITE_OMIT_UTF16
danielk1977c8e9a2d2004-06-25 12:08:46 +00001926static void test_function_utf8(
1927 sqlite3_context *pCtx,
1928 int nArg,
1929 sqlite3_value **argv
1930){
1931 Tcl_Interp *interp;
1932 Tcl_Obj *pX;
1933 sqlite3_value *pVal;
1934 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1935 pX = Tcl_NewStringObj("test_function", -1);
1936 Tcl_IncrRefCount(pX);
1937 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1));
1938 Tcl_ListObjAppendElement(interp, pX,
drh03d847e2005-12-09 20:21:58 +00001939 Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
danielk1977c8e9a2d2004-06-25 12:08:46 +00001940 Tcl_EvalObjEx(interp, pX, 0);
1941 Tcl_DecrRefCount(pX);
1942 sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT);
1943 pVal = sqlite3ValueNew();
1944 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1945 SQLITE_UTF8, SQLITE_STATIC);
1946 sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal),
1947 -1, SQLITE_TRANSIENT);
1948 sqlite3ValueFree(pVal);
1949}
1950static void test_function_utf16le(
1951 sqlite3_context *pCtx,
1952 int nArg,
1953 sqlite3_value **argv
1954){
1955 Tcl_Interp *interp;
1956 Tcl_Obj *pX;
1957 sqlite3_value *pVal;
1958 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1959 pX = Tcl_NewStringObj("test_function", -1);
1960 Tcl_IncrRefCount(pX);
1961 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1));
1962 Tcl_ListObjAppendElement(interp, pX,
drh03d847e2005-12-09 20:21:58 +00001963 Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
danielk1977c8e9a2d2004-06-25 12:08:46 +00001964 Tcl_EvalObjEx(interp, pX, 0);
1965 Tcl_DecrRefCount(pX);
1966 pVal = sqlite3ValueNew();
1967 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1968 SQLITE_UTF8, SQLITE_STATIC);
drh03d847e2005-12-09 20:21:58 +00001969 sqlite3_result_text(pCtx,(char*)sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT);
danielk1977c8e9a2d2004-06-25 12:08:46 +00001970 sqlite3ValueFree(pVal);
1971}
1972static void test_function_utf16be(
1973 sqlite3_context *pCtx,
1974 int nArg,
1975 sqlite3_value **argv
1976){
1977 Tcl_Interp *interp;
1978 Tcl_Obj *pX;
1979 sqlite3_value *pVal;
1980 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1981 pX = Tcl_NewStringObj("test_function", -1);
1982 Tcl_IncrRefCount(pX);
1983 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1));
1984 Tcl_ListObjAppendElement(interp, pX,
drh03d847e2005-12-09 20:21:58 +00001985 Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
danielk1977c8e9a2d2004-06-25 12:08:46 +00001986 Tcl_EvalObjEx(interp, pX, 0);
1987 Tcl_DecrRefCount(pX);
1988 pVal = sqlite3ValueNew();
1989 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1990 SQLITE_UTF8, SQLITE_STATIC);
1991 sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal),
1992 -1, SQLITE_TRANSIENT);
1993 sqlite3ValueFree(pVal);
1994}
drh5436dc22004-11-14 04:04:17 +00001995#endif /* SQLITE_OMIT_UTF16 */
danielk1977c8e9a2d2004-06-25 12:08:46 +00001996static int test_function(
1997 void * clientData,
1998 Tcl_Interp *interp,
1999 int objc,
2000 Tcl_Obj *CONST objv[]
2001){
drh5436dc22004-11-14 04:04:17 +00002002#ifndef SQLITE_OMIT_UTF16
danielk1977c8e9a2d2004-06-25 12:08:46 +00002003 sqlite3 *db;
2004 int val;
2005
2006 if( objc!=5 ) goto bad_args;
2007 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2008
2009 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
2010 if( val ){
2011 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8,
2012 interp, test_function_utf8, 0, 0);
2013 }
2014 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
2015 if( val ){
2016 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE,
2017 interp, test_function_utf16le, 0, 0);
2018 }
2019 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
2020 if( val ){
2021 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE,
2022 interp, test_function_utf16be, 0, 0);
2023 }
2024
2025 return TCL_OK;
2026bad_args:
2027 Tcl_AppendResult(interp, "wrong # args: should be \"",
2028 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
drh5436dc22004-11-14 04:04:17 +00002029#endif /* SQLITE_OMIT_UTF16 */
danielk1977c8e9a2d2004-06-25 12:08:46 +00002030 return TCL_ERROR;
2031}
2032
danielk1977312d6b32004-06-29 13:18:23 +00002033/*
2034** Usage: test_errstr <err code>
2035**
2036** Test that the english language string equivalents for sqlite error codes
2037** are sane. The parameter is an integer representing an sqlite error code.
2038** The result is a list of two elements, the string representation of the
2039** error code and the english language explanation.
2040*/
2041static int test_errstr(
2042 void * clientData,
2043 Tcl_Interp *interp,
2044 int objc,
2045 Tcl_Obj *CONST objv[]
2046){
2047 char *zCode;
2048 int i;
2049 if( objc!=1 ){
2050 Tcl_WrongNumArgs(interp, 1, objv, "<error code>");
2051 }
2052
2053 zCode = Tcl_GetString(objv[1]);
2054 for(i=0; i<200; i++){
2055 if( 0==strcmp(errorName(i), zCode) ) break;
2056 }
2057 Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0);
2058 return TCL_OK;
2059}
2060
drh50457892003-09-06 01:10:47 +00002061/*
drh99ee3602003-02-16 19:13:36 +00002062** Usage: breakpoint
2063**
2064** This routine exists for one purpose - to provide a place to put a
2065** breakpoint with GDB that can be triggered using TCL code. The use
2066** for this is when a particular test fails on (say) the 1485th iteration.
2067** In the TCL test script, we can add code like this:
2068**
2069** if {$i==1485} breakpoint
2070**
2071** Then run testfixture in the debugger and wait for the breakpoint to
2072** fire. Then additional breakpoints can be set to trace down the bug.
2073*/
2074static int test_breakpoint(
2075 void *NotUsed,
2076 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
2077 int argc, /* Number of arguments */
2078 char **argv /* Text of each argument */
2079){
2080 return TCL_OK; /* Do nothing */
2081}
2082
drh241db312004-06-22 12:46:53 +00002083/*
2084** Usage: sqlite3_bind_int STMT N VALUE
2085**
2086** Test the sqlite3_bind_int interface. STMT is a prepared statement.
2087** N is the index of a wildcard in the prepared statement. This command
2088** binds a 32-bit integer VALUE to that wildcard.
2089*/
2090static int test_bind_int(
danielk197751e3d8e2004-05-20 01:12:34 +00002091 void * clientData,
2092 Tcl_Interp *interp,
2093 int objc,
2094 Tcl_Obj *CONST objv[]
2095){
2096 sqlite3_stmt *pStmt;
2097 int idx;
2098 int value;
2099 int rc;
2100
2101 if( objc!=4 ){
2102 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00002103 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00002104 return TCL_ERROR;
2105 }
2106
2107 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2108 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
2109 if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
2110
danielk1977c572ef72004-05-27 09:28:41 +00002111 rc = sqlite3_bind_int(pStmt, idx, value);
drhc60d0442004-09-30 13:43:13 +00002112 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00002113 if( rc!=SQLITE_OK ){
2114 return TCL_ERROR;
2115 }
2116
2117 return TCL_OK;
2118}
2119
drh241db312004-06-22 12:46:53 +00002120
2121/*
2122** Usage: sqlite3_bind_int64 STMT N VALUE
2123**
2124** Test the sqlite3_bind_int64 interface. STMT is a prepared statement.
2125** N is the index of a wildcard in the prepared statement. This command
2126** binds a 64-bit integer VALUE to that wildcard.
2127*/
danielk197751e3d8e2004-05-20 01:12:34 +00002128static int test_bind_int64(
2129 void * clientData,
2130 Tcl_Interp *interp,
2131 int objc,
2132 Tcl_Obj *CONST objv[]
2133){
2134 sqlite3_stmt *pStmt;
2135 int idx;
2136 i64 value;
2137 int rc;
2138
2139 if( objc!=4 ){
2140 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00002141 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00002142 return TCL_ERROR;
2143 }
2144
2145 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2146 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
2147 if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
2148
2149 rc = sqlite3_bind_int64(pStmt, idx, value);
drhc60d0442004-09-30 13:43:13 +00002150 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00002151 if( rc!=SQLITE_OK ){
2152 return TCL_ERROR;
2153 }
2154
2155 return TCL_OK;
2156}
2157
drh241db312004-06-22 12:46:53 +00002158
2159/*
2160** Usage: sqlite3_bind_double STMT N VALUE
2161**
2162** Test the sqlite3_bind_double interface. STMT is a prepared statement.
2163** N is the index of a wildcard in the prepared statement. This command
2164** binds a 64-bit integer VALUE to that wildcard.
2165*/
danielk197751e3d8e2004-05-20 01:12:34 +00002166static int test_bind_double(
2167 void * clientData,
2168 Tcl_Interp *interp,
2169 int objc,
2170 Tcl_Obj *CONST objv[]
2171){
2172 sqlite3_stmt *pStmt;
2173 int idx;
2174 double value;
2175 int rc;
2176
2177 if( objc!=4 ){
2178 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00002179 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00002180 return TCL_ERROR;
2181 }
2182
2183 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2184 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
2185 if( Tcl_GetDoubleFromObj(interp, objv[3], &value) ) return TCL_ERROR;
2186
2187 rc = sqlite3_bind_double(pStmt, idx, value);
drhc60d0442004-09-30 13:43:13 +00002188 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00002189 if( rc!=SQLITE_OK ){
2190 return TCL_ERROR;
2191 }
2192
2193 return TCL_OK;
2194}
2195
drh241db312004-06-22 12:46:53 +00002196/*
2197** Usage: sqlite3_bind_null STMT N
2198**
2199** Test the sqlite3_bind_null interface. STMT is a prepared statement.
2200** N is the index of a wildcard in the prepared statement. This command
2201** binds a NULL to the wildcard.
2202*/
danielk197751e3d8e2004-05-20 01:12:34 +00002203static int test_bind_null(
2204 void * clientData,
2205 Tcl_Interp *interp,
2206 int objc,
2207 Tcl_Obj *CONST objv[]
2208){
2209 sqlite3_stmt *pStmt;
2210 int idx;
2211 int rc;
2212
2213 if( objc!=3 ){
2214 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00002215 Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00002216 return TCL_ERROR;
2217 }
2218
2219 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2220 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
2221
2222 rc = sqlite3_bind_null(pStmt, idx);
drhc60d0442004-09-30 13:43:13 +00002223 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00002224 if( rc!=SQLITE_OK ){
2225 return TCL_ERROR;
2226 }
2227
2228 return TCL_OK;
2229}
2230
drh241db312004-06-22 12:46:53 +00002231/*
2232** Usage: sqlite3_bind_text STMT N STRING BYTES
2233**
2234** Test the sqlite3_bind_text interface. STMT is a prepared statement.
2235** N is the index of a wildcard in the prepared statement. This command
2236** binds a UTF-8 string STRING to the wildcard. The string is BYTES bytes
2237** long.
2238*/
danielk197751e3d8e2004-05-20 01:12:34 +00002239static int test_bind_text(
2240 void * clientData,
2241 Tcl_Interp *interp,
2242 int objc,
2243 Tcl_Obj *CONST objv[]
2244){
2245 sqlite3_stmt *pStmt;
2246 int idx;
2247 int bytes;
2248 char *value;
2249 int rc;
2250
2251 if( objc!=5 ){
2252 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00002253 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00002254 return TCL_ERROR;
2255 }
2256
2257 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2258 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
2259 value = Tcl_GetString(objv[3]);
2260 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
2261
danielk1977d8123362004-06-12 09:25:12 +00002262 rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
drhc60d0442004-09-30 13:43:13 +00002263 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00002264 if( rc!=SQLITE_OK ){
drh473d1792005-06-06 17:54:55 +00002265 Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
danielk197751e3d8e2004-05-20 01:12:34 +00002266 return TCL_ERROR;
2267 }
2268
2269 return TCL_OK;
2270}
2271
drh241db312004-06-22 12:46:53 +00002272/*
danielk1977161fb792006-01-24 10:58:21 +00002273** Usage: sqlite3_bind_text16 ?-static? STMT N STRING BYTES
drh241db312004-06-22 12:46:53 +00002274**
2275** Test the sqlite3_bind_text16 interface. STMT is a prepared statement.
2276** N is the index of a wildcard in the prepared statement. This command
2277** binds a UTF-16 string STRING to the wildcard. The string is BYTES bytes
2278** long.
2279*/
danielk197751e3d8e2004-05-20 01:12:34 +00002280static int test_bind_text16(
2281 void * clientData,
2282 Tcl_Interp *interp,
2283 int objc,
2284 Tcl_Obj *CONST objv[]
2285){
drh5436dc22004-11-14 04:04:17 +00002286#ifndef SQLITE_OMIT_UTF16
danielk197751e3d8e2004-05-20 01:12:34 +00002287 sqlite3_stmt *pStmt;
2288 int idx;
2289 int bytes;
2290 char *value;
2291 int rc;
2292
danielk1977161fb792006-01-24 10:58:21 +00002293 void (*xDel)() = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT);
2294 Tcl_Obj *oStmt = objv[objc-4];
2295 Tcl_Obj *oN = objv[objc-3];
2296 Tcl_Obj *oString = objv[objc-2];
2297 Tcl_Obj *oBytes = objv[objc-1];
2298
2299 if( objc!=5 && objc!=6){
danielk197751e3d8e2004-05-20 01:12:34 +00002300 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00002301 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00002302 return TCL_ERROR;
2303 }
2304
danielk1977161fb792006-01-24 10:58:21 +00002305 if( getStmtPointer(interp, Tcl_GetString(oStmt), &pStmt) ) return TCL_ERROR;
2306 if( Tcl_GetIntFromObj(interp, oN, &idx) ) return TCL_ERROR;
2307 value = (char*)Tcl_GetByteArrayFromObj(oString, 0);
2308 if( Tcl_GetIntFromObj(interp, oBytes, &bytes) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00002309
danielk1977161fb792006-01-24 10:58:21 +00002310 rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, xDel);
drhc60d0442004-09-30 13:43:13 +00002311 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00002312 if( rc!=SQLITE_OK ){
2313 return TCL_ERROR;
2314 }
2315
drh5436dc22004-11-14 04:04:17 +00002316#endif /* SQLITE_OMIT_UTF16 */
danielk197751e3d8e2004-05-20 01:12:34 +00002317 return TCL_OK;
2318}
2319
drh241db312004-06-22 12:46:53 +00002320/*
2321** Usage: sqlite3_bind_blob STMT N DATA BYTES
2322**
2323** Test the sqlite3_bind_blob interface. STMT is a prepared statement.
2324** N is the index of a wildcard in the prepared statement. This command
2325** binds a BLOB to the wildcard. The BLOB is BYTES bytes in size.
2326*/
danielk197751e3d8e2004-05-20 01:12:34 +00002327static int test_bind_blob(
2328 void * clientData,
2329 Tcl_Interp *interp,
2330 int objc,
2331 Tcl_Obj *CONST objv[]
2332){
2333 sqlite3_stmt *pStmt;
2334 int idx;
2335 int bytes;
2336 char *value;
2337 int rc;
2338
2339 if( objc!=5 ){
2340 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00002341 Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00002342 return TCL_ERROR;
2343 }
2344
2345 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2346 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
2347 value = Tcl_GetString(objv[3]);
danielk197749e46432004-05-27 13:55:27 +00002348 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00002349
danielk1977d8123362004-06-12 09:25:12 +00002350 rc = sqlite3_bind_blob(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
drhc60d0442004-09-30 13:43:13 +00002351 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00002352 if( rc!=SQLITE_OK ){
2353 return TCL_ERROR;
2354 }
2355
2356 return TCL_OK;
2357}
2358
drh99ee3602003-02-16 19:13:36 +00002359/*
drh75f6a032004-07-15 14:15:00 +00002360** Usage: sqlite3_bind_parameter_count STMT
2361**
2362** Return the number of wildcards in the given statement.
2363*/
2364static int test_bind_parameter_count(
2365 void * clientData,
2366 Tcl_Interp *interp,
2367 int objc,
2368 Tcl_Obj *CONST objv[]
2369){
2370 sqlite3_stmt *pStmt;
2371
2372 if( objc!=2 ){
2373 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
2374 return TCL_ERROR;
2375 }
2376 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2377 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt)));
2378 return TCL_OK;
2379}
2380
2381/*
drh895d7472004-08-20 16:02:39 +00002382** Usage: sqlite3_bind_parameter_name STMT N
2383**
2384** Return the name of the Nth wildcard. The first wildcard is 1.
2385** An empty string is returned if N is out of range or if the wildcard
2386** is nameless.
2387*/
2388static int test_bind_parameter_name(
2389 void * clientData,
2390 Tcl_Interp *interp,
2391 int objc,
2392 Tcl_Obj *CONST objv[]
2393){
2394 sqlite3_stmt *pStmt;
2395 int i;
2396
2397 if( objc!=3 ){
2398 Tcl_WrongNumArgs(interp, 1, objv, "STMT N");
2399 return TCL_ERROR;
2400 }
2401 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2402 if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR;
2403 Tcl_SetObjResult(interp,
2404 Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1)
2405 );
2406 return TCL_OK;
2407}
2408
2409/*
drhfa6bc002004-09-07 16:19:52 +00002410** Usage: sqlite3_bind_parameter_index STMT NAME
2411**
2412** Return the index of the wildcard called NAME. Return 0 if there is
2413** no such wildcard.
2414*/
2415static int test_bind_parameter_index(
2416 void * clientData,
2417 Tcl_Interp *interp,
2418 int objc,
2419 Tcl_Obj *CONST objv[]
2420){
2421 sqlite3_stmt *pStmt;
2422
2423 if( objc!=3 ){
2424 Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME");
2425 return TCL_ERROR;
2426 }
2427 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2428 Tcl_SetObjResult(interp,
2429 Tcl_NewIntObj(
2430 sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2]))
2431 )
2432 );
2433 return TCL_OK;
2434}
2435
2436/*
danielk1977600dd0b2005-01-20 01:14:23 +00002437** Usage: sqlite3_clear_bindings STMT
2438**
2439*/
danielk1977600dd0b2005-01-20 01:14:23 +00002440static int test_clear_bindings(
2441 void * clientData,
2442 Tcl_Interp *interp,
2443 int objc,
2444 Tcl_Obj *CONST objv[]
2445){
2446 sqlite3_stmt *pStmt;
2447
2448 if( objc!=2 ){
2449 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
2450 return TCL_ERROR;
2451 }
2452 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2453 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt)));
2454 return TCL_OK;
2455}
drhf9cb7f52006-06-27 20:06:44 +00002456
2457/*
2458** Usage: sqlite3_sleep MILLISECONDS
2459*/
2460static int test_sleep(
2461 void * clientData,
2462 Tcl_Interp *interp,
2463 int objc,
2464 Tcl_Obj *CONST objv[]
2465){
2466 int ms;
2467
2468 if( objc!=2 ){
2469 Tcl_WrongNumArgs(interp, 1, objv, "MILLISECONDS");
2470 return TCL_ERROR;
2471 }
2472 if( Tcl_GetIntFromObj(interp, objv[1], &ms) ){
2473 return TCL_ERROR;
2474 }
2475 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_sleep(ms)));
2476 return TCL_OK;
2477}
danielk1977600dd0b2005-01-20 01:14:23 +00002478
2479/*
danielk19776622cce2004-05-20 11:00:52 +00002480** Usage: sqlite3_errcode DB
2481**
2482** Return the string representation of the most recent sqlite3_* API
2483** error code. e.g. "SQLITE_ERROR".
2484*/
2485static int test_errcode(
2486 void * clientData,
2487 Tcl_Interp *interp,
2488 int objc,
2489 Tcl_Obj *CONST objv[]
2490){
2491 sqlite3 *db;
drh4ac285a2006-09-15 07:28:50 +00002492 int rc;
2493 char zBuf[30];
danielk19776622cce2004-05-20 11:00:52 +00002494
2495 if( objc!=2 ){
2496 Tcl_AppendResult(interp, "wrong # args: should be \"",
2497 Tcl_GetString(objv[0]), " DB", 0);
2498 return TCL_ERROR;
2499 }
2500 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
drh4ac285a2006-09-15 07:28:50 +00002501 rc = sqlite3_errcode(db);
2502 if( (rc&0xff)==rc ){
2503 zBuf[0] = 0;
2504 }else{
2505 sprintf(zBuf,"+%d", rc>>8);
2506 }
2507 Tcl_AppendResult(interp, (char *)errorName(rc), zBuf, 0);
danielk19776622cce2004-05-20 11:00:52 +00002508 return TCL_OK;
2509}
2510
2511/*
2512** Usage: test_errmsg DB
2513**
2514** Returns the UTF-8 representation of the error message string for the
2515** most recent sqlite3_* API call.
2516*/
2517static int test_errmsg(
2518 void * clientData,
2519 Tcl_Interp *interp,
2520 int objc,
2521 Tcl_Obj *CONST objv[]
2522){
drh9bb575f2004-09-06 17:24:11 +00002523 sqlite3 *db;
danielk19776622cce2004-05-20 11:00:52 +00002524 const char *zErr;
2525
2526 if( objc!=2 ){
2527 Tcl_AppendResult(interp, "wrong # args: should be \"",
2528 Tcl_GetString(objv[0]), " DB", 0);
2529 return TCL_ERROR;
2530 }
2531 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2532
2533 zErr = sqlite3_errmsg(db);
2534 Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
2535 return TCL_OK;
2536}
2537
2538/*
2539** Usage: test_errmsg16 DB
2540**
2541** Returns the UTF-16 representation of the error message string for the
2542** most recent sqlite3_* API call. This is a byte array object at the TCL
2543** level, and it includes the 0x00 0x00 terminator bytes at the end of the
2544** UTF-16 string.
2545*/
2546static int test_errmsg16(
2547 void * clientData,
2548 Tcl_Interp *interp,
2549 int objc,
2550 Tcl_Obj *CONST objv[]
2551){
drh5436dc22004-11-14 04:04:17 +00002552#ifndef SQLITE_OMIT_UTF16
drh9bb575f2004-09-06 17:24:11 +00002553 sqlite3 *db;
danielk19776622cce2004-05-20 11:00:52 +00002554 const void *zErr;
danielk1977950f0542006-01-18 05:51:57 +00002555 int bytes = 0;
danielk19776622cce2004-05-20 11:00:52 +00002556
2557 if( objc!=2 ){
2558 Tcl_AppendResult(interp, "wrong # args: should be \"",
2559 Tcl_GetString(objv[0]), " DB", 0);
2560 return TCL_ERROR;
2561 }
2562 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2563
2564 zErr = sqlite3_errmsg16(db);
danielk1977950f0542006-01-18 05:51:57 +00002565 if( zErr ){
2566 bytes = sqlite3utf16ByteLen(zErr, -1);
2567 }
danielk19776622cce2004-05-20 11:00:52 +00002568 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes));
drh5436dc22004-11-14 04:04:17 +00002569#endif /* SQLITE_OMIT_UTF16 */
danielk19776622cce2004-05-20 11:00:52 +00002570 return TCL_OK;
2571}
2572
2573/*
2574** Usage: sqlite3_prepare DB sql bytes tailvar
2575**
2576** Compile up to <bytes> bytes of the supplied SQL string <sql> using
2577** database handle <DB>. The parameter <tailval> is the name of a global
2578** variable that is set to the unused portion of <sql> (if any). A
2579** STMT handle is returned.
2580*/
2581static int test_prepare(
2582 void * clientData,
2583 Tcl_Interp *interp,
2584 int objc,
2585 Tcl_Obj *CONST objv[]
2586){
2587 sqlite3 *db;
2588 const char *zSql;
2589 int bytes;
2590 const char *zTail = 0;
2591 sqlite3_stmt *pStmt = 0;
2592 char zBuf[50];
danielk19774ad17132004-05-21 01:47:26 +00002593 int rc;
danielk19776622cce2004-05-20 11:00:52 +00002594
2595 if( objc!=5 ){
2596 Tcl_AppendResult(interp, "wrong # args: should be \"",
2597 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
2598 return TCL_ERROR;
2599 }
2600 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2601 zSql = Tcl_GetString(objv[2]);
2602 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
2603
danielk19774ad17132004-05-21 01:47:26 +00002604 rc = sqlite3_prepare(db, zSql, bytes, &pStmt, &zTail);
drhc60d0442004-09-30 13:43:13 +00002605 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk19776622cce2004-05-20 11:00:52 +00002606 if( zTail ){
2607 if( bytes>=0 ){
2608 bytes = bytes - (zTail-zSql);
2609 }
2610 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
2611 }
danielk19774ad17132004-05-21 01:47:26 +00002612 if( rc!=SQLITE_OK ){
2613 assert( pStmt==0 );
2614 sprintf(zBuf, "(%d) ", rc);
2615 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
2616 return TCL_ERROR;
2617 }
danielk19776622cce2004-05-20 11:00:52 +00002618
danielk19774ad17132004-05-21 01:47:26 +00002619 if( pStmt ){
drh64b1bea2006-01-15 02:30:57 +00002620 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
danielk19774ad17132004-05-21 01:47:26 +00002621 Tcl_AppendResult(interp, zBuf, 0);
2622 }
danielk19776622cce2004-05-20 11:00:52 +00002623 return TCL_OK;
2624}
2625
2626/*
drhb900aaf2006-11-09 00:24:53 +00002627** Usage: sqlite3_prepare_v2 DB sql bytes tailvar
2628**
2629** Compile up to <bytes> bytes of the supplied SQL string <sql> using
2630** database handle <DB>. The parameter <tailval> is the name of a global
2631** variable that is set to the unused portion of <sql> (if any). A
2632** STMT handle is returned.
2633*/
2634static int test_prepare_v2(
2635 void * clientData,
2636 Tcl_Interp *interp,
2637 int objc,
2638 Tcl_Obj *CONST objv[]
2639){
2640 sqlite3 *db;
2641 const char *zSql;
2642 int bytes;
2643 const char *zTail = 0;
2644 sqlite3_stmt *pStmt = 0;
2645 char zBuf[50];
2646 int rc;
2647
2648 if( objc!=5 ){
2649 Tcl_AppendResult(interp, "wrong # args: should be \"",
2650 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
2651 return TCL_ERROR;
2652 }
2653 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2654 zSql = Tcl_GetString(objv[2]);
2655 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
2656
2657 rc = sqlite3_prepare_v2(db, zSql, bytes, &pStmt, &zTail);
2658 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
2659 if( zTail ){
2660 if( bytes>=0 ){
2661 bytes = bytes - (zTail-zSql);
2662 }
2663 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
2664 }
2665 if( rc!=SQLITE_OK ){
2666 assert( pStmt==0 );
2667 sprintf(zBuf, "(%d) ", rc);
2668 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
2669 return TCL_ERROR;
2670 }
2671
2672 if( pStmt ){
2673 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
2674 Tcl_AppendResult(interp, zBuf, 0);
2675 }
2676 return TCL_OK;
2677}
2678
2679/*
2680** Usage: sqlite3_prepare16 DB sql bytes tailvar
danielk19776622cce2004-05-20 11:00:52 +00002681**
2682** Compile up to <bytes> bytes of the supplied SQL string <sql> using
2683** database handle <DB>. The parameter <tailval> is the name of a global
2684** variable that is set to the unused portion of <sql> (if any). A
2685** STMT handle is returned.
2686*/
2687static int test_prepare16(
2688 void * clientData,
2689 Tcl_Interp *interp,
2690 int objc,
2691 Tcl_Obj *CONST objv[]
2692){
drh5436dc22004-11-14 04:04:17 +00002693#ifndef SQLITE_OMIT_UTF16
danielk19776622cce2004-05-20 11:00:52 +00002694 sqlite3 *db;
2695 const void *zSql;
2696 const void *zTail = 0;
2697 Tcl_Obj *pTail = 0;
2698 sqlite3_stmt *pStmt = 0;
drhc60d0442004-09-30 13:43:13 +00002699 char zBuf[50];
2700 int rc;
danielk19776622cce2004-05-20 11:00:52 +00002701 int bytes; /* The integer specified as arg 3 */
2702 int objlen; /* The byte-array length of arg 2 */
2703
2704 if( objc!=5 ){
2705 Tcl_AppendResult(interp, "wrong # args: should be \"",
2706 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
2707 return TCL_ERROR;
2708 }
2709 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2710 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
2711 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
2712
drhc60d0442004-09-30 13:43:13 +00002713 rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, &zTail);
2714 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
2715 if( rc ){
danielk19776622cce2004-05-20 11:00:52 +00002716 return TCL_ERROR;
2717 }
2718
2719 if( zTail ){
2720 objlen = objlen - ((u8 *)zTail-(u8 *)zSql);
2721 }else{
2722 objlen = 0;
2723 }
2724 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
2725 Tcl_IncrRefCount(pTail);
2726 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
danielk19774ad17132004-05-21 01:47:26 +00002727 Tcl_DecrRefCount(pTail);
danielk19776622cce2004-05-20 11:00:52 +00002728
danielk19774ad17132004-05-21 01:47:26 +00002729 if( pStmt ){
drh64b1bea2006-01-15 02:30:57 +00002730 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
danielk19774ad17132004-05-21 01:47:26 +00002731 }
danielk19776622cce2004-05-20 11:00:52 +00002732 Tcl_AppendResult(interp, zBuf, 0);
drh5436dc22004-11-14 04:04:17 +00002733#endif /* SQLITE_OMIT_UTF16 */
danielk19776622cce2004-05-20 11:00:52 +00002734 return TCL_OK;
2735}
2736
danielk19774ad17132004-05-21 01:47:26 +00002737/*
drhb900aaf2006-11-09 00:24:53 +00002738** Usage: sqlite3_prepare16_v2 DB sql bytes tailvar
2739**
2740** Compile up to <bytes> bytes of the supplied SQL string <sql> using
2741** database handle <DB>. The parameter <tailval> is the name of a global
2742** variable that is set to the unused portion of <sql> (if any). A
2743** STMT handle is returned.
2744*/
2745static int test_prepare16_v2(
2746 void * clientData,
2747 Tcl_Interp *interp,
2748 int objc,
2749 Tcl_Obj *CONST objv[]
2750){
2751#ifndef SQLITE_OMIT_UTF16
2752 sqlite3 *db;
2753 const void *zSql;
2754 const void *zTail = 0;
2755 Tcl_Obj *pTail = 0;
2756 sqlite3_stmt *pStmt = 0;
2757 char zBuf[50];
2758 int rc;
2759 int bytes; /* The integer specified as arg 3 */
2760 int objlen; /* The byte-array length of arg 2 */
2761
2762 if( objc!=5 ){
2763 Tcl_AppendResult(interp, "wrong # args: should be \"",
2764 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
2765 return TCL_ERROR;
2766 }
2767 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2768 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
2769 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
2770
2771 rc = sqlite3_prepare16_v2(db, zSql, bytes, &pStmt, &zTail);
2772 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
2773 if( rc ){
2774 return TCL_ERROR;
2775 }
2776
2777 if( zTail ){
2778 objlen = objlen - ((u8 *)zTail-(u8 *)zSql);
2779 }else{
2780 objlen = 0;
2781 }
2782 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
2783 Tcl_IncrRefCount(pTail);
2784 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
2785 Tcl_DecrRefCount(pTail);
2786
2787 if( pStmt ){
2788 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
2789 }
2790 Tcl_AppendResult(interp, zBuf, 0);
2791#endif /* SQLITE_OMIT_UTF16 */
2792 return TCL_OK;
2793}
2794
2795/*
danielk19774ad17132004-05-21 01:47:26 +00002796** Usage: sqlite3_open filename ?options-list?
2797*/
2798static int test_open(
2799 void * clientData,
2800 Tcl_Interp *interp,
2801 int objc,
2802 Tcl_Obj *CONST objv[]
2803){
2804 const char *zFilename;
2805 sqlite3 *db;
2806 int rc;
2807 char zBuf[100];
2808
2809 if( objc!=3 && objc!=2 ){
2810 Tcl_AppendResult(interp, "wrong # args: should be \"",
2811 Tcl_GetString(objv[0]), " filename options-list", 0);
2812 return TCL_ERROR;
2813 }
2814
2815 zFilename = Tcl_GetString(objv[1]);
danielk19774f057f92004-06-08 00:02:33 +00002816 rc = sqlite3_open(zFilename, &db);
danielk19774ad17132004-05-21 01:47:26 +00002817
drh64b1bea2006-01-15 02:30:57 +00002818 if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
danielk19774ad17132004-05-21 01:47:26 +00002819 Tcl_AppendResult(interp, zBuf, 0);
2820 return TCL_OK;
2821}
2822
2823/*
2824** Usage: sqlite3_open16 filename options
2825*/
2826static int test_open16(
2827 void * clientData,
2828 Tcl_Interp *interp,
2829 int objc,
2830 Tcl_Obj *CONST objv[]
2831){
drh5436dc22004-11-14 04:04:17 +00002832#ifndef SQLITE_OMIT_UTF16
danielk19774ad17132004-05-21 01:47:26 +00002833 const void *zFilename;
2834 sqlite3 *db;
2835 int rc;
2836 char zBuf[100];
2837
2838 if( objc!=3 ){
2839 Tcl_AppendResult(interp, "wrong # args: should be \"",
2840 Tcl_GetString(objv[0]), " filename options-list", 0);
2841 return TCL_ERROR;
2842 }
2843
2844 zFilename = Tcl_GetByteArrayFromObj(objv[1], 0);
danielk19774f057f92004-06-08 00:02:33 +00002845 rc = sqlite3_open16(zFilename, &db);
danielk19774ad17132004-05-21 01:47:26 +00002846
drh64b1bea2006-01-15 02:30:57 +00002847 if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
danielk19774ad17132004-05-21 01:47:26 +00002848 Tcl_AppendResult(interp, zBuf, 0);
drh5436dc22004-11-14 04:04:17 +00002849#endif /* SQLITE_OMIT_UTF16 */
danielk19774ad17132004-05-21 01:47:26 +00002850 return TCL_OK;
2851}
drhd3d39e92004-05-20 22:16:29 +00002852
2853/*
danielk1977bc6ada42004-06-30 08:20:16 +00002854** Usage: sqlite3_complete16 <UTF-16 string>
2855**
2856** Return 1 if the supplied argument is a complete SQL statement, or zero
2857** otherwise.
2858*/
2859static int test_complete16(
2860 void * clientData,
2861 Tcl_Interp *interp,
2862 int objc,
2863 Tcl_Obj *CONST objv[]
2864){
drhccae6022005-02-26 17:31:26 +00002865#if !defined(SQLITE_OMIT_COMPLETE) && !defined(SQLITE_OMIT_UTF16)
danielk1977bc6ada42004-06-30 08:20:16 +00002866 char *zBuf;
2867
2868 if( objc!=2 ){
2869 Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>");
2870 return TCL_ERROR;
2871 }
2872
drh03d847e2005-12-09 20:21:58 +00002873 zBuf = (char*)Tcl_GetByteArrayFromObj(objv[1], 0);
danielk1977bc6ada42004-06-30 08:20:16 +00002874 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf)));
drhccae6022005-02-26 17:31:26 +00002875#endif /* SQLITE_OMIT_COMPLETE && SQLITE_OMIT_UTF16 */
danielk1977bc6ada42004-06-30 08:20:16 +00002876 return TCL_OK;
2877}
2878
2879/*
danielk1977106bb232004-05-21 10:08:53 +00002880** Usage: sqlite3_step STMT
2881**
2882** Advance the statement to the next row.
2883*/
danielk197717240fd2004-05-26 00:07:25 +00002884static int test_step(
danielk1977106bb232004-05-21 10:08:53 +00002885 void * clientData,
2886 Tcl_Interp *interp,
2887 int objc,
2888 Tcl_Obj *CONST objv[]
2889){
2890 sqlite3_stmt *pStmt;
2891 int rc;
2892
danielk1977e1cd9872004-05-22 10:33:04 +00002893 if( objc!=2 ){
danielk1977106bb232004-05-21 10:08:53 +00002894 Tcl_AppendResult(interp, "wrong # args: should be \"",
2895 Tcl_GetString(objv[0]), " STMT", 0);
2896 return TCL_ERROR;
2897 }
2898
2899 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
danielk197717240fd2004-05-26 00:07:25 +00002900 rc = sqlite3_step(pStmt);
danielk1977106bb232004-05-21 10:08:53 +00002901
danielk1977fbcd5852004-06-15 02:44:18 +00002902 /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */
danielk197765904932004-05-26 06:18:37 +00002903 Tcl_SetResult(interp, (char *)errorName(rc), 0);
danielk1977e1cd9872004-05-22 10:33:04 +00002904 return TCL_OK;
2905}
2906
2907/*
danielk197717240fd2004-05-26 00:07:25 +00002908** Usage: sqlite3_column_count STMT
2909**
2910** Return the number of columns returned by the sql statement STMT.
2911*/
2912static int test_column_count(
2913 void * clientData,
2914 Tcl_Interp *interp,
2915 int objc,
2916 Tcl_Obj *CONST objv[]
2917){
2918 sqlite3_stmt *pStmt;
2919
2920 if( objc!=2 ){
2921 Tcl_AppendResult(interp, "wrong # args: should be \"",
2922 Tcl_GetString(objv[0]), " STMT column", 0);
2923 return TCL_ERROR;
2924 }
2925
2926 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2927
2928 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt)));
2929 return TCL_OK;
2930}
2931
2932/*
danielk19773cf86062004-05-26 10:11:05 +00002933** Usage: sqlite3_column_type STMT column
2934**
2935** Return the type of the data in column 'column' of the current row.
2936*/
2937static int test_column_type(
2938 void * clientData,
2939 Tcl_Interp *interp,
2940 int objc,
2941 Tcl_Obj *CONST objv[]
2942){
2943 sqlite3_stmt *pStmt;
2944 int col;
2945 int tp;
2946
2947 if( objc!=3 ){
2948 Tcl_AppendResult(interp, "wrong # args: should be \"",
2949 Tcl_GetString(objv[0]), " STMT column", 0);
2950 return TCL_ERROR;
2951 }
2952
2953 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2954 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2955
2956 tp = sqlite3_column_type(pStmt, col);
2957 switch( tp ){
drh9c054832004-05-31 18:51:57 +00002958 case SQLITE_INTEGER:
danielk19773cf86062004-05-26 10:11:05 +00002959 Tcl_SetResult(interp, "INTEGER", TCL_STATIC);
2960 break;
drh9c054832004-05-31 18:51:57 +00002961 case SQLITE_NULL:
danielk19773cf86062004-05-26 10:11:05 +00002962 Tcl_SetResult(interp, "NULL", TCL_STATIC);
2963 break;
drh9c054832004-05-31 18:51:57 +00002964 case SQLITE_FLOAT:
danielk19773cf86062004-05-26 10:11:05 +00002965 Tcl_SetResult(interp, "FLOAT", TCL_STATIC);
2966 break;
drh9c054832004-05-31 18:51:57 +00002967 case SQLITE_TEXT:
danielk19773cf86062004-05-26 10:11:05 +00002968 Tcl_SetResult(interp, "TEXT", TCL_STATIC);
2969 break;
drh9c054832004-05-31 18:51:57 +00002970 case SQLITE_BLOB:
danielk19773cf86062004-05-26 10:11:05 +00002971 Tcl_SetResult(interp, "BLOB", TCL_STATIC);
2972 break;
2973 default:
2974 assert(0);
2975 }
2976
2977 return TCL_OK;
2978}
2979
2980/*
danielk197704f2e682004-05-27 01:04:07 +00002981** Usage: sqlite3_column_int64 STMT column
danielk19773cf86062004-05-26 10:11:05 +00002982**
2983** Return the data in column 'column' of the current row cast as an
danielk197704f2e682004-05-27 01:04:07 +00002984** wide (64-bit) integer.
danielk19773cf86062004-05-26 10:11:05 +00002985*/
danielk197704f2e682004-05-27 01:04:07 +00002986static int test_column_int64(
danielk19773cf86062004-05-26 10:11:05 +00002987 void * clientData,
2988 Tcl_Interp *interp,
2989 int objc,
2990 Tcl_Obj *CONST objv[]
2991){
2992 sqlite3_stmt *pStmt;
2993 int col;
danielk197704f2e682004-05-27 01:04:07 +00002994 i64 iVal;
danielk19773cf86062004-05-26 10:11:05 +00002995
2996 if( objc!=3 ){
2997 Tcl_AppendResult(interp, "wrong # args: should be \"",
2998 Tcl_GetString(objv[0]), " STMT column", 0);
2999 return TCL_ERROR;
3000 }
3001
3002 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3003 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
3004
danielk197704f2e682004-05-27 01:04:07 +00003005 iVal = sqlite3_column_int64(pStmt, col);
3006 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal));
3007 return TCL_OK;
3008}
3009
3010/*
danielk1977ea61b2c2004-05-27 01:49:51 +00003011** Usage: sqlite3_column_blob STMT column
3012*/
3013static int test_column_blob(
3014 void * clientData,
3015 Tcl_Interp *interp,
3016 int objc,
3017 Tcl_Obj *CONST objv[]
3018){
3019 sqlite3_stmt *pStmt;
3020 int col;
3021
3022 int len;
danielk1977c572ef72004-05-27 09:28:41 +00003023 const void *pBlob;
danielk1977ea61b2c2004-05-27 01:49:51 +00003024
3025 if( objc!=3 ){
3026 Tcl_AppendResult(interp, "wrong # args: should be \"",
3027 Tcl_GetString(objv[0]), " STMT column", 0);
3028 return TCL_ERROR;
3029 }
3030
3031 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3032 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
3033
3034 pBlob = sqlite3_column_blob(pStmt, col);
3035 len = sqlite3_column_bytes(pStmt, col);
3036 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len));
3037 return TCL_OK;
3038}
3039
3040/*
danielk197704f2e682004-05-27 01:04:07 +00003041** Usage: sqlite3_column_double STMT column
3042**
3043** Return the data in column 'column' of the current row cast as a double.
3044*/
3045static int test_column_double(
3046 void * clientData,
3047 Tcl_Interp *interp,
3048 int objc,
3049 Tcl_Obj *CONST objv[]
3050){
3051 sqlite3_stmt *pStmt;
3052 int col;
3053 double rVal;
3054
3055 if( objc!=3 ){
3056 Tcl_AppendResult(interp, "wrong # args: should be \"",
3057 Tcl_GetString(objv[0]), " STMT column", 0);
3058 return TCL_ERROR;
3059 }
3060
3061 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3062 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
3063
3064 rVal = sqlite3_column_double(pStmt, col);
danielk1977c572ef72004-05-27 09:28:41 +00003065 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal));
danielk19773cf86062004-05-26 10:11:05 +00003066 return TCL_OK;
3067}
3068
3069/*
danielk197717240fd2004-05-26 00:07:25 +00003070** Usage: sqlite3_data_count STMT
3071**
3072** Return the number of columns returned by the sql statement STMT.
3073*/
3074static int test_data_count(
3075 void * clientData,
3076 Tcl_Interp *interp,
3077 int objc,
3078 Tcl_Obj *CONST objv[]
3079){
3080 sqlite3_stmt *pStmt;
3081
3082 if( objc!=2 ){
3083 Tcl_AppendResult(interp, "wrong # args: should be \"",
3084 Tcl_GetString(objv[0]), " STMT column", 0);
3085 return TCL_ERROR;
3086 }
3087
3088 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3089
3090 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt)));
3091 return TCL_OK;
3092}
3093
3094/*
danielk197704f2e682004-05-27 01:04:07 +00003095** Usage: sqlite3_column_text STMT column
3096**
3097** Usage: sqlite3_column_decltype STMT column
3098**
3099** Usage: sqlite3_column_name STMT column
3100*/
3101static int test_stmt_utf8(
drh241db312004-06-22 12:46:53 +00003102 void * clientData, /* Pointer to SQLite API function to be invoke */
danielk197704f2e682004-05-27 01:04:07 +00003103 Tcl_Interp *interp,
3104 int objc,
3105 Tcl_Obj *CONST objv[]
3106){
3107 sqlite3_stmt *pStmt;
3108 int col;
danielk1977c572ef72004-05-27 09:28:41 +00003109 const char *(*xFunc)(sqlite3_stmt*, int) = clientData;
danielk1977f93bbbe2004-05-27 10:30:52 +00003110 const char *zRet;
danielk197704f2e682004-05-27 01:04:07 +00003111
3112 if( objc!=3 ){
3113 Tcl_AppendResult(interp, "wrong # args: should be \"",
3114 Tcl_GetString(objv[0]), " STMT column", 0);
3115 return TCL_ERROR;
3116 }
3117
3118 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3119 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
danielk1977f93bbbe2004-05-27 10:30:52 +00003120 zRet = xFunc(pStmt, col);
3121 if( zRet ){
3122 Tcl_SetResult(interp, (char *)zRet, 0);
3123 }
danielk197704f2e682004-05-27 01:04:07 +00003124 return TCL_OK;
3125}
3126
danielk19776b456a22005-03-21 04:04:02 +00003127static int test_global_recover(
3128 void * clientData,
3129 Tcl_Interp *interp,
3130 int objc,
3131 Tcl_Obj *CONST objv[]
3132){
3133#ifndef SQLITE_OMIT_GLOBALRECOVER
3134 int rc;
3135 if( objc!=1 ){
3136 Tcl_WrongNumArgs(interp, 1, objv, "");
3137 return TCL_ERROR;
3138 }
3139 rc = sqlite3_global_recover();
3140 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
3141#endif
3142 return TCL_OK;
3143}
3144
danielk197704f2e682004-05-27 01:04:07 +00003145/*
3146** Usage: sqlite3_column_text STMT column
3147**
3148** Usage: sqlite3_column_decltype STMT column
3149**
3150** Usage: sqlite3_column_name STMT column
3151*/
3152static int test_stmt_utf16(
drh241db312004-06-22 12:46:53 +00003153 void * clientData, /* Pointer to SQLite API function to be invoked */
danielk197704f2e682004-05-27 01:04:07 +00003154 Tcl_Interp *interp,
3155 int objc,
3156 Tcl_Obj *CONST objv[]
3157){
drh5436dc22004-11-14 04:04:17 +00003158#ifndef SQLITE_OMIT_UTF16
danielk197704f2e682004-05-27 01:04:07 +00003159 sqlite3_stmt *pStmt;
3160 int col;
3161 Tcl_Obj *pRet;
3162 const void *zName16;
danielk1977c572ef72004-05-27 09:28:41 +00003163 const void *(*xFunc)(sqlite3_stmt*, int) = clientData;
danielk197704f2e682004-05-27 01:04:07 +00003164
3165 if( objc!=3 ){
3166 Tcl_AppendResult(interp, "wrong # args: should be \"",
3167 Tcl_GetString(objv[0]), " STMT column", 0);
3168 return TCL_ERROR;
3169 }
3170
3171 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3172 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
3173
3174 zName16 = xFunc(pStmt, col);
danielk1977f93bbbe2004-05-27 10:30:52 +00003175 if( zName16 ){
3176 pRet = Tcl_NewByteArrayObj(zName16, sqlite3utf16ByteLen(zName16, -1)+2);
3177 Tcl_SetObjResult(interp, pRet);
3178 }
drh5436dc22004-11-14 04:04:17 +00003179#endif /* SQLITE_OMIT_UTF16 */
danielk197704f2e682004-05-27 01:04:07 +00003180
3181 return TCL_OK;
3182}
3183
3184/*
3185** Usage: sqlite3_column_int STMT column
3186**
3187** Usage: sqlite3_column_bytes STMT column
3188**
3189** Usage: sqlite3_column_bytes16 STMT column
3190**
3191*/
3192static int test_stmt_int(
drh241db312004-06-22 12:46:53 +00003193 void * clientData, /* Pointer to SQLite API function to be invoked */
danielk197704f2e682004-05-27 01:04:07 +00003194 Tcl_Interp *interp,
3195 int objc,
3196 Tcl_Obj *CONST objv[]
3197){
3198 sqlite3_stmt *pStmt;
3199 int col;
danielk1977c572ef72004-05-27 09:28:41 +00003200 int (*xFunc)(sqlite3_stmt*, int) = clientData;
danielk197704f2e682004-05-27 01:04:07 +00003201
3202 if( objc!=3 ){
3203 Tcl_AppendResult(interp, "wrong # args: should be \"",
3204 Tcl_GetString(objv[0]), " STMT column", 0);
3205 return TCL_ERROR;
3206 }
3207
3208 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
3209 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
3210
3211 Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col)));
3212 return TCL_OK;
3213}
3214
danielk197744ee5bf2005-05-27 09:41:12 +00003215#ifndef SQLITE_OMIT_DISKIO
danielk19779a1d0ab2004-06-01 14:09:28 +00003216/*
3217** Usage: sqlite3OsOpenReadWrite <filename>
3218*/
3219static int test_sqlite3OsOpenReadWrite(
3220 void * clientData,
3221 Tcl_Interp *interp,
3222 int objc,
3223 Tcl_Obj *CONST objv[]
3224){
drh9cbe6352005-11-29 03:13:21 +00003225 OsFile *pFile;
danielk19779a1d0ab2004-06-01 14:09:28 +00003226 int rc;
3227 int dummy;
3228 char zBuf[100];
danielk197704f2e682004-05-27 01:04:07 +00003229
danielk19779a1d0ab2004-06-01 14:09:28 +00003230 if( objc!=2 ){
3231 Tcl_AppendResult(interp, "wrong # args: should be \"",
3232 Tcl_GetString(objv[0]), " filename", 0);
3233 return TCL_ERROR;
3234 }
3235
drh66560ad2006-01-06 14:32:19 +00003236 rc = sqlite3OsOpenReadWrite(Tcl_GetString(objv[1]), &pFile, &dummy);
danielk19779a1d0ab2004-06-01 14:09:28 +00003237 if( rc!=SQLITE_OK ){
danielk19779a1d0ab2004-06-01 14:09:28 +00003238 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
3239 return TCL_ERROR;
3240 }
drh64b1bea2006-01-15 02:30:57 +00003241 sqlite3TestMakePointerStr(interp, zBuf, pFile);
danielk19779a1d0ab2004-06-01 14:09:28 +00003242 Tcl_SetResult(interp, zBuf, 0);
3243 return TCL_ERROR;
3244}
3245
3246/*
3247** Usage: sqlite3OsClose <file handle>
3248*/
3249static int test_sqlite3OsClose(
3250 void * clientData,
3251 Tcl_Interp *interp,
3252 int objc,
3253 Tcl_Obj *CONST objv[]
3254){
drh9cbe6352005-11-29 03:13:21 +00003255 OsFile *pFile;
danielk19779a1d0ab2004-06-01 14:09:28 +00003256 int rc;
3257
3258 if( objc!=2 ){
3259 Tcl_AppendResult(interp, "wrong # args: should be \"",
3260 Tcl_GetString(objv[0]), " filehandle", 0);
3261 return TCL_ERROR;
3262 }
3263
3264 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
3265 return TCL_ERROR;
3266 }
drh054889e2005-11-30 03:20:31 +00003267 rc = sqlite3OsClose(&pFile);
danielk19779a1d0ab2004-06-01 14:09:28 +00003268 if( rc!=SQLITE_OK ){
3269 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
3270 return TCL_ERROR;
3271 }
danielk19779a1d0ab2004-06-01 14:09:28 +00003272 return TCL_OK;
3273}
3274
3275/*
3276** Usage: sqlite3OsLock <file handle> <locktype>
3277*/
3278static int test_sqlite3OsLock(
3279 void * clientData,
3280 Tcl_Interp *interp,
3281 int objc,
3282 Tcl_Obj *CONST objv[]
3283){
3284 OsFile * pFile;
3285 int rc;
3286
3287 if( objc!=3 ){
3288 Tcl_AppendResult(interp, "wrong # args: should be \"",
3289 Tcl_GetString(objv[0]),
3290 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
3291 return TCL_ERROR;
3292 }
3293
3294 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
3295 return TCL_ERROR;
3296 }
3297
3298 if( 0==strcmp("SHARED", Tcl_GetString(objv[2])) ){
drh054889e2005-11-30 03:20:31 +00003299 rc = sqlite3OsLock(pFile, SHARED_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00003300 }
3301 else if( 0==strcmp("RESERVED", Tcl_GetString(objv[2])) ){
drh054889e2005-11-30 03:20:31 +00003302 rc = sqlite3OsLock(pFile, RESERVED_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00003303 }
3304 else if( 0==strcmp("PENDING", Tcl_GetString(objv[2])) ){
drh054889e2005-11-30 03:20:31 +00003305 rc = sqlite3OsLock(pFile, PENDING_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00003306 }
3307 else if( 0==strcmp("EXCLUSIVE", Tcl_GetString(objv[2])) ){
drh054889e2005-11-30 03:20:31 +00003308 rc = sqlite3OsLock(pFile, EXCLUSIVE_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00003309 }else{
3310 Tcl_AppendResult(interp, "wrong # args: should be \"",
3311 Tcl_GetString(objv[0]),
3312 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
3313 return TCL_ERROR;
3314 }
3315
3316 if( rc!=SQLITE_OK ){
3317 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
3318 return TCL_ERROR;
3319 }
3320 return TCL_OK;
3321}
3322
3323/*
3324** Usage: sqlite3OsUnlock <file handle>
3325*/
3326static int test_sqlite3OsUnlock(
3327 void * clientData,
3328 Tcl_Interp *interp,
3329 int objc,
3330 Tcl_Obj *CONST objv[]
3331){
3332 OsFile * pFile;
3333 int rc;
3334
3335 if( objc!=2 ){
3336 Tcl_AppendResult(interp, "wrong # args: should be \"",
3337 Tcl_GetString(objv[0]), " filehandle", 0);
3338 return TCL_ERROR;
3339 }
3340
3341 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
3342 return TCL_ERROR;
3343 }
drh054889e2005-11-30 03:20:31 +00003344 rc = sqlite3OsUnlock(pFile, NO_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00003345 if( rc!=SQLITE_OK ){
3346 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
3347 return TCL_ERROR;
3348 }
3349 return TCL_OK;
3350}
drhd3d39e92004-05-20 22:16:29 +00003351
drhab3f9fe2004-08-14 17:10:10 +00003352/*
3353** Usage: sqlite3OsTempFileName
3354*/
3355static int test_sqlite3OsTempFileName(
3356 void * clientData,
3357 Tcl_Interp *interp,
3358 int objc,
3359 Tcl_Obj *CONST objv[]
3360){
3361 char zFile[SQLITE_TEMPNAME_SIZE];
3362 int rc;
3363
drh66560ad2006-01-06 14:32:19 +00003364 rc = sqlite3OsTempFileName(zFile);
drhab3f9fe2004-08-14 17:10:10 +00003365 if( rc!=SQLITE_OK ){
3366 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
3367 return TCL_ERROR;
3368 }
3369 Tcl_AppendResult(interp, zFile, 0);
3370 return TCL_OK;
3371}
danielk197744ee5bf2005-05-27 09:41:12 +00003372#endif
danielk1977d8123362004-06-12 09:25:12 +00003373
danielk19776622cce2004-05-20 11:00:52 +00003374/*
drhcacb2082005-01-11 15:28:33 +00003375** Usage: sqlite_set_magic DB MAGIC-NUMBER
3376**
3377** Set the db->magic value. This is used to test error recovery logic.
3378*/
3379static int sqlite_set_magic(
3380 void * clientData,
3381 Tcl_Interp *interp,
3382 int argc,
3383 char **argv
3384){
3385 sqlite3 *db;
3386 if( argc!=3 ){
3387 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
3388 " DB MAGIC", 0);
3389 return TCL_ERROR;
3390 }
3391 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
3392 if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){
3393 db->magic = SQLITE_MAGIC_OPEN;
3394 }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){
3395 db->magic = SQLITE_MAGIC_CLOSED;
3396 }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){
3397 db->magic = SQLITE_MAGIC_BUSY;
3398 }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){
3399 db->magic = SQLITE_MAGIC_ERROR;
3400 }else if( Tcl_GetInt(interp, argv[2], &db->magic) ){
3401 return TCL_ERROR;
3402 }
3403 return TCL_OK;
3404}
3405
3406/*
drhc5cdca62005-01-11 16:54:14 +00003407** Usage: sqlite3_interrupt DB
3408**
3409** Trigger an interrupt on DB
3410*/
3411static int test_interrupt(
3412 void * clientData,
3413 Tcl_Interp *interp,
3414 int argc,
3415 char **argv
3416){
3417 sqlite3 *db;
3418 if( argc!=2 ){
3419 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
3420 return TCL_ERROR;
3421 }
3422 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
3423 sqlite3_interrupt(db);
3424 return TCL_OK;
3425}
3426
drh79158e12005-09-06 21:40:45 +00003427static u8 *sqlite3_stack_baseline = 0;
3428
drhc5cdca62005-01-11 16:54:14 +00003429/*
drh79158e12005-09-06 21:40:45 +00003430** Fill the stack with a known bitpattern.
danielk1977600dd0b2005-01-20 01:14:23 +00003431*/
drh79158e12005-09-06 21:40:45 +00003432static void prepStack(void){
3433 int i;
3434 u32 bigBuf[65536];
3435 for(i=0; i<sizeof(bigBuf); i++) bigBuf[i] = 0xdeadbeef;
3436 sqlite3_stack_baseline = (u8*)&bigBuf[65536];
3437}
3438
3439/*
3440** Get the current stack depth. Used for debugging only.
3441*/
3442u64 sqlite3StackDepth(void){
3443 u8 x;
3444 return (u64)(sqlite3_stack_baseline - &x);
3445}
3446
3447/*
3448** Usage: sqlite3_stack_used DB SQL
3449**
3450** Try to measure the amount of stack space used by a call to sqlite3_exec
3451*/
3452static int test_stack_used(
danielk1977600dd0b2005-01-20 01:14:23 +00003453 void * clientData,
3454 Tcl_Interp *interp,
3455 int argc,
3456 char **argv
3457){
3458 sqlite3 *db;
drh79158e12005-09-06 21:40:45 +00003459 int i;
3460 if( argc!=3 ){
3461 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
3462 " DB SQL", 0);
danielk1977600dd0b2005-01-20 01:14:23 +00003463 return TCL_ERROR;
3464 }
drh79158e12005-09-06 21:40:45 +00003465 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
3466 prepStack();
drh37527852006-03-16 16:19:56 +00003467 (void)sqlite3_exec(db, argv[2], 0, 0, 0);
drh79158e12005-09-06 21:40:45 +00003468 for(i=65535; i>=0 && ((u32*)sqlite3_stack_baseline)[-i]==0xdeadbeef; i--){}
3469 Tcl_SetObjResult(interp, Tcl_NewIntObj(i*4));
danielk1977600dd0b2005-01-20 01:14:23 +00003470 return TCL_OK;
3471}
danielk1977600dd0b2005-01-20 01:14:23 +00003472
3473/*
danielk19779636c4e2005-01-25 04:27:54 +00003474** Usage: sqlite_delete_function DB function-name
3475**
3476** Delete the user function 'function-name' from database handle DB. It
3477** is assumed that the user function was created as UTF8, any number of
3478** arguments (the way the TCL interface does it).
3479*/
3480static int delete_function(
3481 void * clientData,
3482 Tcl_Interp *interp,
3483 int argc,
3484 char **argv
3485){
3486 int rc;
3487 sqlite3 *db;
3488 if( argc!=3 ){
3489 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
3490 " DB function-name", 0);
3491 return TCL_ERROR;
3492 }
3493 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
3494 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0);
3495 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
3496 return TCL_OK;
3497}
3498
3499/*
3500** Usage: sqlite_delete_collation DB collation-name
3501**
3502** Delete the collation sequence 'collation-name' from database handle
3503** DB. It is assumed that the collation sequence was created as UTF8 (the
3504** way the TCL interface does it).
3505*/
3506static int delete_collation(
3507 void * clientData,
3508 Tcl_Interp *interp,
3509 int argc,
3510 char **argv
3511){
3512 int rc;
3513 sqlite3 *db;
3514 if( argc!=3 ){
3515 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
3516 " DB function-name", 0);
3517 return TCL_ERROR;
3518 }
3519 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
3520 rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0);
3521 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
3522 return TCL_OK;
3523}
3524
3525/*
drh3e1d8e62005-05-26 16:23:34 +00003526** Usage: sqlite3_get_autocommit DB
3527**
3528** Return true if the database DB is currently in auto-commit mode.
3529** Return false if not.
3530*/
3531static int get_autocommit(
3532 void * clientData,
3533 Tcl_Interp *interp,
3534 int argc,
3535 char **argv
3536){
3537 char zBuf[30];
3538 sqlite3 *db;
3539 if( argc!=2 ){
3540 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
3541 " DB", 0);
3542 return TCL_ERROR;
3543 }
3544 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
3545 sprintf(zBuf, "%d", sqlite3_get_autocommit(db));
3546 Tcl_AppendResult(interp, zBuf, 0);
3547 return TCL_OK;
3548}
3549
3550/*
drh30867652006-07-06 10:59:57 +00003551** Usage: sqlite3_busy_timeout DB MS
3552**
3553** Set the busy timeout. This is more easily done using the timeout
3554** method of the TCL interface. But we need a way to test the case
3555** where it returns SQLITE_MISUSE.
3556*/
3557static int test_busy_timeout(
3558 void * clientData,
3559 Tcl_Interp *interp,
3560 int argc,
3561 char **argv
3562){
3563 int rc, ms;
3564 sqlite3 *db;
3565 if( argc!=3 ){
3566 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
3567 " DB", 0);
3568 return TCL_ERROR;
3569 }
3570 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
3571 if( Tcl_GetInt(interp, argv[2], &ms) ) return TCL_ERROR;
3572 rc = sqlite3_busy_timeout(db, ms);
3573 Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
3574 return TCL_OK;
3575}
3576
3577/*
drh92febd92004-08-20 18:34:20 +00003578** Usage: tcl_variable_type VARIABLENAME
3579**
3580** Return the name of the internal representation for the
3581** value of the given variable.
3582*/
3583static int tcl_variable_type(
3584 void * clientData,
3585 Tcl_Interp *interp,
3586 int objc,
3587 Tcl_Obj *CONST objv[]
3588){
3589 Tcl_Obj *pVar;
3590 if( objc!=2 ){
3591 Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE");
3592 return TCL_ERROR;
3593 }
3594 pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG);
3595 if( pVar==0 ) return TCL_ERROR;
3596 if( pVar->typePtr ){
3597 Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1));
3598 }
3599 return TCL_OK;
3600}
3601
3602/*
drh6aafc292006-01-05 15:50:06 +00003603** Usage: sqlite3_release_memory ?N?
3604**
3605** Attempt to release memory currently held but not actually required.
3606** The integer N is the number of bytes we are trying to release. The
3607** return value is the amount of memory actually released.
3608*/
3609static int test_release_memory(
3610 void * clientData,
3611 Tcl_Interp *interp,
3612 int objc,
3613 Tcl_Obj *CONST objv[]
3614){
drh6f7adc82006-01-11 21:41:20 +00003615#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
drh6aafc292006-01-05 15:50:06 +00003616 int N;
3617 int amt;
3618 if( objc!=1 && objc!=2 ){
3619 Tcl_WrongNumArgs(interp, 1, objv, "?N?");
3620 return TCL_ERROR;
3621 }
3622 if( objc==2 ){
3623 if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
3624 }else{
3625 N = -1;
3626 }
3627 amt = sqlite3_release_memory(N);
3628 Tcl_SetObjResult(interp, Tcl_NewIntObj(amt));
3629#endif
3630 return TCL_OK;
3631}
3632
3633/*
3634** Usage: sqlite3_soft_heap_limit ?N?
3635**
3636** Query or set the soft heap limit for the current thread. The
3637** limit is only changed if the N is present. The previous limit
3638** is returned.
3639*/
3640static int test_soft_heap_limit(
3641 void * clientData,
3642 Tcl_Interp *interp,
3643 int objc,
3644 Tcl_Obj *CONST objv[]
3645){
drh6f7adc82006-01-11 21:41:20 +00003646#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
drh6aafc292006-01-05 15:50:06 +00003647 int amt;
3648 if( objc!=1 && objc!=2 ){
3649 Tcl_WrongNumArgs(interp, 1, objv, "?N?");
3650 return TCL_ERROR;
3651 }
drh6f7adc82006-01-11 21:41:20 +00003652 amt = sqlite3ThreadDataReadOnly()->nSoftHeapLimit;
drh6aafc292006-01-05 15:50:06 +00003653 if( objc==2 ){
3654 int N;
3655 if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
3656 sqlite3_soft_heap_limit(N);
3657 }
3658 Tcl_SetObjResult(interp, Tcl_NewIntObj(amt));
3659#endif
3660 return TCL_OK;
3661}
3662
3663/*
drhb4bc7052006-01-11 23:40:33 +00003664** Usage: sqlite3_clear_tsd_memdebug
3665**
3666** Clear all of the MEMDEBUG information out of thread-specific data.
3667** This will allow it to be deallocated.
3668*/
3669static int test_clear_tsd_memdebug(
3670 void * clientData,
3671 Tcl_Interp *interp,
3672 int objc,
3673 Tcl_Obj *CONST objv[]
3674){
drhb4bc7052006-01-11 23:40:33 +00003675 return TCL_OK;
3676}
3677
3678/*
3679** Usage: sqlite3_tsd_release
3680**
3681** Call sqlite3ReleaseThreadData.
3682*/
3683static int test_tsd_release(
3684 void * clientData,
3685 Tcl_Interp *interp,
3686 int objc,
3687 Tcl_Obj *CONST objv[]
3688){
3689#if defined(SQLITE_MEMDEBUG)
3690 sqlite3ReleaseThreadData();
3691#endif
3692 return TCL_OK;
3693}
3694
3695/*
3696** Usage: sqlite3_thread_cleanup
3697**
3698** Call the sqlite3_thread_cleanup API.
3699*/
3700static int test_thread_cleanup(
3701 void * clientData,
3702 Tcl_Interp *interp,
3703 int objc,
3704 Tcl_Obj *CONST objv[]
3705){
3706 sqlite3_thread_cleanup();
3707 return TCL_OK;
3708}
3709
3710
3711/*
drh27d258a2004-10-30 20:23:09 +00003712** This routine sets entries in the global ::sqlite_options() array variable
3713** according to the compile-time configuration of the database. Test
3714** procedures use this to determine when tests should be omitted.
3715*/
3716static void set_options(Tcl_Interp *interp){
drh75f86a42005-02-17 00:03:06 +00003717#ifdef SQLITE_32BIT_ROWID
3718 Tcl_SetVar2(interp, "sqlite_options", "rowid32", "1", TCL_GLOBAL_ONLY);
3719#else
3720 Tcl_SetVar2(interp, "sqlite_options", "rowid32", "0", TCL_GLOBAL_ONLY);
3721#endif
3722
drh9f18e8a2005-07-08 12:13:04 +00003723#ifdef SQLITE_CASE_SENSITIVE_LIKE
3724 Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","1",TCL_GLOBAL_ONLY);
3725#else
3726 Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","0",TCL_GLOBAL_ONLY);
3727#endif
3728
danielk1977d7c03f72005-11-25 10:38:22 +00003729#ifdef SQLITE_DISABLE_DIRSYNC
3730 Tcl_SetVar2(interp, "sqlite_options", "dirsync", "0", TCL_GLOBAL_ONLY);
3731#else
3732 Tcl_SetVar2(interp, "sqlite_options", "dirsync", "1", TCL_GLOBAL_ONLY);
3733#endif
3734
danielk197726c5d792005-11-25 09:01:23 +00003735#ifdef SQLITE_DISABLE_LFS
3736 Tcl_SetVar2(interp, "sqlite_options", "lfs", "0", TCL_GLOBAL_ONLY);
3737#else
3738 Tcl_SetVar2(interp, "sqlite_options", "lfs", "1", TCL_GLOBAL_ONLY);
3739#endif
3740
danielk19771c8c23c2004-11-12 15:53:37 +00003741#ifdef SQLITE_OMIT_ALTERTABLE
3742 Tcl_SetVar2(interp, "sqlite_options", "altertable", "0", TCL_GLOBAL_ONLY);
3743#else
3744 Tcl_SetVar2(interp, "sqlite_options", "altertable", "1", TCL_GLOBAL_ONLY);
3745#endif
drh13d70422004-11-13 15:59:14 +00003746
drh9f18e8a2005-07-08 12:13:04 +00003747#ifdef SQLITE_OMIT_ANALYZE
3748 Tcl_SetVar2(interp, "sqlite_options", "analyze", "0", TCL_GLOBAL_ONLY);
3749#else
3750 Tcl_SetVar2(interp, "sqlite_options", "analyze", "1", TCL_GLOBAL_ONLY);
3751#endif
3752
drh13d70422004-11-13 15:59:14 +00003753#ifdef SQLITE_OMIT_AUTHORIZATION
3754 Tcl_SetVar2(interp, "sqlite_options", "auth", "0", TCL_GLOBAL_ONLY);
3755#else
3756 Tcl_SetVar2(interp, "sqlite_options", "auth", "1", TCL_GLOBAL_ONLY);
3757#endif
3758
drhf3388142004-11-13 03:48:06 +00003759#ifdef SQLITE_OMIT_AUTOINCREMENT
3760 Tcl_SetVar2(interp, "sqlite_options", "autoinc", "0", TCL_GLOBAL_ONLY);
3761#else
3762 Tcl_SetVar2(interp, "sqlite_options", "autoinc", "1", TCL_GLOBAL_ONLY);
3763#endif
3764
danielk197745901d62004-11-10 15:27:38 +00003765#ifdef SQLITE_OMIT_AUTOVACUUM
3766 Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "0", TCL_GLOBAL_ONLY);
3767#else
3768 Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "1", TCL_GLOBAL_ONLY);
drhf3388142004-11-13 03:48:06 +00003769#endif /* SQLITE_OMIT_AUTOVACUUM */
danielk19774d36b812004-11-19 07:07:30 +00003770#if !defined(SQLITE_DEFAULT_AUTOVACUUM) || SQLITE_DEFAULT_AUTOVACUUM==0
danielk197745901d62004-11-10 15:27:38 +00003771 Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","0",TCL_GLOBAL_ONLY);
3772#else
3773 Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","1",TCL_GLOBAL_ONLY);
3774#endif
drh13d70422004-11-13 15:59:14 +00003775
drh55ef4d92005-08-14 01:20:37 +00003776#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
3777 Tcl_SetVar2(interp, "sqlite_options", "between_opt", "0", TCL_GLOBAL_ONLY);
3778#else
3779 Tcl_SetVar2(interp, "sqlite_options", "between_opt", "1", TCL_GLOBAL_ONLY);
3780#endif
3781
drh13d70422004-11-13 15:59:14 +00003782#ifdef SQLITE_OMIT_BLOB_LITERAL
3783 Tcl_SetVar2(interp, "sqlite_options", "bloblit", "0", TCL_GLOBAL_ONLY);
3784#else
3785 Tcl_SetVar2(interp, "sqlite_options", "bloblit", "1", TCL_GLOBAL_ONLY);
3786#endif
3787
drh487e2622005-06-25 18:42:14 +00003788#ifdef SQLITE_OMIT_CAST
3789 Tcl_SetVar2(interp, "sqlite_options", "cast", "0", TCL_GLOBAL_ONLY);
3790#else
3791 Tcl_SetVar2(interp, "sqlite_options", "cast", "1", TCL_GLOBAL_ONLY);
3792#endif
3793
drhffe07b22005-11-03 00:41:17 +00003794#ifdef SQLITE_OMIT_CHECK
3795 Tcl_SetVar2(interp, "sqlite_options", "check", "0", TCL_GLOBAL_ONLY);
3796#else
3797 Tcl_SetVar2(interp, "sqlite_options", "check", "1", TCL_GLOBAL_ONLY);
3798#endif
3799
danielk1977deb802c2006-02-09 13:43:28 +00003800#ifdef SQLITE_ENABLE_COLUMN_METADATA
3801 Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "1", TCL_GLOBAL_ONLY);
3802#else
3803 Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "0", TCL_GLOBAL_ONLY);
3804#endif
3805
drhccae6022005-02-26 17:31:26 +00003806#ifdef SQLITE_OMIT_COMPLETE
3807 Tcl_SetVar2(interp, "sqlite_options", "complete", "0", TCL_GLOBAL_ONLY);
3808#else
3809 Tcl_SetVar2(interp, "sqlite_options", "complete", "1", TCL_GLOBAL_ONLY);
3810#endif
3811
drh13d70422004-11-13 15:59:14 +00003812#ifdef SQLITE_OMIT_COMPOUND_SELECT
3813 Tcl_SetVar2(interp, "sqlite_options", "compound", "0", TCL_GLOBAL_ONLY);
3814#else
3815 Tcl_SetVar2(interp, "sqlite_options", "compound", "1", TCL_GLOBAL_ONLY);
3816#endif
3817
3818#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
3819 Tcl_SetVar2(interp, "sqlite_options", "conflict", "0", TCL_GLOBAL_ONLY);
3820#else
3821 Tcl_SetVar2(interp, "sqlite_options", "conflict", "1", TCL_GLOBAL_ONLY);
3822#endif
3823
drh66560ad2006-01-06 14:32:19 +00003824#if OS_UNIX
3825 Tcl_SetVar2(interp, "sqlite_options", "crashtest", "1", TCL_GLOBAL_ONLY);
3826#else
3827 Tcl_SetVar2(interp, "sqlite_options", "crashtest", "0", TCL_GLOBAL_ONLY);
3828#endif
3829
drh13d70422004-11-13 15:59:14 +00003830#ifdef SQLITE_OMIT_DATETIME_FUNCS
3831 Tcl_SetVar2(interp, "sqlite_options", "datetime", "0", TCL_GLOBAL_ONLY);
3832#else
3833 Tcl_SetVar2(interp, "sqlite_options", "datetime", "1", TCL_GLOBAL_ONLY);
3834#endif
3835
drh2e66f0b2005-04-28 17:18:48 +00003836#ifdef SQLITE_OMIT_DISKIO
3837 Tcl_SetVar2(interp, "sqlite_options", "diskio", "0", TCL_GLOBAL_ONLY);
3838#else
3839 Tcl_SetVar2(interp, "sqlite_options", "diskio", "1", TCL_GLOBAL_ONLY);
3840#endif
3841
drh13d70422004-11-13 15:59:14 +00003842#ifdef SQLITE_OMIT_EXPLAIN
3843 Tcl_SetVar2(interp, "sqlite_options", "explain", "0", TCL_GLOBAL_ONLY);
3844#else
3845 Tcl_SetVar2(interp, "sqlite_options", "explain", "1", TCL_GLOBAL_ONLY);
3846#endif
3847
3848#ifdef SQLITE_OMIT_FLOATING_POINT
3849 Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "0", TCL_GLOBAL_ONLY);
3850#else
3851 Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "1", TCL_GLOBAL_ONLY);
3852#endif
3853
3854#ifdef SQLITE_OMIT_FOREIGN_KEY
3855 Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "0", TCL_GLOBAL_ONLY);
3856#else
3857 Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "1", TCL_GLOBAL_ONLY);
3858#endif
3859
drha2a9d182006-09-10 03:34:06 +00003860#ifdef SQLITE_ENABLE_FTS1
3861 Tcl_SetVar2(interp, "sqlite_options", "fts1", "1", TCL_GLOBAL_ONLY);
3862#else
3863 Tcl_SetVar2(interp, "sqlite_options", "fts1", "0", TCL_GLOBAL_ONLY);
3864#endif
3865
shessa26cf572006-10-19 20:27:58 +00003866#ifdef SQLITE_ENABLE_FTS2
3867 Tcl_SetVar2(interp, "sqlite_options", "fts2", "1", TCL_GLOBAL_ONLY);
3868#else
3869 Tcl_SetVar2(interp, "sqlite_options", "fts2", "0", TCL_GLOBAL_ONLY);
3870#endif
3871
danielk19776b456a22005-03-21 04:04:02 +00003872#ifdef SQLITE_OMIT_GLOBALRECOVER
3873 Tcl_SetVar2(interp, "sqlite_options", "globalrecover", "0", TCL_GLOBAL_ONLY);
3874#else
3875 Tcl_SetVar2(interp, "sqlite_options", "globalrecover", "1", TCL_GLOBAL_ONLY);
3876#endif
3877
drh13d70422004-11-13 15:59:14 +00003878#ifdef SQLITE_OMIT_INTEGRITY_CHECK
3879 Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
3880#else
3881 Tcl_SetVar2(interp, "sqlite_options", "integrityck", "1", TCL_GLOBAL_ONLY);
3882#endif
3883
drhff91c452006-06-27 12:51:12 +00003884#if defined(SQLITE_DEFAULT_FILE_FORMAT) && SQLITE_DEFAULT_FILE_FORMAT==1
3885 Tcl_SetVar2(interp, "sqlite_options", "legacyformat", "1", TCL_GLOBAL_ONLY);
3886#else
3887 Tcl_SetVar2(interp, "sqlite_options", "legacyformat", "0", TCL_GLOBAL_ONLY);
3888#endif
3889
drh55ef4d92005-08-14 01:20:37 +00003890#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
3891 Tcl_SetVar2(interp, "sqlite_options", "like_opt", "0", TCL_GLOBAL_ONLY);
3892#else
3893 Tcl_SetVar2(interp, "sqlite_options", "like_opt", "1", TCL_GLOBAL_ONLY);
3894#endif
3895
drh13d70422004-11-13 15:59:14 +00003896#ifdef SQLITE_OMIT_MEMORYDB
3897 Tcl_SetVar2(interp, "sqlite_options", "memorydb", "0", TCL_GLOBAL_ONLY);
3898#else
3899 Tcl_SetVar2(interp, "sqlite_options", "memorydb", "1", TCL_GLOBAL_ONLY);
3900#endif
3901
drh6f7adc82006-01-11 21:41:20 +00003902#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
drh6aafc292006-01-05 15:50:06 +00003903 Tcl_SetVar2(interp, "sqlite_options", "memorymanage", "1", TCL_GLOBAL_ONLY);
drh6f7adc82006-01-11 21:41:20 +00003904#else
3905 Tcl_SetVar2(interp, "sqlite_options", "memorymanage", "0", TCL_GLOBAL_ONLY);
drh6aafc292006-01-05 15:50:06 +00003906#endif
3907
drh55ef4d92005-08-14 01:20:37 +00003908#ifdef SQLITE_OMIT_OR_OPTIMIZATION
3909 Tcl_SetVar2(interp, "sqlite_options", "or_opt", "0", TCL_GLOBAL_ONLY);
3910#else
3911 Tcl_SetVar2(interp, "sqlite_options", "or_opt", "1", TCL_GLOBAL_ONLY);
3912#endif
3913
drh13d70422004-11-13 15:59:14 +00003914#ifdef SQLITE_OMIT_PAGER_PRAGMAS
3915 Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "0", TCL_GLOBAL_ONLY);
3916#else
3917 Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "1", TCL_GLOBAL_ONLY);
3918#endif
3919
drh2e66f0b2005-04-28 17:18:48 +00003920#ifdef SQLITE_OMIT_PARSER
3921 Tcl_SetVar2(interp, "sqlite_options", "parser", "0", TCL_GLOBAL_ONLY);
3922#else
3923 Tcl_SetVar2(interp, "sqlite_options", "parser", "1", TCL_GLOBAL_ONLY);
3924#endif
3925
drhbf216272005-02-26 18:10:44 +00003926#if defined(SQLITE_OMIT_PRAGMA) || defined(SQLITE_OMIT_FLAG_PRAGMAS)
drh13d70422004-11-13 15:59:14 +00003927 Tcl_SetVar2(interp, "sqlite_options", "pragma", "0", TCL_GLOBAL_ONLY);
3928 Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
3929#else
3930 Tcl_SetVar2(interp, "sqlite_options", "pragma", "1", TCL_GLOBAL_ONLY);
3931#endif
3932
3933#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
3934 Tcl_SetVar2(interp, "sqlite_options", "progress", "0", TCL_GLOBAL_ONLY);
3935#else
3936 Tcl_SetVar2(interp, "sqlite_options", "progress", "1", TCL_GLOBAL_ONLY);
3937#endif
3938
drh3f459022006-01-07 16:06:07 +00003939#ifdef SQLITE_ENABLE_REDEF_IO
3940 Tcl_SetVar2(interp, "sqlite_options", "redefio", "1", TCL_GLOBAL_ONLY);
3941#else
3942 Tcl_SetVar2(interp, "sqlite_options", "redefio", "0", TCL_GLOBAL_ONLY);
3943#endif
3944
drh13d70422004-11-13 15:59:14 +00003945#ifdef SQLITE_OMIT_REINDEX
3946 Tcl_SetVar2(interp, "sqlite_options", "reindex", "0", TCL_GLOBAL_ONLY);
3947#else
3948 Tcl_SetVar2(interp, "sqlite_options", "reindex", "1", TCL_GLOBAL_ONLY);
3949#endif
3950
3951#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
3952 Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "0", TCL_GLOBAL_ONLY);
3953#else
3954 Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "1", TCL_GLOBAL_ONLY);
3955#endif
3956
3957#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
3958 Tcl_SetVar2(interp, "sqlite_options", "schema_version", "0", TCL_GLOBAL_ONLY);
3959#else
3960 Tcl_SetVar2(interp, "sqlite_options", "schema_version", "1", TCL_GLOBAL_ONLY);
3961#endif
3962
danielk1977aef0bf62005-12-30 16:28:01 +00003963#ifdef SQLITE_OMIT_SHARED_CACHE
3964 Tcl_SetVar2(interp, "sqlite_options", "shared_cache", "0", TCL_GLOBAL_ONLY);
3965#else
3966 Tcl_SetVar2(interp, "sqlite_options", "shared_cache", "1", TCL_GLOBAL_ONLY);
3967#endif
3968
danielk19773e8c37e2005-01-21 03:12:14 +00003969#ifdef SQLITE_OMIT_SUBQUERY
3970 Tcl_SetVar2(interp, "sqlite_options", "subquery", "0", TCL_GLOBAL_ONLY);
3971#else
3972 Tcl_SetVar2(interp, "sqlite_options", "subquery", "1", TCL_GLOBAL_ONLY);
3973#endif
3974
drh13d70422004-11-13 15:59:14 +00003975#ifdef SQLITE_OMIT_TCL_VARIABLE
3976 Tcl_SetVar2(interp, "sqlite_options", "tclvar", "0", TCL_GLOBAL_ONLY);
3977#else
3978 Tcl_SetVar2(interp, "sqlite_options", "tclvar", "1", TCL_GLOBAL_ONLY);
3979#endif
3980
3981#if defined(THREADSAFE) && THREADSAFE
3982 Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "1", TCL_GLOBAL_ONLY);
3983#else
3984 Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "0", TCL_GLOBAL_ONLY);
3985#endif
3986
drh19e2d372005-08-29 23:00:03 +00003987#ifdef SQLITE_OMIT_TRACE
3988 Tcl_SetVar2(interp, "sqlite_options", "trace", "0", TCL_GLOBAL_ONLY);
3989#else
3990 Tcl_SetVar2(interp, "sqlite_options", "trace", "1", TCL_GLOBAL_ONLY);
3991#endif
3992
drh13d70422004-11-13 15:59:14 +00003993#ifdef SQLITE_OMIT_TRIGGER
3994 Tcl_SetVar2(interp, "sqlite_options", "trigger", "0", TCL_GLOBAL_ONLY);
3995#else
3996 Tcl_SetVar2(interp, "sqlite_options", "trigger", "1", TCL_GLOBAL_ONLY);
3997#endif
3998
danielk197753c0f742005-03-29 03:10:59 +00003999#ifdef SQLITE_OMIT_TEMPDB
4000 Tcl_SetVar2(interp, "sqlite_options", "tempdb", "0", TCL_GLOBAL_ONLY);
4001#else
4002 Tcl_SetVar2(interp, "sqlite_options", "tempdb", "1", TCL_GLOBAL_ONLY);
4003#endif
4004
drh13d70422004-11-13 15:59:14 +00004005#ifdef SQLITE_OMIT_UTF16
4006 Tcl_SetVar2(interp, "sqlite_options", "utf16", "0", TCL_GLOBAL_ONLY);
4007#else
4008 Tcl_SetVar2(interp, "sqlite_options", "utf16", "1", TCL_GLOBAL_ONLY);
4009#endif
4010
4011#ifdef SQLITE_OMIT_VACUUM
4012 Tcl_SetVar2(interp, "sqlite_options", "vacuum", "0", TCL_GLOBAL_ONLY);
4013#else
4014 Tcl_SetVar2(interp, "sqlite_options", "vacuum", "1", TCL_GLOBAL_ONLY);
4015#endif
4016
4017#ifdef SQLITE_OMIT_VIEW
4018 Tcl_SetVar2(interp, "sqlite_options", "view", "0", TCL_GLOBAL_ONLY);
4019#else
4020 Tcl_SetVar2(interp, "sqlite_options", "view", "1", TCL_GLOBAL_ONLY);
4021#endif
drhb9bb7c12006-06-11 23:41:55 +00004022
4023#ifdef SQLITE_OMIT_VIRTUALTABLE
4024 Tcl_SetVar2(interp, "sqlite_options", "vtab", "0", TCL_GLOBAL_ONLY);
4025#else
4026 Tcl_SetVar2(interp, "sqlite_options", "vtab", "1", TCL_GLOBAL_ONLY);
4027#endif
drh27d258a2004-10-30 20:23:09 +00004028}
4029
4030/*
drh80788d82006-09-02 14:50:23 +00004031** tclcmd: working_64bit_int
4032**
4033** Some TCL builds (ex: cygwin) do not support 64-bit integers. This
4034** leads to a number of test failures. The present command checks the
4035** TCL build to see whether or not it supports 64-bit integers. It
4036** returns TRUE if it does and FALSE if not.
4037**
4038** This command is used to warn users that their TCL build is defective
4039** and that the errors they are seeing in the test scripts might be
4040** a result of their defective TCL rather than problems in SQLite.
4041*/
4042static int working_64bit_int(
4043 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
4044 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
4045 int objc, /* Number of arguments */
4046 Tcl_Obj *CONST objv[] /* Command arguments */
4047){
4048 Tcl_Obj *pTestObj;
4049 int working = 0;
4050
4051 pTestObj = Tcl_NewWideIntObj(1000000*(i64)1234567890);
4052 working = strcmp(Tcl_GetString(pTestObj), "1234567890000000")==0;
4053 Tcl_DecrRefCount(pTestObj);
4054 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(working));
4055 return TCL_OK;
4056}
4057
4058
4059/*
drhd1bf3512001-04-07 15:24:33 +00004060** Register commands with the TCL interpreter.
4061*/
4062int Sqlitetest1_Init(Tcl_Interp *interp){
danielk19776f8a5032004-05-10 10:34:51 +00004063 extern int sqlite3_search_count;
4064 extern int sqlite3_interrupt_count;
4065 extern int sqlite3_open_file_count;
drh6bf89572004-11-03 16:27:01 +00004066 extern int sqlite3_sort_count;
danielk19776f8a5032004-05-10 10:34:51 +00004067 extern int sqlite3_current_time;
drhc2eef3b2002-08-31 18:53:06 +00004068 static struct {
4069 char *zName;
4070 Tcl_CmdProc *xProc;
4071 } aCmd[] = {
drhd3d39e92004-05-20 22:16:29 +00004072 { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int },
drhe9707672004-06-25 01:10:48 +00004073 { "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 },
drhd3d39e92004-05-20 22:16:29 +00004074 { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str },
drhe29b1a02004-07-17 21:56:09 +00004075 { "sqlite3_mprintf_stronly", (Tcl_CmdProc*)sqlite3_mprintf_stronly},
drhd3d39e92004-05-20 22:16:29 +00004076 { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double },
4077 { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled },
drh63782852005-08-30 19:30:59 +00004078 { "sqlite3_mprintf_hexdouble", (Tcl_CmdProc*)sqlite3_mprintf_hexdouble},
drhd3d39e92004-05-20 22:16:29 +00004079 { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z },
drh05a82982006-03-19 13:00:25 +00004080 { "sqlite3_mprintf_n_test", (Tcl_CmdProc*)test_mprintf_n },
drhd3d39e92004-05-20 22:16:29 +00004081 { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid },
4082 { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf },
drhb62c3352006-11-23 09:39:16 +00004083 { "sqlite3_exec", (Tcl_CmdProc*)test_exec },
4084 { "sqlite3_exec_nr", (Tcl_CmdProc*)test_exec_nr },
drhd3d39e92004-05-20 22:16:29 +00004085 { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf },
4086 { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close },
4087 { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function },
4088 { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate },
4089 { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func },
4090 { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort },
danielk19772c336542005-01-13 02:14:23 +00004091#ifdef SQLITE_MEMDEBUG
drhd3d39e92004-05-20 22:16:29 +00004092 { "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail },
4093 { "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat },
drhc2eef3b2002-08-31 18:53:06 +00004094#endif
drh25d65432004-07-22 15:02:25 +00004095 { "sqlite_bind", (Tcl_CmdProc*)test_bind },
4096 { "breakpoint", (Tcl_CmdProc*)test_breakpoint },
4097 { "sqlite3_key", (Tcl_CmdProc*)test_key },
4098 { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey },
drhcacb2082005-01-11 15:28:33 +00004099 { "sqlite_set_magic", (Tcl_CmdProc*)sqlite_set_magic },
drhc5cdca62005-01-11 16:54:14 +00004100 { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt },
drh3e1d8e62005-05-26 16:23:34 +00004101 { "sqlite_delete_function", (Tcl_CmdProc*)delete_function },
4102 { "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation },
4103 { "sqlite3_get_autocommit", (Tcl_CmdProc*)get_autocommit },
drh79158e12005-09-06 21:40:45 +00004104 { "sqlite3_stack_used", (Tcl_CmdProc*)test_stack_used },
drh30867652006-07-06 10:59:57 +00004105 { "sqlite3_busy_timeout", (Tcl_CmdProc*)test_busy_timeout },
drh3c23a882007-01-09 14:01:13 +00004106 { "printf", (Tcl_CmdProc*)test_printf },
drhc2eef3b2002-08-31 18:53:06 +00004107 };
danielk197751e3d8e2004-05-20 01:12:34 +00004108 static struct {
4109 char *zName;
4110 Tcl_ObjCmdProc *xProc;
danielk197704f2e682004-05-27 01:04:07 +00004111 void *clientData;
danielk197751e3d8e2004-05-20 01:12:34 +00004112 } aObjCmd[] = {
drhdddca282006-01-03 00:33:50 +00004113 { "sqlite3_connection_pointer", get_sqlite_pointer, 0 },
drh241db312004-06-22 12:46:53 +00004114 { "sqlite3_bind_int", test_bind_int, 0 },
4115 { "sqlite3_bind_int64", test_bind_int64, 0 },
4116 { "sqlite3_bind_double", test_bind_double, 0 },
danielk197704f2e682004-05-27 01:04:07 +00004117 { "sqlite3_bind_null", test_bind_null ,0 },
4118 { "sqlite3_bind_text", test_bind_text ,0 },
4119 { "sqlite3_bind_text16", test_bind_text16 ,0 },
4120 { "sqlite3_bind_blob", test_bind_blob ,0 },
drh75f6a032004-07-15 14:15:00 +00004121 { "sqlite3_bind_parameter_count", test_bind_parameter_count, 0},
drh895d7472004-08-20 16:02:39 +00004122 { "sqlite3_bind_parameter_name", test_bind_parameter_name, 0},
drhfa6bc002004-09-07 16:19:52 +00004123 { "sqlite3_bind_parameter_index", test_bind_parameter_index, 0},
danielk1977600dd0b2005-01-20 01:14:23 +00004124 { "sqlite3_clear_bindings", test_clear_bindings, 0},
drhf9cb7f52006-06-27 20:06:44 +00004125 { "sqlite3_sleep", test_sleep, 0},
danielk197704f2e682004-05-27 01:04:07 +00004126 { "sqlite3_errcode", test_errcode ,0 },
4127 { "sqlite3_errmsg", test_errmsg ,0 },
4128 { "sqlite3_errmsg16", test_errmsg16 ,0 },
4129 { "sqlite3_open", test_open ,0 },
4130 { "sqlite3_open16", test_open16 ,0 },
danielk1977bc6ada42004-06-30 08:20:16 +00004131 { "sqlite3_complete16", test_complete16 ,0 },
danielk197704f2e682004-05-27 01:04:07 +00004132
4133 { "sqlite3_prepare", test_prepare ,0 },
4134 { "sqlite3_prepare16", test_prepare16 ,0 },
drhb900aaf2006-11-09 00:24:53 +00004135 { "sqlite3_prepare_v2", test_prepare_v2 ,0 },
4136 { "sqlite3_prepare16_v2", test_prepare16_v2 ,0 },
danielk197704f2e682004-05-27 01:04:07 +00004137 { "sqlite3_finalize", test_finalize ,0 },
4138 { "sqlite3_reset", test_reset ,0 },
drhd89bd002005-01-22 03:03:54 +00004139 { "sqlite3_expired", test_expired ,0 },
drhf8db1bc2005-04-22 02:38:37 +00004140 { "sqlite3_transfer_bindings", test_transfer_bind ,0 },
danielk1977fbcd5852004-06-15 02:44:18 +00004141 { "sqlite3_changes", test_changes ,0 },
4142 { "sqlite3_step", test_step ,0 },
danielk197704f2e682004-05-27 01:04:07 +00004143
drhb4bc7052006-01-11 23:40:33 +00004144 { "sqlite3_release_memory", test_release_memory, 0},
4145 { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0},
4146 { "sqlite3_clear_tsd_memdebug", test_clear_tsd_memdebug, 0},
4147 { "sqlite3_tsd_release", test_tsd_release, 0},
4148 { "sqlite3_thread_cleanup", test_thread_cleanup, 0},
drh6aafc292006-01-05 15:50:06 +00004149
drhc2e87a32006-06-27 15:16:14 +00004150 { "sqlite3_load_extension", test_load_extension, 0},
4151 { "sqlite3_enable_load_extension", test_enable_load, 0},
drh4ac285a2006-09-15 07:28:50 +00004152 { "sqlite3_extended_result_codes", test_extended_result_codes, 0},
drhc2e87a32006-06-27 15:16:14 +00004153
danielk197704f2e682004-05-27 01:04:07 +00004154 /* sqlite3_column_*() API */
4155 { "sqlite3_column_count", test_column_count ,0 },
4156 { "sqlite3_data_count", test_data_count ,0 },
4157 { "sqlite3_column_type", test_column_type ,0 },
danielk1977ea61b2c2004-05-27 01:49:51 +00004158 { "sqlite3_column_blob", test_column_blob ,0 },
danielk197704f2e682004-05-27 01:04:07 +00004159 { "sqlite3_column_double", test_column_double ,0 },
4160 { "sqlite3_column_int64", test_column_int64 ,0 },
drh241db312004-06-22 12:46:53 +00004161 { "sqlite3_column_text", test_stmt_utf8, sqlite3_column_text },
4162 { "sqlite3_column_decltype", test_stmt_utf8, sqlite3_column_decltype },
4163 { "sqlite3_column_name", test_stmt_utf8, sqlite3_column_name },
drh6c626082004-11-14 21:56:29 +00004164 { "sqlite3_column_int", test_stmt_int, sqlite3_column_int },
4165 { "sqlite3_column_bytes", test_stmt_int, sqlite3_column_bytes },
danielk19774b1ae992006-02-10 03:06:10 +00004166#ifdef SQLITE_ENABLE_COLUMN_METADATA
danielk1977955de522006-02-10 02:27:42 +00004167{ "sqlite3_column_database_name", test_stmt_utf8, sqlite3_column_database_name},
4168{ "sqlite3_column_table_name", test_stmt_utf8, sqlite3_column_table_name},
4169{ "sqlite3_column_origin_name", test_stmt_utf8, sqlite3_column_origin_name},
danielk19774b1ae992006-02-10 03:06:10 +00004170#endif
danielk1977955de522006-02-10 02:27:42 +00004171
drh6c626082004-11-14 21:56:29 +00004172#ifndef SQLITE_OMIT_UTF16
4173 { "sqlite3_column_bytes16", test_stmt_int, sqlite3_column_bytes16 },
drh241db312004-06-22 12:46:53 +00004174 { "sqlite3_column_text16", test_stmt_utf16, sqlite3_column_text16 },
4175 { "sqlite3_column_decltype16", test_stmt_utf16, sqlite3_column_decltype16},
4176 { "sqlite3_column_name16", test_stmt_utf16, sqlite3_column_name16 },
drh7d9bd4e2006-02-16 18:16:36 +00004177 { "add_alignment_test_collations", add_alignment_test_collations, 0 },
danielk19774b1ae992006-02-10 03:06:10 +00004178#ifdef SQLITE_ENABLE_COLUMN_METADATA
danielk1977955de522006-02-10 02:27:42 +00004179{"sqlite3_column_database_name16",
4180 test_stmt_utf16, sqlite3_column_database_name16},
4181{"sqlite3_column_table_name16", test_stmt_utf16, sqlite3_column_table_name16},
4182{"sqlite3_column_origin_name16", test_stmt_utf16, sqlite3_column_origin_name16},
drh6c626082004-11-14 21:56:29 +00004183#endif
danielk19774b1ae992006-02-10 03:06:10 +00004184#endif
danielk19776b456a22005-03-21 04:04:02 +00004185 { "sqlite3_global_recover", test_global_recover, 0 },
drh80788d82006-09-02 14:50:23 +00004186 { "working_64bit_int", working_64bit_int, 0 },
danielk197704f2e682004-05-27 01:04:07 +00004187
danielk19779a1d0ab2004-06-01 14:09:28 +00004188 /* Functions from os.h */
danielk197744ee5bf2005-05-27 09:41:12 +00004189#ifndef SQLITE_OMIT_DISKIO
danielk19779a1d0ab2004-06-01 14:09:28 +00004190 { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 },
4191 { "sqlite3OsClose", test_sqlite3OsClose, 0 },
4192 { "sqlite3OsLock", test_sqlite3OsLock, 0 },
drhab3f9fe2004-08-14 17:10:10 +00004193 { "sqlite3OsTempFileName", test_sqlite3OsTempFileName, 0 },
danielk1977312d6b32004-06-29 13:18:23 +00004194
4195 /* Custom test interfaces */
4196 { "sqlite3OsUnlock", test_sqlite3OsUnlock, 0 },
danielk197744ee5bf2005-05-27 09:41:12 +00004197#endif
drh5436dc22004-11-14 04:04:17 +00004198#ifndef SQLITE_OMIT_UTF16
danielk1977312d6b32004-06-29 13:18:23 +00004199 { "add_test_collate", test_collate, 0 },
4200 { "add_test_collate_needed", test_collate_needed, 0 },
4201 { "add_test_function", test_function, 0 },
drh5436dc22004-11-14 04:04:17 +00004202#endif
danielk19775591df52005-12-20 09:19:37 +00004203#ifdef SQLITE_MEMDEBUG
4204 { "sqlite_malloc_outstanding", sqlite_malloc_outstanding, 0},
4205#endif
danielk1977312d6b32004-06-29 13:18:23 +00004206 { "sqlite3_test_errstr", test_errstr, 0 },
drh92febd92004-08-20 18:34:20 +00004207 { "tcl_variable_type", tcl_variable_type, 0 },
danielk1977aef0bf62005-12-30 16:28:01 +00004208#ifndef SQLITE_OMIT_SHARED_CACHE
drh6f7adc82006-01-11 21:41:20 +00004209 { "sqlite3_enable_shared_cache", test_enable_shared, 0 },
danielk1977aef0bf62005-12-30 16:28:01 +00004210#endif
danielk1977161fb792006-01-24 10:58:21 +00004211 { "sqlite3_libversion_number", test_libversion_number, 0 },
danielk1977deb802c2006-02-09 13:43:28 +00004212#ifdef SQLITE_ENABLE_COLUMN_METADATA
4213 { "sqlite3_table_column_metadata", test_table_column_metadata, 0 },
4214#endif
danielk197751e3d8e2004-05-20 01:12:34 +00004215 };
drh1398ad32005-01-19 23:24:50 +00004216 static int bitmask_size = sizeof(Bitmask)*8;
drhc2eef3b2002-08-31 18:53:06 +00004217 int i;
drh2ac3ee92004-06-07 16:27:46 +00004218 extern int sqlite3_os_trace;
drh51147ba2005-07-23 22:59:55 +00004219 extern int sqlite3_where_trace;
drhb851b2c2005-03-10 14:11:12 +00004220 extern int sqlite3_sync_count, sqlite3_fullsync_count;
drhaf6df112005-06-07 02:12:30 +00004221 extern int sqlite3_opentemp_count;
drh01397202005-07-20 14:31:53 +00004222 extern int sqlite3_memUsed;
danielk19772e588c72005-12-09 14:25:08 +00004223 extern int sqlite3_malloc_id;
drh01397202005-07-20 14:31:53 +00004224 extern int sqlite3_memMax;
drh55ef4d92005-08-14 01:20:37 +00004225 extern int sqlite3_like_count;
drhb4bc7052006-01-11 23:40:33 +00004226 extern int sqlite3_tsd_count;
drhdd735212007-02-24 13:53:05 +00004227 extern int sqlite3_xferopt_count;
drh029b44b2006-01-15 00:13:15 +00004228#if OS_UNIX && defined(SQLITE_TEST) && defined(THREADSAFE) && THREADSAFE
4229 extern int threadsOverrideEachOthersLocks;
4230#endif
drhc0929982005-09-05 19:08:29 +00004231#if OS_WIN
4232 extern int sqlite3_os_type;
4233#endif
drh8b3d9902005-08-19 00:14:42 +00004234#ifdef SQLITE_DEBUG
4235 extern int sqlite3_vdbe_addop_trace;
drh549c8b62005-09-19 13:15:23 +00004236#endif
4237#ifdef SQLITE_TEST
4238 extern char sqlite3_query_plan[];
drh9042f392005-07-15 23:24:23 +00004239 static char *query_plan = sqlite3_query_plan;
drh48083ce2005-09-19 12:37:27 +00004240#endif
drhc2eef3b2002-08-31 18:53:06 +00004241
4242 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
4243 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
4244 }
danielk197751e3d8e2004-05-20 01:12:34 +00004245 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
danielk1977c572ef72004-05-27 09:28:41 +00004246 Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
4247 aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
danielk197751e3d8e2004-05-20 01:12:34 +00004248 }
danielk19776490beb2004-05-11 06:17:21 +00004249 Tcl_LinkVar(interp, "sqlite_search_count",
danielk19776f8a5032004-05-10 10:34:51 +00004250 (char*)&sqlite3_search_count, TCL_LINK_INT);
drh6bf89572004-11-03 16:27:01 +00004251 Tcl_LinkVar(interp, "sqlite_sort_count",
4252 (char*)&sqlite3_sort_count, TCL_LINK_INT);
drh55ef4d92005-08-14 01:20:37 +00004253 Tcl_LinkVar(interp, "sqlite_like_count",
4254 (char*)&sqlite3_like_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00004255 Tcl_LinkVar(interp, "sqlite_interrupt_count",
danielk19776f8a5032004-05-10 10:34:51 +00004256 (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00004257 Tcl_LinkVar(interp, "sqlite_open_file_count",
danielk19776f8a5032004-05-10 10:34:51 +00004258 (char*)&sqlite3_open_file_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00004259 Tcl_LinkVar(interp, "sqlite_current_time",
danielk19776f8a5032004-05-10 10:34:51 +00004260 (char*)&sqlite3_current_time, TCL_LINK_INT);
drh2ac3ee92004-06-07 16:27:46 +00004261 Tcl_LinkVar(interp, "sqlite_os_trace",
4262 (char*)&sqlite3_os_trace, TCL_LINK_INT);
drhb4bc7052006-01-11 23:40:33 +00004263 Tcl_LinkVar(interp, "sqlite3_tsd_count",
4264 (char*)&sqlite3_tsd_count, TCL_LINK_INT);
drhdd735212007-02-24 13:53:05 +00004265 Tcl_LinkVar(interp, "sqlite3_xferopt_count",
4266 (char*)&sqlite3_xferopt_count, TCL_LINK_INT);
danielk19774b2688a2006-06-20 11:01:07 +00004267#ifndef SQLITE_OMIT_UTF16
drh7d9bd4e2006-02-16 18:16:36 +00004268 Tcl_LinkVar(interp, "unaligned_string_counter",
4269 (char*)&unaligned_string_counter, TCL_LINK_INT);
danielk19774b2688a2006-06-20 11:01:07 +00004270#endif
drh029b44b2006-01-15 00:13:15 +00004271#if OS_UNIX && defined(SQLITE_TEST) && defined(THREADSAFE) && THREADSAFE
4272 Tcl_LinkVar(interp, "threadsOverrideEachOthersLocks",
4273 (char*)&threadsOverrideEachOthersLocks, TCL_LINK_INT);
4274#endif
drh268803a2005-12-14 20:11:30 +00004275#ifndef SQLITE_OMIT_UTF16
4276 Tcl_LinkVar(interp, "sqlite_last_needed_collation",
4277 (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
4278#endif
danielk197797cb2e92005-12-09 14:39:04 +00004279#ifdef SQLITE_MEMDEBUG
danielk19772e588c72005-12-09 14:25:08 +00004280 Tcl_LinkVar(interp, "sqlite_malloc_id",
4281 (char*)&sqlite3_malloc_id, TCL_LINK_STRING);
danielk197797cb2e92005-12-09 14:39:04 +00004282#endif
drhc0929982005-09-05 19:08:29 +00004283#if OS_WIN
4284 Tcl_LinkVar(interp, "sqlite_os_type",
4285 (char*)&sqlite3_os_type, TCL_LINK_INT);
4286#endif
drh549c8b62005-09-19 13:15:23 +00004287#ifdef SQLITE_TEST
4288 Tcl_LinkVar(interp, "sqlite_query_plan",
4289 (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
4290#endif
drh8b3d9902005-08-19 00:14:42 +00004291#ifdef SQLITE_DEBUG
4292 Tcl_LinkVar(interp, "sqlite_addop_trace",
4293 (char*)&sqlite3_vdbe_addop_trace, TCL_LINK_INT);
drh48083ce2005-09-19 12:37:27 +00004294 Tcl_LinkVar(interp, "sqlite_where_trace",
4295 (char*)&sqlite3_where_trace, TCL_LINK_INT);
drh8b3d9902005-08-19 00:14:42 +00004296#endif
drh70180302005-08-02 21:42:16 +00004297#ifdef SQLITE_MEMDEBUG
drh01397202005-07-20 14:31:53 +00004298 Tcl_LinkVar(interp, "sqlite_memused",
4299 (char*)&sqlite3_memUsed, TCL_LINK_INT | TCL_LINK_READ_ONLY);
4300 Tcl_LinkVar(interp, "sqlite_memmax",
4301 (char*)&sqlite3_memMax, TCL_LINK_INT | TCL_LINK_READ_ONLY);
drh70180302005-08-02 21:42:16 +00004302#endif
danielk1977cbe21be2005-06-07 07:58:48 +00004303#ifndef SQLITE_OMIT_DISKIO
drhaf6df112005-06-07 02:12:30 +00004304 Tcl_LinkVar(interp, "sqlite_opentemp_count",
4305 (char*)&sqlite3_opentemp_count, TCL_LINK_INT);
danielk1977cbe21be2005-06-07 07:58:48 +00004306#endif
drh7c972de2003-09-06 22:18:07 +00004307 Tcl_LinkVar(interp, "sqlite_static_bind_value",
4308 (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
drhf0313812006-09-04 15:53:53 +00004309 Tcl_LinkVar(interp, "sqlite_static_bind_nbyte",
4310 (char*)&sqlite_static_bind_nbyte, TCL_LINK_INT);
drhab3f9fe2004-08-14 17:10:10 +00004311 Tcl_LinkVar(interp, "sqlite_temp_directory",
drheffd02b2004-08-29 23:42:13 +00004312 (char*)&sqlite3_temp_directory, TCL_LINK_STRING);
drh1398ad32005-01-19 23:24:50 +00004313 Tcl_LinkVar(interp, "bitmask_size",
4314 (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
drh748f7632005-03-11 04:41:39 +00004315#if OS_UNIX
drhb851b2c2005-03-10 14:11:12 +00004316 Tcl_LinkVar(interp, "sqlite_sync_count",
4317 (char*)&sqlite3_sync_count, TCL_LINK_INT);
4318 Tcl_LinkVar(interp, "sqlite_fullsync_count",
4319 (char*)&sqlite3_fullsync_count, TCL_LINK_INT);
drh748f7632005-03-11 04:41:39 +00004320#endif /* OS_UNIX */
drh27d258a2004-10-30 20:23:09 +00004321 set_options(interp);
danielk1977b82e7ed2006-01-11 14:09:31 +00004322
drhb4bc7052006-01-11 23:40:33 +00004323 {
danielk197707cb5602006-01-20 10:55:05 +00004324#ifdef SQLITE_DEBUG
drhb4bc7052006-01-11 23:40:33 +00004325 extern int sqlite3_shared_cache_report(void *, Tcl_Interp *,
4326 int, Tcl_Obj *CONST[]);
4327 Tcl_CreateObjCommand(interp, "sqlite_shared_cache_report",
4328 sqlite3_shared_cache_report, 0, 0);
danielk197707cb5602006-01-20 10:55:05 +00004329#endif
drhb4bc7052006-01-11 23:40:33 +00004330 }
drhd1bf3512001-04-07 15:24:33 +00004331 return TCL_OK;
4332}