blob: f960ef746c9336aca9668d6e57fd978955e3f998 [file] [log] [blame]
drhd1bf3512001-04-07 15:24:33 +00001/*
drhb19a2bc2001-09-16 00:13:26 +00002** 2001 September 15
drhd1bf3512001-04-07 15:24:33 +00003**
drhb19a2bc2001-09-16 00:13:26 +00004** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
drhd1bf3512001-04-07 15:24:33 +00006**
drhb19a2bc2001-09-16 00:13:26 +00007** May you do good and not evil.
8** May you find forgiveness for yourself and forgive others.
9** May you share freely, never taking more than you give.
drhd1bf3512001-04-07 15:24:33 +000010**
11*************************************************************************
12** Code for testing the printf() interface to SQLite. This code
13** is not included in the SQLite library. It is used for automated
14** testing of the SQLite library.
15**
drh6aafc292006-01-05 15:50:06 +000016** $Id: test1.c,v 1.180 2006/01/05 15:50:07 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
drh2e66f0b2005-04-28 17:18:48 +000066const char *sqlite3TestErrorName(int rc){
danielk19776622cce2004-05-20 11:00:52 +000067 const char *zName = 0;
68 switch( rc ){
69 case SQLITE_OK: zName = "SQLITE_OK"; break;
70 case SQLITE_ERROR: zName = "SQLITE_ERROR"; break;
danielk19776622cce2004-05-20 11:00:52 +000071 case SQLITE_PERM: zName = "SQLITE_PERM"; break;
72 case SQLITE_ABORT: zName = "SQLITE_ABORT"; break;
73 case SQLITE_BUSY: zName = "SQLITE_BUSY"; break;
74 case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break;
75 case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break;
76 case SQLITE_READONLY: zName = "SQLITE_READONLY"; break;
77 case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break;
78 case SQLITE_IOERR: zName = "SQLITE_IOERR"; break;
79 case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break;
danielk19776622cce2004-05-20 11:00:52 +000080 case SQLITE_FULL: zName = "SQLITE_FULL"; break;
81 case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break;
82 case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
83 case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break;
84 case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break;
danielk19776622cce2004-05-20 11:00:52 +000085 case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break;
86 case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break;
87 case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break;
88 case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break;
89 case SQLITE_AUTH: zName = "SQLITE_AUTH"; break;
90 case SQLITE_FORMAT: zName = "SQLITE_FORMAT"; break;
91 case SQLITE_RANGE: zName = "SQLITE_RANGE"; break;
92 case SQLITE_ROW: zName = "SQLITE_ROW"; break;
93 case SQLITE_DONE: zName = "SQLITE_DONE"; break;
drhc60d0442004-09-30 13:43:13 +000094 case SQLITE_NOTADB: zName = "SQLITE_NOTADB"; break;
danielk19776622cce2004-05-20 11:00:52 +000095 default: zName = "SQLITE_Unknown"; break;
96 }
97 return zName;
98}
drh2e66f0b2005-04-28 17:18:48 +000099#define errorName sqlite3TestErrorName
danielk19776622cce2004-05-20 11:00:52 +0000100
drhd1bf3512001-04-07 15:24:33 +0000101/*
drhc60d0442004-09-30 13:43:13 +0000102** Convert an sqlite3_stmt* into an sqlite3*. This depends on the
103** fact that the sqlite3* is the first field in the Vdbe structure.
104*/
drh51942bc2005-06-12 22:01:42 +0000105#define StmtToDb(X) sqlite3_db_handle(X)
drhc60d0442004-09-30 13:43:13 +0000106
107/*
108** Check a return value to make sure it agrees with the results
109** from sqlite3_errcode.
110*/
111int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){
112 if( rc!=SQLITE_MISUSE && rc!=SQLITE_OK && sqlite3_errcode(db)!=rc ){
113 char zBuf[200];
114 int r2 = sqlite3_errcode(db);
115 sprintf(zBuf, "error code %s (%d) does not match sqlite3_errcode %s (%d)",
116 errorName(rc), rc, errorName(r2), r2);
117 Tcl_ResetResult(interp);
118 Tcl_AppendResult(interp, zBuf, 0);
119 return 1;
120 }
121 return 0;
122}
123
124/*
drh9bb575f2004-09-06 17:24:11 +0000125** Decode a pointer to an sqlite3 object.
drhb86ccfb2003-01-28 23:13:10 +0000126*/
drh9bb575f2004-09-06 17:24:11 +0000127static int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
drhfe63d1c2004-09-08 20:13:04 +0000128 *ppDb = (sqlite3*)sqlite3TextToPtr(zA);
drhb86ccfb2003-01-28 23:13:10 +0000129 return TCL_OK;
130}
131
132/*
danielk197751e3d8e2004-05-20 01:12:34 +0000133** Decode a pointer to an sqlite3_stmt object.
134*/
135static int getStmtPointer(
136 Tcl_Interp *interp,
137 const char *zArg,
138 sqlite3_stmt **ppStmt
139){
drhfe63d1c2004-09-08 20:13:04 +0000140 *ppStmt = (sqlite3_stmt*)sqlite3TextToPtr(zArg);
danielk197751e3d8e2004-05-20 01:12:34 +0000141 return TCL_OK;
142}
143
144/*
danielk19779a1d0ab2004-06-01 14:09:28 +0000145** Decode a pointer to an sqlite3_stmt object.
146*/
147static int getFilePointer(
148 Tcl_Interp *interp,
149 const char *zArg,
150 OsFile **ppFile
151){
drhfe63d1c2004-09-08 20:13:04 +0000152 *ppFile = (OsFile*)sqlite3TextToPtr(zArg);
danielk19779a1d0ab2004-06-01 14:09:28 +0000153 return TCL_OK;
154}
155
156/*
drh7d8085a2003-04-26 13:19:38 +0000157** Generate a text representation of a pointer that can be understood
158** by the getDbPointer and getVmPointer routines above.
159**
160** The problem is, on some machines (Solaris) if you do a printf with
161** "%p" you cannot turn around and do a scanf with the same "%p" and
162** get your pointer back. You have to prepend a "0x" before it will
163** work. Or at least that is what is reported to me (drh). But this
164** behavior varies from machine to machine. The solution used her is
165** to test the string right after it is generated to see if it can be
166** understood by scanf, and if not, try prepending an "0x" to see if
167** that helps. If nothing works, a fatal error is generated.
168*/
169static int makePointerStr(Tcl_Interp *interp, char *zPtr, void *p){
drhfe63d1c2004-09-08 20:13:04 +0000170 sqlite3_snprintf(100, zPtr, "%p", p);
drh7d8085a2003-04-26 13:19:38 +0000171 return TCL_OK;
172}
173
174/*
danielk19776f8a5032004-05-10 10:34:51 +0000175** The callback routine for sqlite3_exec_printf().
drhd1bf3512001-04-07 15:24:33 +0000176*/
177static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){
178 Tcl_DString *str = (Tcl_DString*)pArg;
179 int i;
180
181 if( Tcl_DStringLength(str)==0 ){
182 for(i=0; i<argc; i++){
183 Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL");
184 }
185 }
186 for(i=0; i<argc; i++){
187 Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL");
188 }
189 return 0;
190}
191
192/*
danielk19776f8a5032004-05-10 10:34:51 +0000193** Usage: sqlite3_exec_printf DB FORMAT STRING
drhd1bf3512001-04-07 15:24:33 +0000194**
danielk19776f8a5032004-05-10 10:34:51 +0000195** Invoke the sqlite3_exec_printf() interface using the open database
drhd1bf3512001-04-07 15:24:33 +0000196** DB. The SQL is the string FORMAT. The format string should contain
197** one %s or %q. STRING is the value inserted into %s or %q.
198*/
199static int test_exec_printf(
200 void *NotUsed,
201 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
202 int argc, /* Number of arguments */
203 char **argv /* Text of each argument */
204){
drh9bb575f2004-09-06 17:24:11 +0000205 sqlite3 *db;
drhd1bf3512001-04-07 15:24:33 +0000206 Tcl_DString str;
207 int rc;
208 char *zErr = 0;
drh1211de32004-07-26 12:24:22 +0000209 char *zSql;
drhd1bf3512001-04-07 15:24:33 +0000210 char zBuf[30];
211 if( argc!=4 ){
212 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
213 " DB FORMAT STRING", 0);
214 return TCL_ERROR;
215 }
drhb86ccfb2003-01-28 23:13:10 +0000216 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000217 Tcl_DStringInit(&str);
drh1211de32004-07-26 12:24:22 +0000218 zSql = sqlite3_mprintf(argv[2], argv[3]);
219 rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
220 sqlite3_free(zSql);
drhd1bf3512001-04-07 15:24:33 +0000221 sprintf(zBuf, "%d", rc);
222 Tcl_AppendElement(interp, zBuf);
223 Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
224 Tcl_DStringFree(&str);
225 if( zErr ) free(zErr);
drhc60d0442004-09-30 13:43:13 +0000226 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000227 return TCL_OK;
228}
229
230/*
danielk19776f8a5032004-05-10 10:34:51 +0000231** Usage: sqlite3_mprintf_z_test SEPARATOR ARG0 ARG1 ...
drhd93d8a82003-06-16 03:08:18 +0000232**
233** Test the %z format of mprintf(). Use multiple mprintf() calls to
234** concatenate arg0 through argn using separator as the separator.
235** Return the result.
236*/
237static int test_mprintf_z(
238 void *NotUsed,
239 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
240 int argc, /* Number of arguments */
241 char **argv /* Text of each argument */
242){
243 char *zResult = 0;
244 int i;
245
246 for(i=2; i<argc; i++){
danielk19774adee202004-05-08 08:23:19 +0000247 zResult = sqlite3MPrintf("%z%s%s", zResult, argv[1], argv[i]);
drhd93d8a82003-06-16 03:08:18 +0000248 }
249 Tcl_AppendResult(interp, zResult, 0);
drh5f968432004-02-21 19:02:30 +0000250 sqliteFree(zResult);
drhd93d8a82003-06-16 03:08:18 +0000251 return TCL_OK;
252}
253
254/*
danielk19776f8a5032004-05-10 10:34:51 +0000255** Usage: sqlite3_get_table_printf DB FORMAT STRING
drhd1bf3512001-04-07 15:24:33 +0000256**
danielk19776f8a5032004-05-10 10:34:51 +0000257** Invoke the sqlite3_get_table_printf() interface using the open database
drhd1bf3512001-04-07 15:24:33 +0000258** DB. The SQL is the string FORMAT. The format string should contain
259** one %s or %q. STRING is the value inserted into %s or %q.
260*/
261static int test_get_table_printf(
262 void *NotUsed,
263 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
264 int argc, /* Number of arguments */
265 char **argv /* Text of each argument */
266){
drh9bb575f2004-09-06 17:24:11 +0000267 sqlite3 *db;
drhd1bf3512001-04-07 15:24:33 +0000268 Tcl_DString str;
269 int rc;
270 char *zErr = 0;
271 int nRow, nCol;
272 char **aResult;
273 int i;
274 char zBuf[30];
drh1211de32004-07-26 12:24:22 +0000275 char *zSql;
drhd1bf3512001-04-07 15:24:33 +0000276 if( argc!=4 ){
277 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
278 " DB FORMAT STRING", 0);
279 return TCL_ERROR;
280 }
drhb86ccfb2003-01-28 23:13:10 +0000281 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000282 Tcl_DStringInit(&str);
drh1211de32004-07-26 12:24:22 +0000283 zSql = sqlite3_mprintf(argv[2],argv[3]);
284 rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr);
285 sqlite3_free(zSql);
drhd1bf3512001-04-07 15:24:33 +0000286 sprintf(zBuf, "%d", rc);
287 Tcl_AppendElement(interp, zBuf);
288 if( rc==SQLITE_OK ){
289 sprintf(zBuf, "%d", nRow);
290 Tcl_AppendElement(interp, zBuf);
291 sprintf(zBuf, "%d", nCol);
292 Tcl_AppendElement(interp, zBuf);
293 for(i=0; i<(nRow+1)*nCol; i++){
294 Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL");
295 }
296 }else{
297 Tcl_AppendElement(interp, zErr);
298 }
danielk19776f8a5032004-05-10 10:34:51 +0000299 sqlite3_free_table(aResult);
drhd1bf3512001-04-07 15:24:33 +0000300 if( zErr ) free(zErr);
drhc60d0442004-09-30 13:43:13 +0000301 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000302 return TCL_OK;
303}
304
drhaf9ff332002-01-16 21:00:27 +0000305
306/*
danielk19776f8a5032004-05-10 10:34:51 +0000307** Usage: sqlite3_last_insert_rowid DB
drhaf9ff332002-01-16 21:00:27 +0000308**
309** Returns the integer ROWID of the most recent insert.
310*/
311static int test_last_rowid(
312 void *NotUsed,
313 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
314 int argc, /* Number of arguments */
315 char **argv /* Text of each argument */
316){
drh9bb575f2004-09-06 17:24:11 +0000317 sqlite3 *db;
drhaf9ff332002-01-16 21:00:27 +0000318 char zBuf[30];
319
320 if( argc!=2 ){
321 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0);
322 return TCL_ERROR;
323 }
drhb86ccfb2003-01-28 23:13:10 +0000324 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk1977c572ef72004-05-27 09:28:41 +0000325 sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db));
drhaf9ff332002-01-16 21:00:27 +0000326 Tcl_AppendResult(interp, zBuf, 0);
327 return SQLITE_OK;
328}
329
drhd1bf3512001-04-07 15:24:33 +0000330/*
drh25d65432004-07-22 15:02:25 +0000331** Usage: sqlite3_key DB KEY
332**
333** Set the codec key.
334*/
335static int test_key(
336 void *NotUsed,
337 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
338 int argc, /* Number of arguments */
339 char **argv /* Text of each argument */
340){
drh9bb575f2004-09-06 17:24:11 +0000341 sqlite3 *db;
drh25d65432004-07-22 15:02:25 +0000342 const char *zKey;
343 int nKey;
344 if( argc!=3 ){
345 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
346 " FILENAME\"", 0);
347 return TCL_ERROR;
348 }
349 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
350 zKey = argv[2];
351 nKey = strlen(zKey);
352#ifdef SQLITE_HAS_CODEC
353 sqlite3_key(db, zKey, nKey);
354#endif
355 return TCL_OK;
356}
357
358/*
359** Usage: sqlite3_rekey DB KEY
360**
361** Change the codec key.
362*/
363static int test_rekey(
364 void *NotUsed,
365 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
366 int argc, /* Number of arguments */
367 char **argv /* Text of each argument */
368){
drh9bb575f2004-09-06 17:24:11 +0000369 sqlite3 *db;
drh25d65432004-07-22 15:02:25 +0000370 const char *zKey;
371 int nKey;
372 if( argc!=3 ){
373 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
374 " FILENAME\"", 0);
375 return TCL_ERROR;
376 }
377 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
378 zKey = argv[2];
379 nKey = strlen(zKey);
380#ifdef SQLITE_HAS_CODEC
381 sqlite3_rekey(db, zKey, nKey);
382#endif
383 return TCL_OK;
384}
385
386/*
danielk19776f8a5032004-05-10 10:34:51 +0000387** Usage: sqlite3_close DB
drhd1bf3512001-04-07 15:24:33 +0000388**
danielk19776f8a5032004-05-10 10:34:51 +0000389** Closes the database opened by sqlite3_open.
drhd1bf3512001-04-07 15:24:33 +0000390*/
391static int sqlite_test_close(
392 void *NotUsed,
393 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
394 int argc, /* Number of arguments */
395 char **argv /* Text of each argument */
396){
drh9bb575f2004-09-06 17:24:11 +0000397 sqlite3 *db;
danielk197796d81f92004-06-19 03:33:57 +0000398 int rc;
drhd1bf3512001-04-07 15:24:33 +0000399 if( argc!=2 ){
400 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
401 " FILENAME\"", 0);
402 return TCL_ERROR;
403 }
drhb86ccfb2003-01-28 23:13:10 +0000404 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk197796d81f92004-06-19 03:33:57 +0000405 rc = sqlite3_close(db);
danielk1977f9d64d22004-06-19 08:18:07 +0000406 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
drhd1bf3512001-04-07 15:24:33 +0000407 return TCL_OK;
408}
409
410/*
drhc22bd472002-05-10 13:14:07 +0000411** Implementation of the x_coalesce() function.
412** Return the first argument non-NULL argument.
413*/
danielk19770ae8b832004-05-25 12:05:56 +0000414static void ifnullFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
drhc22bd472002-05-10 13:14:07 +0000415 int i;
416 for(i=0; i<argc; i++){
drh9c054832004-05-31 18:51:57 +0000417 if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
drh03d847e2005-12-09 20:21:58 +0000418 sqlite3_result_text(context, (char*)sqlite3_value_text(argv[i]),
drh5c434b72005-12-05 13:20:01 +0000419 sqlite3_value_bytes(argv[i]), SQLITE_TRANSIENT);
drhc22bd472002-05-10 13:14:07 +0000420 break;
421 }
422 }
423}
424
425/*
drhd1d9fc32004-01-07 19:24:48 +0000426** A structure into which to accumulate text.
427*/
428struct dstr {
429 int nAlloc; /* Space allocated */
430 int nUsed; /* Space used */
431 char *z; /* The space */
432};
433
434/*
435** Append text to a dstr
436*/
437static void dstrAppend(struct dstr *p, const char *z, int divider){
438 int n = strlen(z);
439 if( p->nUsed + n + 2 > p->nAlloc ){
440 char *zNew;
441 p->nAlloc = p->nAlloc*2 + n + 200;
442 zNew = sqliteRealloc(p->z, p->nAlloc);
443 if( zNew==0 ){
444 sqliteFree(p->z);
445 memset(p, 0, sizeof(*p));
446 return;
447 }
448 p->z = zNew;
449 }
450 if( divider && p->nUsed>0 ){
451 p->z[p->nUsed++] = divider;
452 }
453 memcpy(&p->z[p->nUsed], z, n+1);
454 p->nUsed += n;
455}
456
457/*
danielk19774adee202004-05-08 08:23:19 +0000458** Invoked for each callback from sqlite3ExecFunc
drhd1d9fc32004-01-07 19:24:48 +0000459*/
460static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){
461 struct dstr *p = (struct dstr*)pData;
462 int i;
463 for(i=0; i<argc; i++){
464 if( argv[i]==0 ){
465 dstrAppend(p, "NULL", ' ');
466 }else{
467 dstrAppend(p, argv[i], ' ');
468 }
469 }
470 return 0;
471}
472
473/*
danielk1977e35ee192004-06-26 09:50:11 +0000474** Implementation of the x_sqlite_exec() function. This function takes
drhc22bd472002-05-10 13:14:07 +0000475** a single argument and attempts to execute that argument as SQL code.
drh6cbe1f12002-07-01 00:31:36 +0000476** This is illegal and should set the SQLITE_MISUSE flag on the database.
drhd1d9fc32004-01-07 19:24:48 +0000477**
danielk19776f8a5032004-05-10 10:34:51 +0000478** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec()
drhd1d9fc32004-01-07 19:24:48 +0000479** from within a function call.
drhc22bd472002-05-10 13:14:07 +0000480**
481** This routine simulates the effect of having two threads attempt to
482** use the same database at the same time.
483*/
danielk197751ad0ec2004-05-24 12:39:02 +0000484static void sqlite3ExecFunc(
danielk19770ae8b832004-05-25 12:05:56 +0000485 sqlite3_context *context,
danielk197751ad0ec2004-05-24 12:39:02 +0000486 int argc,
487 sqlite3_value **argv
488){
drhd1d9fc32004-01-07 19:24:48 +0000489 struct dstr x;
490 memset(&x, 0, sizeof(x));
drh9bb575f2004-09-06 17:24:11 +0000491 sqlite3_exec((sqlite3*)sqlite3_user_data(context),
drh03d847e2005-12-09 20:21:58 +0000492 (char*)sqlite3_value_text(argv[0]),
drhd1d9fc32004-01-07 19:24:48 +0000493 execFuncCallback, &x, 0);
danielk1977d8123362004-06-12 09:25:12 +0000494 sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT);
drhd1d9fc32004-01-07 19:24:48 +0000495 sqliteFree(x.z);
drhc22bd472002-05-10 13:14:07 +0000496}
497
498/*
499** Usage: sqlite_test_create_function DB
500**
danielk19776f8a5032004-05-10 10:34:51 +0000501** Call the sqlite3_create_function API on the given database in order
drhc22bd472002-05-10 13:14:07 +0000502** to create a function named "x_coalesce". This function does the same thing
503** as the "coalesce" function. This function also registers an SQL function
danielk1977e35ee192004-06-26 09:50:11 +0000504** named "x_sqlite_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec()
drhc22bd472002-05-10 13:14:07 +0000505** in this way is illegal recursion and should raise an SQLITE_MISUSE error.
506** The effect is similar to trying to use the same database connection from
507** two threads at the same time.
508**
509** The original motivation for this routine was to be able to call the
danielk19776f8a5032004-05-10 10:34:51 +0000510** sqlite3_create_function function while a query is in progress in order
drhc22bd472002-05-10 13:14:07 +0000511** to test the SQLITE_MISUSE detection logic.
512*/
drhc2eef3b2002-08-31 18:53:06 +0000513static int test_create_function(
drhc22bd472002-05-10 13:14:07 +0000514 void *NotUsed,
515 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
516 int argc, /* Number of arguments */
517 char **argv /* Text of each argument */
518){
drhc60d0442004-09-30 13:43:13 +0000519 int rc;
drh9bb575f2004-09-06 17:24:11 +0000520 sqlite3 *db;
drh9bb575f2004-09-06 17:24:11 +0000521 extern void Md5_Register(sqlite3*);
danielk1977312d6b32004-06-29 13:18:23 +0000522
drhc22bd472002-05-10 13:14:07 +0000523 if( argc!=2 ){
524 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
danielk19774397de52005-01-12 12:44:03 +0000525 " DB\"", 0);
drhc22bd472002-05-10 13:14:07 +0000526 return TCL_ERROR;
527 }
drhb86ccfb2003-01-28 23:13:10 +0000528 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +0000529 rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0,
530 ifnullFunc, 0, 0);
danielk1977312d6b32004-06-29 13:18:23 +0000531
drh5436dc22004-11-14 04:04:17 +0000532#ifndef SQLITE_OMIT_UTF16
danielk1977312d6b32004-06-29 13:18:23 +0000533 /* Use the sqlite3_create_function16() API here. Mainly for fun, but also
534 ** because it is not tested anywhere else. */
drhc60d0442004-09-30 13:43:13 +0000535 if( rc==SQLITE_OK ){
danielk1977576ec6b2005-01-21 11:55:25 +0000536 sqlite3_value *pVal;
drhc60d0442004-09-30 13:43:13 +0000537 pVal = sqlite3ValueNew();
538 sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC);
539 rc = sqlite3_create_function16(db,
540 sqlite3ValueText(pVal, SQLITE_UTF16NATIVE),
541 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
542 sqlite3ValueFree(pVal);
543 }
drh5436dc22004-11-14 04:04:17 +0000544#endif
545
drhc60d0442004-09-30 13:43:13 +0000546 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk19774397de52005-01-12 12:44:03 +0000547 Tcl_SetResult(interp, (char *)errorName(rc), 0);
drhc22bd472002-05-10 13:14:07 +0000548 return TCL_OK;
549}
550
551/*
552** Routines to implement the x_count() aggregate function.
553*/
554typedef struct CountCtx CountCtx;
555struct CountCtx {
556 int n;
557};
danielk19770ae8b832004-05-25 12:05:56 +0000558static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
drhc22bd472002-05-10 13:14:07 +0000559 CountCtx *p;
drh4f26d6c2004-05-26 23:25:30 +0000560 p = sqlite3_aggregate_context(context, sizeof(*p));
drh9c054832004-05-31 18:51:57 +0000561 if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){
drhc22bd472002-05-10 13:14:07 +0000562 p->n++;
563 }
564}
danielk19770ae8b832004-05-25 12:05:56 +0000565static void countFinalize(sqlite3_context *context){
drhc22bd472002-05-10 13:14:07 +0000566 CountCtx *p;
drh4f26d6c2004-05-26 23:25:30 +0000567 p = sqlite3_aggregate_context(context, sizeof(*p));
danielk1977c572ef72004-05-27 09:28:41 +0000568 sqlite3_result_int(context, p ? p->n : 0);
drhc22bd472002-05-10 13:14:07 +0000569}
570
571/*
572** Usage: sqlite_test_create_aggregate DB
573**
danielk19776f8a5032004-05-10 10:34:51 +0000574** Call the sqlite3_create_function API on the given database in order
drhc22bd472002-05-10 13:14:07 +0000575** to create a function named "x_count". This function does the same thing
576** as the "md5sum" function.
577**
578** The original motivation for this routine was to be able to call the
danielk19776f8a5032004-05-10 10:34:51 +0000579** sqlite3_create_aggregate function while a query is in progress in order
drhc22bd472002-05-10 13:14:07 +0000580** to test the SQLITE_MISUSE detection logic.
581*/
drhc2eef3b2002-08-31 18:53:06 +0000582static int test_create_aggregate(
drhc22bd472002-05-10 13:14:07 +0000583 void *NotUsed,
584 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
585 int argc, /* Number of arguments */
586 char **argv /* Text of each argument */
587){
drh9bb575f2004-09-06 17:24:11 +0000588 sqlite3 *db;
drhc60d0442004-09-30 13:43:13 +0000589 int rc;
drhc22bd472002-05-10 13:14:07 +0000590 if( argc!=2 ){
591 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
592 " FILENAME\"", 0);
593 return TCL_ERROR;
594 }
drhb86ccfb2003-01-28 23:13:10 +0000595 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +0000596 rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0,
danielk1977d8123362004-06-12 09:25:12 +0000597 countStep,countFinalize);
drhc60d0442004-09-30 13:43:13 +0000598 if( rc==SQLITE_OK ){
599 sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0,
600 countStep,countFinalize);
601 }
602 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drhc22bd472002-05-10 13:14:07 +0000603 return TCL_OK;
604}
605
606
607
608/*
danielk19776f8a5032004-05-10 10:34:51 +0000609** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER
drhd1bf3512001-04-07 15:24:33 +0000610**
611** Call mprintf with three integer arguments
612*/
danielk19776f8a5032004-05-10 10:34:51 +0000613static int sqlite3_mprintf_int(
drhd1bf3512001-04-07 15:24:33 +0000614 void *NotUsed,
615 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
616 int argc, /* Number of arguments */
617 char **argv /* Text of each argument */
618){
619 int a[3], i;
620 char *z;
621 if( argc!=5 ){
622 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
623 " FORMAT INT INT INT\"", 0);
624 return TCL_ERROR;
625 }
626 for(i=2; i<5; i++){
627 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
628 }
danielk19776f8a5032004-05-10 10:34:51 +0000629 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
drhd1bf3512001-04-07 15:24:33 +0000630 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000631 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +0000632 return TCL_OK;
633}
634
635/*
drh9d213ef2004-06-30 04:02:11 +0000636** If zNum represents an integer that will fit in 64-bits, then set
637** *pValue to that integer and return true. Otherwise return false.
638*/
639static int sqlite3GetInt64(const char *zNum, i64 *pValue){
640 if( sqlite3FitsIn64Bits(zNum) ){
641 sqlite3atoi64(zNum, pValue);
642 return 1;
643 }
644 return 0;
645}
646
647/*
drhe9707672004-06-25 01:10:48 +0000648** Usage: sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER
649**
650** Call mprintf with three 64-bit integer arguments
651*/
652static int sqlite3_mprintf_int64(
653 void *NotUsed,
654 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
655 int argc, /* Number of arguments */
656 char **argv /* Text of each argument */
657){
658 int i;
659 sqlite_int64 a[3];
660 char *z;
661 if( argc!=5 ){
662 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
663 " FORMAT INT INT INT\"", 0);
664 return TCL_ERROR;
665 }
666 for(i=2; i<5; i++){
667 if( !sqlite3GetInt64(argv[i], &a[i-2]) ){
668 Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0);
669 return TCL_ERROR;
670 }
671 }
672 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
673 Tcl_AppendResult(interp, z, 0);
674 sqlite3_free(z);
675 return TCL_OK;
676}
677
678/*
danielk19776f8a5032004-05-10 10:34:51 +0000679** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING
drhd1bf3512001-04-07 15:24:33 +0000680**
681** Call mprintf with two integer arguments and one string argument
682*/
danielk19776f8a5032004-05-10 10:34:51 +0000683static int sqlite3_mprintf_str(
drhd1bf3512001-04-07 15:24:33 +0000684 void *NotUsed,
685 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
686 int argc, /* Number of arguments */
687 char **argv /* Text of each argument */
688){
689 int a[3], i;
690 char *z;
chwf220b242002-06-16 04:54:28 +0000691 if( argc<4 || argc>5 ){
drhd1bf3512001-04-07 15:24:33 +0000692 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
chwf220b242002-06-16 04:54:28 +0000693 " FORMAT INT INT ?STRING?\"", 0);
drhd1bf3512001-04-07 15:24:33 +0000694 return TCL_ERROR;
695 }
696 for(i=2; i<4; i++){
697 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
698 }
danielk19776f8a5032004-05-10 10:34:51 +0000699 z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL);
drhd1bf3512001-04-07 15:24:33 +0000700 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000701 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +0000702 return TCL_OK;
703}
704
705/*
drh63782852005-08-30 19:30:59 +0000706** Usage: sqlite3_mprintf_double FORMAT INTEGER INTEGER DOUBLE
drhd1bf3512001-04-07 15:24:33 +0000707**
708** Call mprintf with two integer arguments and one double argument
709*/
danielk19776f8a5032004-05-10 10:34:51 +0000710static int sqlite3_mprintf_double(
drhd1bf3512001-04-07 15:24:33 +0000711 void *NotUsed,
712 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
713 int argc, /* Number of arguments */
714 char **argv /* Text of each argument */
715){
716 int a[3], i;
717 double r;
718 char *z;
719 if( argc!=5 ){
720 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
drh63782852005-08-30 19:30:59 +0000721 " FORMAT INT INT DOUBLE\"", 0);
drhd1bf3512001-04-07 15:24:33 +0000722 return TCL_ERROR;
723 }
724 for(i=2; i<4; i++){
725 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
726 }
727 if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
danielk19776f8a5032004-05-10 10:34:51 +0000728 z = sqlite3_mprintf(argv[1], a[0], a[1], r);
drhd1bf3512001-04-07 15:24:33 +0000729 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000730 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +0000731 return TCL_OK;
732}
733
734/*
drh63782852005-08-30 19:30:59 +0000735** Usage: sqlite3_mprintf_scaled FORMAT DOUBLE DOUBLE
drhb621c232004-02-21 19:41:04 +0000736**
737** Call mprintf with a single double argument which is the product of the
738** two arguments given above. This is used to generate overflow and underflow
739** doubles to test that they are converted properly.
740*/
danielk19776f8a5032004-05-10 10:34:51 +0000741static int sqlite3_mprintf_scaled(
drhb621c232004-02-21 19:41:04 +0000742 void *NotUsed,
743 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
744 int argc, /* Number of arguments */
745 char **argv /* Text of each argument */
746){
747 int i;
748 double r[2];
749 char *z;
750 if( argc!=4 ){
751 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
752 " FORMAT DOUBLE DOUBLE\"", 0);
753 return TCL_ERROR;
754 }
755 for(i=2; i<4; i++){
756 if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR;
757 }
danielk19776f8a5032004-05-10 10:34:51 +0000758 z = sqlite3_mprintf(argv[1], r[0]*r[1]);
drhb621c232004-02-21 19:41:04 +0000759 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000760 sqlite3_free(z);
drhb621c232004-02-21 19:41:04 +0000761 return TCL_OK;
762}
763
764/*
drhe29b1a02004-07-17 21:56:09 +0000765** Usage: sqlite3_mprintf_stronly FORMAT STRING
766**
767** Call mprintf with a single double argument which is the product of the
768** two arguments given above. This is used to generate overflow and underflow
769** doubles to test that they are converted properly.
770*/
771static int sqlite3_mprintf_stronly(
772 void *NotUsed,
773 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
774 int argc, /* Number of arguments */
775 char **argv /* Text of each argument */
776){
777 char *z;
778 if( argc!=3 ){
779 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
780 " FORMAT STRING\"", 0);
781 return TCL_ERROR;
782 }
783 z = sqlite3_mprintf(argv[1], argv[2]);
784 Tcl_AppendResult(interp, z, 0);
785 sqlite3_free(z);
786 return TCL_OK;
787}
788
789/*
drh63782852005-08-30 19:30:59 +0000790** Usage: sqlite3_mprintf_hexdouble FORMAT HEX
791**
792** Call mprintf with a single double argument which is derived from the
793** hexadecimal encoding of an IEEE double.
794*/
795static int sqlite3_mprintf_hexdouble(
796 void *NotUsed,
797 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
798 int argc, /* Number of arguments */
799 char **argv /* Text of each argument */
800){
801 char *z;
802 double r;
803 unsigned x1, x2;
804 long long unsigned d;
805 if( argc!=3 ){
806 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
807 " FORMAT STRING\"", 0);
808 return TCL_ERROR;
809 }
810 if( sscanf(argv[2], "%08x%08x", &x2, &x1)!=2 ){
811 Tcl_AppendResult(interp, "2nd argument should be 16-characters of hex", 0);
812 return TCL_ERROR;
813 }
814 d = x2;
815 d = (d<<32) + x1;
816 memcpy(&r, &d, sizeof(r));
817 z = sqlite3_mprintf(argv[1], r);
818 Tcl_AppendResult(interp, z, 0);
819 sqlite3_free(z);
820 return TCL_OK;
821}
822
823/*
drh46934232004-11-20 19:18:00 +0000824** Usage: sqlite_malloc_fail N ?REPEAT-INTERVAL?
drhdaffd0e2001-04-11 14:28:42 +0000825**
drh46934232004-11-20 19:18:00 +0000826** Rig sqliteMalloc() to fail on the N-th call and every REPEAT-INTERVAL call
827** after that. If REPEAT-INTERVAL is 0 or is omitted, then only a single
828** malloc will fail. If REPEAT-INTERVAL is 1 then all mallocs after the
829** first failure will continue to fail on every call. If REPEAT-INTERVAL is
830** 2 then every other malloc will fail. And so forth.
831**
danielk1977261919c2005-12-06 12:52:59 +0000832** Turn off this mechanism and reset the sqlite3Tsd()->mallocFailed variable is N==0.
drhdaffd0e2001-04-11 14:28:42 +0000833*/
danielk19772c336542005-01-13 02:14:23 +0000834#ifdef SQLITE_MEMDEBUG
drhdaffd0e2001-04-11 14:28:42 +0000835static int sqlite_malloc_fail(
836 void *NotUsed,
837 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
838 int argc, /* Number of arguments */
839 char **argv /* Text of each argument */
840){
841 int n;
drh46934232004-11-20 19:18:00 +0000842 int rep;
843 if( argc!=2 && argc!=3 ){
drhdaffd0e2001-04-11 14:28:42 +0000844 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0);
845 return TCL_ERROR;
846 }
847 if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
drh46934232004-11-20 19:18:00 +0000848 if( argc==3 ){
849 if( Tcl_GetInt(interp, argv[2], &rep) ) return TCL_ERROR;
850 }else{
851 rep = 0;
852 }
danielk19776f8a5032004-05-10 10:34:51 +0000853 sqlite3_iMallocFail = n;
drh46934232004-11-20 19:18:00 +0000854 sqlite3_iMallocReset = rep;
drhdaffd0e2001-04-11 14:28:42 +0000855 return TCL_OK;
856}
857#endif
858
859/*
860** Usage: sqlite_malloc_stat
861**
862** Return the number of prior calls to sqliteMalloc() and sqliteFree().
863*/
danielk19772c336542005-01-13 02:14:23 +0000864#ifdef SQLITE_MEMDEBUG
drhdaffd0e2001-04-11 14:28:42 +0000865static int sqlite_malloc_stat(
866 void *NotUsed,
867 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
868 int argc, /* Number of arguments */
869 char **argv /* Text of each argument */
870){
871 char zBuf[200];
danielk19775591df52005-12-20 09:19:37 +0000872 sprintf(zBuf, "%d %d %d", sqlite3_nMalloc,sqlite3_nFree,sqlite3_iMallocFail);
drhdaffd0e2001-04-11 14:28:42 +0000873 Tcl_AppendResult(interp, zBuf, 0);
874 return TCL_OK;
875}
danielk19775591df52005-12-20 09:19:37 +0000876
877/*
878** This function implements a Tcl command that may be invoked using any of
879** the four forms enumerated below.
880**
881** sqlite_malloc_outstanding
882** Return a summary of all unfreed blocks of memory allocated by the
883** current thread. See comments above function sqlite3OutstandingMallocs()
884** in util.c for a description of the returned value.
885**
886** sqlite_malloc_outstanding -bytes
887** Return the total amount of unfreed memory (in bytes) allocated by
888** this thread.
889**
890** sqlite_malloc_outstanding -maxbytes
891** Return the maximum amount of dynamic memory in use at one time
892** by this thread.
893**
894** sqlite_malloc_outstanding -clearmaxbytes
895** Set the value returned by [sqlite_malloc_outstanding -maxbytes]
896** to the current value of [sqlite_malloc_outstanding -bytes].
897*/
danielk19772e588c72005-12-09 14:25:08 +0000898static int sqlite_malloc_outstanding(
danielk19775591df52005-12-20 09:19:37 +0000899 ClientData clientData,
danielk19772e588c72005-12-09 14:25:08 +0000900 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
danielk19775591df52005-12-20 09:19:37 +0000901 int objc, /* Number of arguments */
902 Tcl_Obj *CONST objv[] /* Command arguments */
danielk19772e588c72005-12-09 14:25:08 +0000903){
904 extern int sqlite3OutstandingMallocs(Tcl_Interp *interp);
danielk19775591df52005-12-20 09:19:37 +0000905
906 if( objc!=1 && objc!=2 ){
907 Tcl_WrongNumArgs(interp, 1, objv, "?-bytes?");
908 return TCL_ERROR;
909 }
910
911 if( objc==2 ){
912 const char *zArg = Tcl_GetString(objv[1]);
913 if( 0==strcmp(zArg, "-bytes") ){
914 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3Tsd()->nAlloc));
915#ifndef SQLITE_OMIT_MEMORY_MANAGEMENT
916 }else if( 0==strcmp(zArg, "-maxbytes") ){
917 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sqlite3Tsd()->nMaxAlloc));
918 }else if( 0==strcmp(zArg, "-clearmaxbytes") ){
919 sqlite3Tsd()->nMaxAlloc = sqlite3Tsd()->nAlloc;
920#endif
921 }else{
922 Tcl_AppendResult(interp, "bad option \"", zArg,
923 "\": must be -bytes, -maxbytes or -clearmaxbytes", 0
924 );
925 return TCL_ERROR;
926 }
927
928 return TCL_OK;
929 }
930
danielk19772e588c72005-12-09 14:25:08 +0000931 return sqlite3OutstandingMallocs(interp);
932}
drhdaffd0e2001-04-11 14:28:42 +0000933#endif
934
935/*
danielk1977aef0bf62005-12-30 16:28:01 +0000936** Usage: sqlite3_enable_shared_cache BOOLEAN
937**
938*/
939#ifndef SQLITE_OMIT_SHARED_CACHE
940static int test_enable_shared_cache(
941 ClientData clientData,
942 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
943 int objc, /* Number of arguments */
944 Tcl_Obj *CONST objv[] /* Command arguments */
945){
946 int rc;
947 int enable;
948 SqliteTsd *pTsd = sqlite3Tsd();
949 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(pTsd->useSharedData));
950
951 if( objc!=2 ){
952 Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
953 return TCL_ERROR;
954 }
955 if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){
956 return TCL_ERROR;
957 }
958 rc = sqlite3_enable_shared_cache(enable);
959 if( rc!=SQLITE_OK ){
960 Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
961 return TCL_ERROR;
962 }
963 return TCL_OK;
964}
965#endif
966
967/*
drh28b4e482002-03-11 02:06:13 +0000968** Usage: sqlite_abort
969**
970** Shutdown the process immediately. This is not a clean shutdown.
971** This command is used to test the recoverability of a database in
972** the event of a program crash.
973*/
974static int sqlite_abort(
975 void *NotUsed,
976 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
977 int argc, /* Number of arguments */
978 char **argv /* Text of each argument */
979){
980 assert( interp==0 ); /* This will always fail */
981 return TCL_OK;
982}
983
984/*
drh6cbe1f12002-07-01 00:31:36 +0000985** The following routine is a user-defined SQL function whose purpose
986** is to test the sqlite_set_result() API.
987*/
danielk19770ae8b832004-05-25 12:05:56 +0000988static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
drh6cbe1f12002-07-01 00:31:36 +0000989 while( argc>=2 ){
drh03d847e2005-12-09 20:21:58 +0000990 const char *zArg0 = (char*)sqlite3_value_text(argv[0]);
danielk19776d88bad2004-05-27 14:23:36 +0000991 if( zArg0 ){
992 if( 0==sqlite3StrICmp(zArg0, "int") ){
993 sqlite3_result_int(context, sqlite3_value_int(argv[1]));
994 }else if( sqlite3StrICmp(zArg0,"int64")==0 ){
995 sqlite3_result_int64(context, sqlite3_value_int64(argv[1]));
996 }else if( sqlite3StrICmp(zArg0,"string")==0 ){
drh03d847e2005-12-09 20:21:58 +0000997 sqlite3_result_text(context, (char*)sqlite3_value_text(argv[1]), -1,
danielk1977d8123362004-06-12 09:25:12 +0000998 SQLITE_TRANSIENT);
danielk19776d88bad2004-05-27 14:23:36 +0000999 }else if( sqlite3StrICmp(zArg0,"double")==0 ){
1000 sqlite3_result_double(context, sqlite3_value_double(argv[1]));
1001 }else if( sqlite3StrICmp(zArg0,"null")==0 ){
1002 sqlite3_result_null(context);
1003 }else if( sqlite3StrICmp(zArg0,"value")==0 ){
1004 sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]);
1005 }else{
1006 goto error_out;
1007 }
drh6cbe1f12002-07-01 00:31:36 +00001008 }else{
danielk19776d88bad2004-05-27 14:23:36 +00001009 goto error_out;
drh6cbe1f12002-07-01 00:31:36 +00001010 }
1011 argc -= 2;
1012 argv += 2;
1013 }
danielk19776d88bad2004-05-27 14:23:36 +00001014 return;
1015
1016error_out:
1017 sqlite3_result_error(context,"first argument should be one of: "
1018 "int int64 string double null value", -1);
drh6cbe1f12002-07-01 00:31:36 +00001019}
1020
1021/*
1022** Usage: sqlite_register_test_function DB NAME
1023**
1024** Register the test SQL function on the database DB under the name NAME.
1025*/
drhc2eef3b2002-08-31 18:53:06 +00001026static int test_register_func(
drh6cbe1f12002-07-01 00:31:36 +00001027 void *NotUsed,
1028 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1029 int argc, /* Number of arguments */
1030 char **argv /* Text of each argument */
1031){
drh9bb575f2004-09-06 17:24:11 +00001032 sqlite3 *db;
drh6cbe1f12002-07-01 00:31:36 +00001033 int rc;
1034 if( argc!=3 ){
1035 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1036 " DB FUNCTION-NAME", 0);
1037 return TCL_ERROR;
1038 }
drhb86ccfb2003-01-28 23:13:10 +00001039 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk1977f9d64d22004-06-19 08:18:07 +00001040 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0,
danielk1977d8123362004-06-12 09:25:12 +00001041 testFunc, 0, 0);
drh6cbe1f12002-07-01 00:31:36 +00001042 if( rc!=0 ){
danielk1977f20b21c2004-05-31 23:56:42 +00001043 Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);
drh6cbe1f12002-07-01 00:31:36 +00001044 return TCL_ERROR;
1045 }
drhc60d0442004-09-30 13:43:13 +00001046 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drh6cbe1f12002-07-01 00:31:36 +00001047 return TCL_OK;
1048}
1049
1050/*
danielk1977106bb232004-05-21 10:08:53 +00001051** Usage: sqlite3_finalize STMT
drhb86ccfb2003-01-28 23:13:10 +00001052**
danielk1977106bb232004-05-21 10:08:53 +00001053** Finalize a statement handle.
drhb86ccfb2003-01-28 23:13:10 +00001054*/
1055static int test_finalize(
danielk1977106bb232004-05-21 10:08:53 +00001056 void * clientData,
1057 Tcl_Interp *interp,
1058 int objc,
1059 Tcl_Obj *CONST objv[]
drhb86ccfb2003-01-28 23:13:10 +00001060){
danielk1977106bb232004-05-21 10:08:53 +00001061 sqlite3_stmt *pStmt;
drhb86ccfb2003-01-28 23:13:10 +00001062 int rc;
drhc60d0442004-09-30 13:43:13 +00001063 sqlite3 *db;
danielk1977106bb232004-05-21 10:08:53 +00001064
1065 if( objc!=2 ){
1066 Tcl_AppendResult(interp, "wrong # args: should be \"",
1067 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
drhb86ccfb2003-01-28 23:13:10 +00001068 return TCL_ERROR;
1069 }
danielk1977106bb232004-05-21 10:08:53 +00001070
1071 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1072
danielk19774397de52005-01-12 12:44:03 +00001073 if( pStmt ){
1074 db = StmtToDb(pStmt);
1075 }
danielk1977fc57d7b2004-05-26 02:04:57 +00001076 rc = sqlite3_finalize(pStmt);
danielk1977b77f5da2004-05-26 13:27:00 +00001077 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
danielk19774397de52005-01-12 12:44:03 +00001078 if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk1977106bb232004-05-21 10:08:53 +00001079 return TCL_OK;
1080}
1081
1082/*
1083** Usage: sqlite3_reset STMT
1084**
danielk1977261919c2005-12-06 12:52:59 +00001085** Reset a statement handle.
danielk1977106bb232004-05-21 10:08:53 +00001086*/
1087static int test_reset(
1088 void * clientData,
1089 Tcl_Interp *interp,
1090 int objc,
1091 Tcl_Obj *CONST objv[]
1092){
1093 sqlite3_stmt *pStmt;
1094 int rc;
1095
1096 if( objc!=2 ){
1097 Tcl_AppendResult(interp, "wrong # args: should be \"",
1098 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
1099 return TCL_ERROR;
1100 }
1101
1102 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1103
danielk1977fc57d7b2004-05-26 02:04:57 +00001104 rc = sqlite3_reset(pStmt);
danielk1977261919c2005-12-06 12:52:59 +00001105 if( pStmt && sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ){
1106 return TCL_ERROR;
1107 }
danielk19774397de52005-01-12 12:44:03 +00001108 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
danielk1977261919c2005-12-06 12:52:59 +00001109/*
danielk1977106bb232004-05-21 10:08:53 +00001110 if( rc ){
drhb86ccfb2003-01-28 23:13:10 +00001111 return TCL_ERROR;
1112 }
danielk1977261919c2005-12-06 12:52:59 +00001113*/
drhb86ccfb2003-01-28 23:13:10 +00001114 return TCL_OK;
1115}
1116
drh5a387052003-01-11 14:19:51 +00001117/*
drhd89bd002005-01-22 03:03:54 +00001118** Usage: sqlite3_expired STMT
1119**
1120** Return TRUE if a recompilation of the statement is recommended.
1121*/
1122static int test_expired(
1123 void * clientData,
1124 Tcl_Interp *interp,
1125 int objc,
1126 Tcl_Obj *CONST objv[]
1127){
1128 sqlite3_stmt *pStmt;
1129 if( objc!=2 ){
1130 Tcl_AppendResult(interp, "wrong # args: should be \"",
1131 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
1132 return TCL_ERROR;
1133 }
1134 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1135 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite3_expired(pStmt)));
1136 return TCL_OK;
1137}
1138
1139/*
drhf8db1bc2005-04-22 02:38:37 +00001140** Usage: sqlite3_transfer_bindings FROMSTMT TOSTMT
1141**
1142** Transfer all bindings from FROMSTMT over to TOSTMT
1143*/
1144static int test_transfer_bind(
1145 void * clientData,
1146 Tcl_Interp *interp,
1147 int objc,
1148 Tcl_Obj *CONST objv[]
1149){
1150 sqlite3_stmt *pStmt1, *pStmt2;
1151 if( objc!=3 ){
1152 Tcl_AppendResult(interp, "wrong # args: should be \"",
1153 Tcl_GetStringFromObj(objv[0], 0), " FROM-STMT TO-STMT", 0);
1154 return TCL_ERROR;
1155 }
1156 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt1)) return TCL_ERROR;
1157 if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt2)) return TCL_ERROR;
1158 Tcl_SetObjResult(interp,
1159 Tcl_NewIntObj(sqlite3_transfer_bindings(pStmt1,pStmt2)));
1160 return TCL_OK;
1161}
1162
1163/*
danielk1977fbcd5852004-06-15 02:44:18 +00001164** Usage: sqlite3_changes DB
drh50457892003-09-06 01:10:47 +00001165**
danielk1977fbcd5852004-06-15 02:44:18 +00001166** Return the number of changes made to the database by the last SQL
1167** execution.
drh50457892003-09-06 01:10:47 +00001168*/
danielk1977fbcd5852004-06-15 02:44:18 +00001169static int test_changes(
1170 void * clientData,
1171 Tcl_Interp *interp,
1172 int objc,
1173 Tcl_Obj *CONST objv[]
1174){
1175 sqlite3 *db;
1176 if( objc!=2 ){
1177 Tcl_AppendResult(interp, "wrong # args: should be \"",
1178 Tcl_GetString(objv[0]), " DB", 0);
1179 return TCL_ERROR;
1180 }
1181 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1182 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db)));
1183 return TCL_OK;
1184}
drh50457892003-09-06 01:10:47 +00001185
1186/*
drh7c972de2003-09-06 22:18:07 +00001187** This is the "static_bind_value" that variables are bound to when
danielk19776f8a5032004-05-10 10:34:51 +00001188** the FLAG option of sqlite3_bind is "static"
drh50457892003-09-06 01:10:47 +00001189*/
drh7c972de2003-09-06 22:18:07 +00001190static char *sqlite_static_bind_value = 0;
1191
1192/*
danielk19776f8a5032004-05-10 10:34:51 +00001193** Usage: sqlite3_bind VM IDX VALUE FLAGS
drh7c972de2003-09-06 22:18:07 +00001194**
1195** Sets the value of the IDX-th occurance of "?" in the original SQL
1196** string. VALUE is the new value. If FLAGS=="null" then VALUE is
1197** ignored and the value is set to NULL. If FLAGS=="static" then
1198** the value is set to the value of a static variable named
1199** "sqlite_static_bind_value". If FLAGS=="normal" then a copy
drhbf8aa2a2005-12-02 02:44:05 +00001200** of the VALUE is made. If FLAGS=="blob10" then a VALUE is ignored
1201** an a 10-byte blob "abc\000xyz\000pq" is inserted.
drh7c972de2003-09-06 22:18:07 +00001202*/
1203static int test_bind(
drh50457892003-09-06 01:10:47 +00001204 void *NotUsed,
1205 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1206 int argc, /* Number of arguments */
1207 char **argv /* Text of each argument */
1208){
danielk1977fc57d7b2004-05-26 02:04:57 +00001209 sqlite3_stmt *pStmt;
drh50457892003-09-06 01:10:47 +00001210 int rc;
drh7c972de2003-09-06 22:18:07 +00001211 int idx;
1212 if( argc!=5 ){
drh50457892003-09-06 01:10:47 +00001213 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
drh7c972de2003-09-06 22:18:07 +00001214 " VM IDX VALUE (null|static|normal)\"", 0);
drh50457892003-09-06 01:10:47 +00001215 return TCL_ERROR;
1216 }
danielk1977fc57d7b2004-05-26 02:04:57 +00001217 if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR;
drh7c972de2003-09-06 22:18:07 +00001218 if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR;
1219 if( strcmp(argv[4],"null")==0 ){
danielk1977fc57d7b2004-05-26 02:04:57 +00001220 rc = sqlite3_bind_null(pStmt, idx);
drh7c972de2003-09-06 22:18:07 +00001221 }else if( strcmp(argv[4],"static")==0 ){
danielk1977fc57d7b2004-05-26 02:04:57 +00001222 rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0);
drh7c972de2003-09-06 22:18:07 +00001223 }else if( strcmp(argv[4],"normal")==0 ){
danielk1977d8123362004-06-12 09:25:12 +00001224 rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT);
drhbf8aa2a2005-12-02 02:44:05 +00001225 }else if( strcmp(argv[4],"blob10")==0 ){
1226 rc = sqlite3_bind_text(pStmt, idx, "abc\000xyz\000pq", 10, SQLITE_STATIC);
drh7c972de2003-09-06 22:18:07 +00001227 }else{
1228 Tcl_AppendResult(interp, "4th argument should be "
1229 "\"null\" or \"static\" or \"normal\"", 0);
1230 return TCL_ERROR;
1231 }
drhc60d0442004-09-30 13:43:13 +00001232 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
drh50457892003-09-06 01:10:47 +00001233 if( rc ){
1234 char zBuf[50];
1235 sprintf(zBuf, "(%d) ", rc);
danielk1977f20b21c2004-05-31 23:56:42 +00001236 Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0);
drh50457892003-09-06 01:10:47 +00001237 return TCL_ERROR;
1238 }
1239 return TCL_OK;
1240}
1241
drh5436dc22004-11-14 04:04:17 +00001242#ifndef SQLITE_OMIT_UTF16
danielk19774e6af132004-06-10 14:01:08 +00001243/*
1244** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be>
1245**
1246** This function is used to test that SQLite selects the correct collation
1247** sequence callback when multiple versions (for different text encodings)
1248** are available.
1249**
1250** Calling this routine registers the collation sequence "test_collate"
1251** with database handle <db>. The second argument must be a list of three
1252** boolean values. If the first is true, then a version of test_collate is
1253** registered for UTF-8, if the second is true, a version is registered for
1254** UTF-16le, if the third is true, a UTF-16be version is available.
1255** Previous versions of test_collate are deleted.
1256**
1257** The collation sequence test_collate is implemented by calling the
1258** following TCL script:
1259**
1260** "test_collate <enc> <lhs> <rhs>"
1261**
1262** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8.
1263** The <enc> parameter is the encoding of the collation function that
1264** SQLite selected to call. The TCL test script implements the
1265** "test_collate" proc.
1266**
1267** Note that this will only work with one intepreter at a time, as the
1268** interp pointer to use when evaluating the TCL script is stored in
1269** pTestCollateInterp.
1270*/
1271static Tcl_Interp* pTestCollateInterp;
1272static int test_collate_func(
1273 void *pCtx,
1274 int nA, const void *zA,
1275 int nB, const void *zB
1276){
1277 Tcl_Interp *i = pTestCollateInterp;
1278 int encin = (int)pCtx;
1279 int res;
drh4db38a72005-09-01 12:16:28 +00001280 int n;
danielk19774e6af132004-06-10 14:01:08 +00001281
1282 sqlite3_value *pVal;
1283 Tcl_Obj *pX;
1284
1285 pX = Tcl_NewStringObj("test_collate", -1);
1286 Tcl_IncrRefCount(pX);
1287
1288 switch( encin ){
1289 case SQLITE_UTF8:
1290 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1));
1291 break;
1292 case SQLITE_UTF16LE:
1293 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1));
1294 break;
1295 case SQLITE_UTF16BE:
1296 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1));
1297 break;
1298 default:
1299 assert(0);
1300 }
1301
1302 pVal = sqlite3ValueNew();
danielk1977bfd6cce2004-06-18 04:24:54 +00001303 sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC);
drh4db38a72005-09-01 12:16:28 +00001304 n = sqlite3_value_bytes(pVal);
drh03d847e2005-12-09 20:21:58 +00001305 Tcl_ListObjAppendElement(i,pX,
1306 Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
danielk1977bfd6cce2004-06-18 04:24:54 +00001307 sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC);
drh4db38a72005-09-01 12:16:28 +00001308 n = sqlite3_value_bytes(pVal);
drh03d847e2005-12-09 20:21:58 +00001309 Tcl_ListObjAppendElement(i,pX,
1310 Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
danielk19774e6af132004-06-10 14:01:08 +00001311 sqlite3ValueFree(pVal);
1312
1313 Tcl_EvalObjEx(i, pX, 0);
1314 Tcl_DecrRefCount(pX);
1315 Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res);
1316 return res;
1317}
1318static int test_collate(
1319 void * clientData,
1320 Tcl_Interp *interp,
1321 int objc,
1322 Tcl_Obj *CONST objv[]
1323){
1324 sqlite3 *db;
1325 int val;
danielk1977312d6b32004-06-29 13:18:23 +00001326 sqlite3_value *pVal;
drhc60d0442004-09-30 13:43:13 +00001327 int rc;
danielk19774e6af132004-06-10 14:01:08 +00001328
1329 if( objc!=5 ) goto bad_args;
1330 pTestCollateInterp = interp;
1331 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1332
1333 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +00001334 rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8,
1335 (void *)SQLITE_UTF8, val?test_collate_func:0);
1336 if( rc==SQLITE_OK ){
1337 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
1338 rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE,
1339 (void *)SQLITE_UTF16LE, val?test_collate_func:0);
1340 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
danielk1977312d6b32004-06-29 13:18:23 +00001341
drhc60d0442004-09-30 13:43:13 +00001342 pVal = sqlite3ValueNew();
1343 sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC);
1344 sqlite3_create_collation16(db, sqlite3ValueText(pVal, SQLITE_UTF16NATIVE),
1345 SQLITE_UTF16BE, (void *)SQLITE_UTF16BE, val?test_collate_func:0);
1346 sqlite3ValueFree(pVal);
1347 }
1348 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk19774e6af132004-06-10 14:01:08 +00001349 return TCL_OK;
1350
1351bad_args:
1352 Tcl_AppendResult(interp, "wrong # args: should be \"",
1353 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
1354 return TCL_ERROR;
1355}
1356
drh268803a2005-12-14 20:11:30 +00001357/*
1358** When the collation needed callback is invoked, record the name of
1359** the requested collating function here. The recorded name is linked
1360** to a TCL variable and used to make sure that the requested collation
1361** name is correct.
1362*/
1363static char zNeededCollation[200];
1364static char *pzNeededCollation = zNeededCollation;
1365
1366
1367/*
1368** Called when a collating sequence is needed. Registered using
1369** sqlite3_collation_needed16().
1370*/
danielk1977312d6b32004-06-29 13:18:23 +00001371static void test_collate_needed_cb(
1372 void *pCtx,
1373 sqlite3 *db,
1374 int eTextRep,
drh268803a2005-12-14 20:11:30 +00001375 const void *pName
danielk1977312d6b32004-06-29 13:18:23 +00001376){
1377 int enc = db->enc;
drh268803a2005-12-14 20:11:30 +00001378 int i;
1379 char *z;
1380 for(z = (char*)pName, i=0; *z || z[1]; z++){
1381 if( *z ) zNeededCollation[i++] = *z;
1382 }
1383 zNeededCollation[i] = 0;
danielk1977312d6b32004-06-29 13:18:23 +00001384 sqlite3_create_collation(
1385 db, "test_collate", db->enc, (void *)enc, test_collate_func);
1386}
1387
1388/*
1389** Usage: add_test_collate_needed DB
1390*/
1391static int test_collate_needed(
1392 void * clientData,
1393 Tcl_Interp *interp,
1394 int objc,
1395 Tcl_Obj *CONST objv[]
1396){
1397 sqlite3 *db;
drhc60d0442004-09-30 13:43:13 +00001398 int rc;
danielk1977312d6b32004-06-29 13:18:23 +00001399
1400 if( objc!=2 ) goto bad_args;
1401 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +00001402 rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb);
drh268803a2005-12-14 20:11:30 +00001403 zNeededCollation[0] = 0;
drhc60d0442004-09-30 13:43:13 +00001404 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk1977312d6b32004-06-29 13:18:23 +00001405 return TCL_OK;
1406
1407bad_args:
1408 Tcl_WrongNumArgs(interp, 1, objv, "DB");
1409 return TCL_ERROR;
1410}
drh5436dc22004-11-14 04:04:17 +00001411#endif /* SQLITE_OMIT_UTF16 */
danielk1977312d6b32004-06-29 13:18:23 +00001412
danielk1977c8e9a2d2004-06-25 12:08:46 +00001413/*
1414** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
1415**
1416** This function is used to test that SQLite selects the correct user
1417** function callback when multiple versions (for different text encodings)
1418** are available.
1419**
1420** Calling this routine registers up to three versions of the user function
1421** "test_function" with database handle <db>. If the second argument is
1422** true, then a version of test_function is registered for UTF-8, if the
1423** third is true, a version is registered for UTF-16le, if the fourth is
1424** true, a UTF-16be version is available. Previous versions of
1425** test_function are deleted.
1426**
1427** The user function is implemented by calling the following TCL script:
1428**
1429** "test_function <enc> <arg>"
1430**
1431** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the
1432** single argument passed to the SQL function. The value returned by
1433** the TCL script is used as the return value of the SQL function. It
1434** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8
1435** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
1436** prefers UTF-16BE.
1437*/
drh5436dc22004-11-14 04:04:17 +00001438#ifndef SQLITE_OMIT_UTF16
danielk1977c8e9a2d2004-06-25 12:08:46 +00001439static void test_function_utf8(
1440 sqlite3_context *pCtx,
1441 int nArg,
1442 sqlite3_value **argv
1443){
1444 Tcl_Interp *interp;
1445 Tcl_Obj *pX;
1446 sqlite3_value *pVal;
1447 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1448 pX = Tcl_NewStringObj("test_function", -1);
1449 Tcl_IncrRefCount(pX);
1450 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1));
1451 Tcl_ListObjAppendElement(interp, pX,
drh03d847e2005-12-09 20:21:58 +00001452 Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
danielk1977c8e9a2d2004-06-25 12:08:46 +00001453 Tcl_EvalObjEx(interp, pX, 0);
1454 Tcl_DecrRefCount(pX);
1455 sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT);
1456 pVal = sqlite3ValueNew();
1457 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1458 SQLITE_UTF8, SQLITE_STATIC);
1459 sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal),
1460 -1, SQLITE_TRANSIENT);
1461 sqlite3ValueFree(pVal);
1462}
1463static void test_function_utf16le(
1464 sqlite3_context *pCtx,
1465 int nArg,
1466 sqlite3_value **argv
1467){
1468 Tcl_Interp *interp;
1469 Tcl_Obj *pX;
1470 sqlite3_value *pVal;
1471 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1472 pX = Tcl_NewStringObj("test_function", -1);
1473 Tcl_IncrRefCount(pX);
1474 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1));
1475 Tcl_ListObjAppendElement(interp, pX,
drh03d847e2005-12-09 20:21:58 +00001476 Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
danielk1977c8e9a2d2004-06-25 12:08:46 +00001477 Tcl_EvalObjEx(interp, pX, 0);
1478 Tcl_DecrRefCount(pX);
1479 pVal = sqlite3ValueNew();
1480 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1481 SQLITE_UTF8, SQLITE_STATIC);
drh03d847e2005-12-09 20:21:58 +00001482 sqlite3_result_text(pCtx,(char*)sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT);
danielk1977c8e9a2d2004-06-25 12:08:46 +00001483 sqlite3ValueFree(pVal);
1484}
1485static void test_function_utf16be(
1486 sqlite3_context *pCtx,
1487 int nArg,
1488 sqlite3_value **argv
1489){
1490 Tcl_Interp *interp;
1491 Tcl_Obj *pX;
1492 sqlite3_value *pVal;
1493 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1494 pX = Tcl_NewStringObj("test_function", -1);
1495 Tcl_IncrRefCount(pX);
1496 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1));
1497 Tcl_ListObjAppendElement(interp, pX,
drh03d847e2005-12-09 20:21:58 +00001498 Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
danielk1977c8e9a2d2004-06-25 12:08:46 +00001499 Tcl_EvalObjEx(interp, pX, 0);
1500 Tcl_DecrRefCount(pX);
1501 pVal = sqlite3ValueNew();
1502 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1503 SQLITE_UTF8, SQLITE_STATIC);
1504 sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal),
1505 -1, SQLITE_TRANSIENT);
1506 sqlite3ValueFree(pVal);
1507}
drh5436dc22004-11-14 04:04:17 +00001508#endif /* SQLITE_OMIT_UTF16 */
danielk1977c8e9a2d2004-06-25 12:08:46 +00001509static int test_function(
1510 void * clientData,
1511 Tcl_Interp *interp,
1512 int objc,
1513 Tcl_Obj *CONST objv[]
1514){
drh5436dc22004-11-14 04:04:17 +00001515#ifndef SQLITE_OMIT_UTF16
danielk1977c8e9a2d2004-06-25 12:08:46 +00001516 sqlite3 *db;
1517 int val;
1518
1519 if( objc!=5 ) goto bad_args;
1520 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1521
1522 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
1523 if( val ){
1524 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8,
1525 interp, test_function_utf8, 0, 0);
1526 }
1527 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
1528 if( val ){
1529 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE,
1530 interp, test_function_utf16le, 0, 0);
1531 }
1532 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
1533 if( val ){
1534 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE,
1535 interp, test_function_utf16be, 0, 0);
1536 }
1537
1538 return TCL_OK;
1539bad_args:
1540 Tcl_AppendResult(interp, "wrong # args: should be \"",
1541 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
drh5436dc22004-11-14 04:04:17 +00001542#endif /* SQLITE_OMIT_UTF16 */
danielk1977c8e9a2d2004-06-25 12:08:46 +00001543 return TCL_ERROR;
1544}
1545
danielk1977312d6b32004-06-29 13:18:23 +00001546/*
1547** Usage: test_errstr <err code>
1548**
1549** Test that the english language string equivalents for sqlite error codes
1550** are sane. The parameter is an integer representing an sqlite error code.
1551** The result is a list of two elements, the string representation of the
1552** error code and the english language explanation.
1553*/
1554static int test_errstr(
1555 void * clientData,
1556 Tcl_Interp *interp,
1557 int objc,
1558 Tcl_Obj *CONST objv[]
1559){
1560 char *zCode;
1561 int i;
1562 if( objc!=1 ){
1563 Tcl_WrongNumArgs(interp, 1, objv, "<error code>");
1564 }
1565
1566 zCode = Tcl_GetString(objv[1]);
1567 for(i=0; i<200; i++){
1568 if( 0==strcmp(errorName(i), zCode) ) break;
1569 }
1570 Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0);
1571 return TCL_OK;
1572}
1573
drh50457892003-09-06 01:10:47 +00001574/*
drh99ee3602003-02-16 19:13:36 +00001575** Usage: breakpoint
1576**
1577** This routine exists for one purpose - to provide a place to put a
1578** breakpoint with GDB that can be triggered using TCL code. The use
1579** for this is when a particular test fails on (say) the 1485th iteration.
1580** In the TCL test script, we can add code like this:
1581**
1582** if {$i==1485} breakpoint
1583**
1584** Then run testfixture in the debugger and wait for the breakpoint to
1585** fire. Then additional breakpoints can be set to trace down the bug.
1586*/
1587static int test_breakpoint(
1588 void *NotUsed,
1589 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1590 int argc, /* Number of arguments */
1591 char **argv /* Text of each argument */
1592){
1593 return TCL_OK; /* Do nothing */
1594}
1595
drh241db312004-06-22 12:46:53 +00001596/*
1597** Usage: sqlite3_bind_int STMT N VALUE
1598**
1599** Test the sqlite3_bind_int interface. STMT is a prepared statement.
1600** N is the index of a wildcard in the prepared statement. This command
1601** binds a 32-bit integer VALUE to that wildcard.
1602*/
1603static int test_bind_int(
danielk197751e3d8e2004-05-20 01:12:34 +00001604 void * clientData,
1605 Tcl_Interp *interp,
1606 int objc,
1607 Tcl_Obj *CONST objv[]
1608){
1609 sqlite3_stmt *pStmt;
1610 int idx;
1611 int value;
1612 int rc;
1613
1614 if( objc!=4 ){
1615 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001616 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001617 return TCL_ERROR;
1618 }
1619
1620 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1621 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1622 if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
1623
danielk1977c572ef72004-05-27 09:28:41 +00001624 rc = sqlite3_bind_int(pStmt, idx, value);
drhc60d0442004-09-30 13:43:13 +00001625 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001626 if( rc!=SQLITE_OK ){
1627 return TCL_ERROR;
1628 }
1629
1630 return TCL_OK;
1631}
1632
drh241db312004-06-22 12:46:53 +00001633
1634/*
1635** Usage: sqlite3_bind_int64 STMT N VALUE
1636**
1637** Test the sqlite3_bind_int64 interface. STMT is a prepared statement.
1638** N is the index of a wildcard in the prepared statement. This command
1639** binds a 64-bit integer VALUE to that wildcard.
1640*/
danielk197751e3d8e2004-05-20 01:12:34 +00001641static int test_bind_int64(
1642 void * clientData,
1643 Tcl_Interp *interp,
1644 int objc,
1645 Tcl_Obj *CONST objv[]
1646){
1647 sqlite3_stmt *pStmt;
1648 int idx;
1649 i64 value;
1650 int rc;
1651
1652 if( objc!=4 ){
1653 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001654 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001655 return TCL_ERROR;
1656 }
1657
1658 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1659 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1660 if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
1661
1662 rc = sqlite3_bind_int64(pStmt, idx, value);
drhc60d0442004-09-30 13:43:13 +00001663 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001664 if( rc!=SQLITE_OK ){
1665 return TCL_ERROR;
1666 }
1667
1668 return TCL_OK;
1669}
1670
drh241db312004-06-22 12:46:53 +00001671
1672/*
1673** Usage: sqlite3_bind_double STMT N VALUE
1674**
1675** Test the sqlite3_bind_double interface. STMT is a prepared statement.
1676** N is the index of a wildcard in the prepared statement. This command
1677** binds a 64-bit integer VALUE to that wildcard.
1678*/
danielk197751e3d8e2004-05-20 01:12:34 +00001679static int test_bind_double(
1680 void * clientData,
1681 Tcl_Interp *interp,
1682 int objc,
1683 Tcl_Obj *CONST objv[]
1684){
1685 sqlite3_stmt *pStmt;
1686 int idx;
1687 double value;
1688 int rc;
1689
1690 if( objc!=4 ){
1691 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001692 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001693 return TCL_ERROR;
1694 }
1695
1696 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1697 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1698 if( Tcl_GetDoubleFromObj(interp, objv[3], &value) ) return TCL_ERROR;
1699
1700 rc = sqlite3_bind_double(pStmt, idx, value);
drhc60d0442004-09-30 13:43:13 +00001701 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001702 if( rc!=SQLITE_OK ){
1703 return TCL_ERROR;
1704 }
1705
1706 return TCL_OK;
1707}
1708
drh241db312004-06-22 12:46:53 +00001709/*
1710** Usage: sqlite3_bind_null STMT N
1711**
1712** Test the sqlite3_bind_null interface. STMT is a prepared statement.
1713** N is the index of a wildcard in the prepared statement. This command
1714** binds a NULL to the wildcard.
1715*/
danielk197751e3d8e2004-05-20 01:12:34 +00001716static int test_bind_null(
1717 void * clientData,
1718 Tcl_Interp *interp,
1719 int objc,
1720 Tcl_Obj *CONST objv[]
1721){
1722 sqlite3_stmt *pStmt;
1723 int idx;
1724 int rc;
1725
1726 if( objc!=3 ){
1727 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001728 Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001729 return TCL_ERROR;
1730 }
1731
1732 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1733 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1734
1735 rc = sqlite3_bind_null(pStmt, idx);
drhc60d0442004-09-30 13:43:13 +00001736 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001737 if( rc!=SQLITE_OK ){
1738 return TCL_ERROR;
1739 }
1740
1741 return TCL_OK;
1742}
1743
drh241db312004-06-22 12:46:53 +00001744/*
1745** Usage: sqlite3_bind_text STMT N STRING BYTES
1746**
1747** Test the sqlite3_bind_text interface. STMT is a prepared statement.
1748** N is the index of a wildcard in the prepared statement. This command
1749** binds a UTF-8 string STRING to the wildcard. The string is BYTES bytes
1750** long.
1751*/
danielk197751e3d8e2004-05-20 01:12:34 +00001752static int test_bind_text(
1753 void * clientData,
1754 Tcl_Interp *interp,
1755 int objc,
1756 Tcl_Obj *CONST objv[]
1757){
1758 sqlite3_stmt *pStmt;
1759 int idx;
1760 int bytes;
1761 char *value;
1762 int rc;
1763
1764 if( objc!=5 ){
1765 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001766 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001767 return TCL_ERROR;
1768 }
1769
1770 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1771 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1772 value = Tcl_GetString(objv[3]);
1773 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
1774
danielk1977d8123362004-06-12 09:25:12 +00001775 rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
drhc60d0442004-09-30 13:43:13 +00001776 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001777 if( rc!=SQLITE_OK ){
drh473d1792005-06-06 17:54:55 +00001778 Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001779 return TCL_ERROR;
1780 }
1781
1782 return TCL_OK;
1783}
1784
drh241db312004-06-22 12:46:53 +00001785/*
1786** Usage: sqlite3_bind_text16 STMT N STRING BYTES
1787**
1788** Test the sqlite3_bind_text16 interface. STMT is a prepared statement.
1789** N is the index of a wildcard in the prepared statement. This command
1790** binds a UTF-16 string STRING to the wildcard. The string is BYTES bytes
1791** long.
1792*/
danielk197751e3d8e2004-05-20 01:12:34 +00001793static int test_bind_text16(
1794 void * clientData,
1795 Tcl_Interp *interp,
1796 int objc,
1797 Tcl_Obj *CONST objv[]
1798){
drh5436dc22004-11-14 04:04:17 +00001799#ifndef SQLITE_OMIT_UTF16
danielk197751e3d8e2004-05-20 01:12:34 +00001800 sqlite3_stmt *pStmt;
1801 int idx;
1802 int bytes;
1803 char *value;
1804 int rc;
1805
1806 if( objc!=5 ){
1807 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001808 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001809 return TCL_ERROR;
1810 }
1811
1812 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1813 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
drh03d847e2005-12-09 20:21:58 +00001814 value = (char*)Tcl_GetByteArrayFromObj(objv[3], 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001815 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
1816
danielk1977d8123362004-06-12 09:25:12 +00001817 rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, SQLITE_TRANSIENT);
drhc60d0442004-09-30 13:43:13 +00001818 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001819 if( rc!=SQLITE_OK ){
1820 return TCL_ERROR;
1821 }
1822
drh5436dc22004-11-14 04:04:17 +00001823#endif /* SQLITE_OMIT_UTF16 */
danielk197751e3d8e2004-05-20 01:12:34 +00001824 return TCL_OK;
1825}
1826
drh241db312004-06-22 12:46:53 +00001827/*
1828** Usage: sqlite3_bind_blob STMT N DATA BYTES
1829**
1830** Test the sqlite3_bind_blob interface. STMT is a prepared statement.
1831** N is the index of a wildcard in the prepared statement. This command
1832** binds a BLOB to the wildcard. The BLOB is BYTES bytes in size.
1833*/
danielk197751e3d8e2004-05-20 01:12:34 +00001834static int test_bind_blob(
1835 void * clientData,
1836 Tcl_Interp *interp,
1837 int objc,
1838 Tcl_Obj *CONST objv[]
1839){
1840 sqlite3_stmt *pStmt;
1841 int idx;
1842 int bytes;
1843 char *value;
1844 int rc;
1845
1846 if( objc!=5 ){
1847 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001848 Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001849 return TCL_ERROR;
1850 }
1851
1852 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1853 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1854 value = Tcl_GetString(objv[3]);
danielk197749e46432004-05-27 13:55:27 +00001855 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001856
danielk1977d8123362004-06-12 09:25:12 +00001857 rc = sqlite3_bind_blob(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
drhc60d0442004-09-30 13:43:13 +00001858 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001859 if( rc!=SQLITE_OK ){
1860 return TCL_ERROR;
1861 }
1862
1863 return TCL_OK;
1864}
1865
drh99ee3602003-02-16 19:13:36 +00001866/*
drh75f6a032004-07-15 14:15:00 +00001867** Usage: sqlite3_bind_parameter_count STMT
1868**
1869** Return the number of wildcards in the given statement.
1870*/
1871static int test_bind_parameter_count(
1872 void * clientData,
1873 Tcl_Interp *interp,
1874 int objc,
1875 Tcl_Obj *CONST objv[]
1876){
1877 sqlite3_stmt *pStmt;
1878
1879 if( objc!=2 ){
1880 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
1881 return TCL_ERROR;
1882 }
1883 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1884 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt)));
1885 return TCL_OK;
1886}
1887
1888/*
drh895d7472004-08-20 16:02:39 +00001889** Usage: sqlite3_bind_parameter_name STMT N
1890**
1891** Return the name of the Nth wildcard. The first wildcard is 1.
1892** An empty string is returned if N is out of range or if the wildcard
1893** is nameless.
1894*/
1895static int test_bind_parameter_name(
1896 void * clientData,
1897 Tcl_Interp *interp,
1898 int objc,
1899 Tcl_Obj *CONST objv[]
1900){
1901 sqlite3_stmt *pStmt;
1902 int i;
1903
1904 if( objc!=3 ){
1905 Tcl_WrongNumArgs(interp, 1, objv, "STMT N");
1906 return TCL_ERROR;
1907 }
1908 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1909 if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR;
1910 Tcl_SetObjResult(interp,
1911 Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1)
1912 );
1913 return TCL_OK;
1914}
1915
1916/*
drhfa6bc002004-09-07 16:19:52 +00001917** Usage: sqlite3_bind_parameter_index STMT NAME
1918**
1919** Return the index of the wildcard called NAME. Return 0 if there is
1920** no such wildcard.
1921*/
1922static int test_bind_parameter_index(
1923 void * clientData,
1924 Tcl_Interp *interp,
1925 int objc,
1926 Tcl_Obj *CONST objv[]
1927){
1928 sqlite3_stmt *pStmt;
1929
1930 if( objc!=3 ){
1931 Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME");
1932 return TCL_ERROR;
1933 }
1934 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1935 Tcl_SetObjResult(interp,
1936 Tcl_NewIntObj(
1937 sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2]))
1938 )
1939 );
1940 return TCL_OK;
1941}
1942
1943/*
danielk1977600dd0b2005-01-20 01:14:23 +00001944** Usage: sqlite3_clear_bindings STMT
1945**
1946*/
1947#if 0
1948static int test_clear_bindings(
1949 void * clientData,
1950 Tcl_Interp *interp,
1951 int objc,
1952 Tcl_Obj *CONST objv[]
1953){
1954 sqlite3_stmt *pStmt;
1955
1956 if( objc!=2 ){
1957 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
1958 return TCL_ERROR;
1959 }
1960 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1961 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt)));
1962 return TCL_OK;
1963}
1964#endif
1965
1966/*
danielk19776622cce2004-05-20 11:00:52 +00001967** Usage: sqlite3_errcode DB
1968**
1969** Return the string representation of the most recent sqlite3_* API
1970** error code. e.g. "SQLITE_ERROR".
1971*/
1972static int test_errcode(
1973 void * clientData,
1974 Tcl_Interp *interp,
1975 int objc,
1976 Tcl_Obj *CONST objv[]
1977){
1978 sqlite3 *db;
1979
1980 if( objc!=2 ){
1981 Tcl_AppendResult(interp, "wrong # args: should be \"",
1982 Tcl_GetString(objv[0]), " DB", 0);
1983 return TCL_ERROR;
1984 }
1985 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1986 Tcl_SetResult(interp, (char *)errorName(sqlite3_errcode(db)), 0);
1987 return TCL_OK;
1988}
1989
1990/*
1991** Usage: test_errmsg DB
1992**
1993** Returns the UTF-8 representation of the error message string for the
1994** most recent sqlite3_* API call.
1995*/
1996static int test_errmsg(
1997 void * clientData,
1998 Tcl_Interp *interp,
1999 int objc,
2000 Tcl_Obj *CONST objv[]
2001){
drh9bb575f2004-09-06 17:24:11 +00002002 sqlite3 *db;
danielk19776622cce2004-05-20 11:00:52 +00002003 const char *zErr;
2004
2005 if( objc!=2 ){
2006 Tcl_AppendResult(interp, "wrong # args: should be \"",
2007 Tcl_GetString(objv[0]), " DB", 0);
2008 return TCL_ERROR;
2009 }
2010 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2011
2012 zErr = sqlite3_errmsg(db);
2013 Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
2014 return TCL_OK;
2015}
2016
2017/*
2018** Usage: test_errmsg16 DB
2019**
2020** Returns the UTF-16 representation of the error message string for the
2021** most recent sqlite3_* API call. This is a byte array object at the TCL
2022** level, and it includes the 0x00 0x00 terminator bytes at the end of the
2023** UTF-16 string.
2024*/
2025static int test_errmsg16(
2026 void * clientData,
2027 Tcl_Interp *interp,
2028 int objc,
2029 Tcl_Obj *CONST objv[]
2030){
drh5436dc22004-11-14 04:04:17 +00002031#ifndef SQLITE_OMIT_UTF16
drh9bb575f2004-09-06 17:24:11 +00002032 sqlite3 *db;
danielk19776622cce2004-05-20 11:00:52 +00002033 const void *zErr;
2034 int bytes;
2035
2036 if( objc!=2 ){
2037 Tcl_AppendResult(interp, "wrong # args: should be \"",
2038 Tcl_GetString(objv[0]), " DB", 0);
2039 return TCL_ERROR;
2040 }
2041 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2042
2043 zErr = sqlite3_errmsg16(db);
2044 bytes = sqlite3utf16ByteLen(zErr, -1);
2045 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes));
drh5436dc22004-11-14 04:04:17 +00002046#endif /* SQLITE_OMIT_UTF16 */
danielk19776622cce2004-05-20 11:00:52 +00002047 return TCL_OK;
2048}
2049
2050/*
2051** Usage: sqlite3_prepare DB sql bytes tailvar
2052**
2053** Compile up to <bytes> bytes of the supplied SQL string <sql> using
2054** database handle <DB>. The parameter <tailval> is the name of a global
2055** variable that is set to the unused portion of <sql> (if any). A
2056** STMT handle is returned.
2057*/
2058static int test_prepare(
2059 void * clientData,
2060 Tcl_Interp *interp,
2061 int objc,
2062 Tcl_Obj *CONST objv[]
2063){
2064 sqlite3 *db;
2065 const char *zSql;
2066 int bytes;
2067 const char *zTail = 0;
2068 sqlite3_stmt *pStmt = 0;
2069 char zBuf[50];
danielk19774ad17132004-05-21 01:47:26 +00002070 int rc;
danielk19776622cce2004-05-20 11:00:52 +00002071
2072 if( objc!=5 ){
2073 Tcl_AppendResult(interp, "wrong # args: should be \"",
2074 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
2075 return TCL_ERROR;
2076 }
2077 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2078 zSql = Tcl_GetString(objv[2]);
2079 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
2080
danielk19774ad17132004-05-21 01:47:26 +00002081 rc = sqlite3_prepare(db, zSql, bytes, &pStmt, &zTail);
drhc60d0442004-09-30 13:43:13 +00002082 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk19776622cce2004-05-20 11:00:52 +00002083 if( zTail ){
2084 if( bytes>=0 ){
2085 bytes = bytes - (zTail-zSql);
2086 }
2087 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
2088 }
danielk19774ad17132004-05-21 01:47:26 +00002089 if( rc!=SQLITE_OK ){
2090 assert( pStmt==0 );
2091 sprintf(zBuf, "(%d) ", rc);
2092 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
2093 return TCL_ERROR;
2094 }
danielk19776622cce2004-05-20 11:00:52 +00002095
danielk19774ad17132004-05-21 01:47:26 +00002096 if( pStmt ){
2097 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
2098 Tcl_AppendResult(interp, zBuf, 0);
2099 }
danielk19776622cce2004-05-20 11:00:52 +00002100 return TCL_OK;
2101}
2102
2103/*
2104** Usage: sqlite3_prepare DB sql bytes tailvar
2105**
2106** Compile up to <bytes> bytes of the supplied SQL string <sql> using
2107** database handle <DB>. The parameter <tailval> is the name of a global
2108** variable that is set to the unused portion of <sql> (if any). A
2109** STMT handle is returned.
2110*/
2111static int test_prepare16(
2112 void * clientData,
2113 Tcl_Interp *interp,
2114 int objc,
2115 Tcl_Obj *CONST objv[]
2116){
drh5436dc22004-11-14 04:04:17 +00002117#ifndef SQLITE_OMIT_UTF16
danielk19776622cce2004-05-20 11:00:52 +00002118 sqlite3 *db;
2119 const void *zSql;
2120 const void *zTail = 0;
2121 Tcl_Obj *pTail = 0;
2122 sqlite3_stmt *pStmt = 0;
drhc60d0442004-09-30 13:43:13 +00002123 char zBuf[50];
2124 int rc;
danielk19776622cce2004-05-20 11:00:52 +00002125 int bytes; /* The integer specified as arg 3 */
2126 int objlen; /* The byte-array length of arg 2 */
2127
2128 if( objc!=5 ){
2129 Tcl_AppendResult(interp, "wrong # args: should be \"",
2130 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
2131 return TCL_ERROR;
2132 }
2133 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2134 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
2135 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
2136
drhc60d0442004-09-30 13:43:13 +00002137 rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, &zTail);
2138 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
2139 if( rc ){
danielk19776622cce2004-05-20 11:00:52 +00002140 return TCL_ERROR;
2141 }
2142
2143 if( zTail ){
2144 objlen = objlen - ((u8 *)zTail-(u8 *)zSql);
2145 }else{
2146 objlen = 0;
2147 }
2148 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
2149 Tcl_IncrRefCount(pTail);
2150 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
danielk19774ad17132004-05-21 01:47:26 +00002151 Tcl_DecrRefCount(pTail);
danielk19776622cce2004-05-20 11:00:52 +00002152
danielk19774ad17132004-05-21 01:47:26 +00002153 if( pStmt ){
2154 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
2155 }
danielk19776622cce2004-05-20 11:00:52 +00002156 Tcl_AppendResult(interp, zBuf, 0);
drh5436dc22004-11-14 04:04:17 +00002157#endif /* SQLITE_OMIT_UTF16 */
danielk19776622cce2004-05-20 11:00:52 +00002158 return TCL_OK;
2159}
2160
danielk19774ad17132004-05-21 01:47:26 +00002161/*
2162** Usage: sqlite3_open filename ?options-list?
2163*/
2164static int test_open(
2165 void * clientData,
2166 Tcl_Interp *interp,
2167 int objc,
2168 Tcl_Obj *CONST objv[]
2169){
2170 const char *zFilename;
2171 sqlite3 *db;
2172 int rc;
2173 char zBuf[100];
2174
2175 if( objc!=3 && objc!=2 ){
2176 Tcl_AppendResult(interp, "wrong # args: should be \"",
2177 Tcl_GetString(objv[0]), " filename options-list", 0);
2178 return TCL_ERROR;
2179 }
2180
2181 zFilename = Tcl_GetString(objv[1]);
danielk19774f057f92004-06-08 00:02:33 +00002182 rc = sqlite3_open(zFilename, &db);
danielk19774ad17132004-05-21 01:47:26 +00002183
2184 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR;
2185 Tcl_AppendResult(interp, zBuf, 0);
2186 return TCL_OK;
2187}
2188
2189/*
2190** Usage: sqlite3_open16 filename options
2191*/
2192static int test_open16(
2193 void * clientData,
2194 Tcl_Interp *interp,
2195 int objc,
2196 Tcl_Obj *CONST objv[]
2197){
drh5436dc22004-11-14 04:04:17 +00002198#ifndef SQLITE_OMIT_UTF16
danielk19774ad17132004-05-21 01:47:26 +00002199 const void *zFilename;
2200 sqlite3 *db;
2201 int rc;
2202 char zBuf[100];
2203
2204 if( objc!=3 ){
2205 Tcl_AppendResult(interp, "wrong # args: should be \"",
2206 Tcl_GetString(objv[0]), " filename options-list", 0);
2207 return TCL_ERROR;
2208 }
2209
2210 zFilename = Tcl_GetByteArrayFromObj(objv[1], 0);
danielk19774f057f92004-06-08 00:02:33 +00002211 rc = sqlite3_open16(zFilename, &db);
danielk19774ad17132004-05-21 01:47:26 +00002212
2213 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR;
2214 Tcl_AppendResult(interp, zBuf, 0);
drh5436dc22004-11-14 04:04:17 +00002215#endif /* SQLITE_OMIT_UTF16 */
danielk19774ad17132004-05-21 01:47:26 +00002216 return TCL_OK;
2217}
drhd3d39e92004-05-20 22:16:29 +00002218
2219/*
danielk1977bc6ada42004-06-30 08:20:16 +00002220** Usage: sqlite3_complete16 <UTF-16 string>
2221**
2222** Return 1 if the supplied argument is a complete SQL statement, or zero
2223** otherwise.
2224*/
2225static int test_complete16(
2226 void * clientData,
2227 Tcl_Interp *interp,
2228 int objc,
2229 Tcl_Obj *CONST objv[]
2230){
drhccae6022005-02-26 17:31:26 +00002231#if !defined(SQLITE_OMIT_COMPLETE) && !defined(SQLITE_OMIT_UTF16)
danielk1977bc6ada42004-06-30 08:20:16 +00002232 char *zBuf;
2233
2234 if( objc!=2 ){
2235 Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>");
2236 return TCL_ERROR;
2237 }
2238
drh03d847e2005-12-09 20:21:58 +00002239 zBuf = (char*)Tcl_GetByteArrayFromObj(objv[1], 0);
danielk1977bc6ada42004-06-30 08:20:16 +00002240 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf)));
drhccae6022005-02-26 17:31:26 +00002241#endif /* SQLITE_OMIT_COMPLETE && SQLITE_OMIT_UTF16 */
danielk1977bc6ada42004-06-30 08:20:16 +00002242 return TCL_OK;
2243}
2244
2245/*
danielk1977106bb232004-05-21 10:08:53 +00002246** Usage: sqlite3_step STMT
2247**
2248** Advance the statement to the next row.
2249*/
danielk197717240fd2004-05-26 00:07:25 +00002250static int test_step(
danielk1977106bb232004-05-21 10:08:53 +00002251 void * clientData,
2252 Tcl_Interp *interp,
2253 int objc,
2254 Tcl_Obj *CONST objv[]
2255){
2256 sqlite3_stmt *pStmt;
2257 int rc;
2258
danielk1977e1cd9872004-05-22 10:33:04 +00002259 if( objc!=2 ){
danielk1977106bb232004-05-21 10:08:53 +00002260 Tcl_AppendResult(interp, "wrong # args: should be \"",
2261 Tcl_GetString(objv[0]), " STMT", 0);
2262 return TCL_ERROR;
2263 }
2264
2265 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
danielk197717240fd2004-05-26 00:07:25 +00002266 rc = sqlite3_step(pStmt);
danielk1977106bb232004-05-21 10:08:53 +00002267
danielk1977fbcd5852004-06-15 02:44:18 +00002268 /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */
danielk197765904932004-05-26 06:18:37 +00002269 Tcl_SetResult(interp, (char *)errorName(rc), 0);
danielk1977e1cd9872004-05-22 10:33:04 +00002270 return TCL_OK;
2271}
2272
2273/*
danielk197717240fd2004-05-26 00:07:25 +00002274** Usage: sqlite3_column_count STMT
2275**
2276** Return the number of columns returned by the sql statement STMT.
2277*/
2278static int test_column_count(
2279 void * clientData,
2280 Tcl_Interp *interp,
2281 int objc,
2282 Tcl_Obj *CONST objv[]
2283){
2284 sqlite3_stmt *pStmt;
2285
2286 if( objc!=2 ){
2287 Tcl_AppendResult(interp, "wrong # args: should be \"",
2288 Tcl_GetString(objv[0]), " STMT column", 0);
2289 return TCL_ERROR;
2290 }
2291
2292 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2293
2294 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt)));
2295 return TCL_OK;
2296}
2297
2298/*
danielk19773cf86062004-05-26 10:11:05 +00002299** Usage: sqlite3_column_type STMT column
2300**
2301** Return the type of the data in column 'column' of the current row.
2302*/
2303static int test_column_type(
2304 void * clientData,
2305 Tcl_Interp *interp,
2306 int objc,
2307 Tcl_Obj *CONST objv[]
2308){
2309 sqlite3_stmt *pStmt;
2310 int col;
2311 int tp;
2312
2313 if( objc!=3 ){
2314 Tcl_AppendResult(interp, "wrong # args: should be \"",
2315 Tcl_GetString(objv[0]), " STMT column", 0);
2316 return TCL_ERROR;
2317 }
2318
2319 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2320 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2321
2322 tp = sqlite3_column_type(pStmt, col);
2323 switch( tp ){
drh9c054832004-05-31 18:51:57 +00002324 case SQLITE_INTEGER:
danielk19773cf86062004-05-26 10:11:05 +00002325 Tcl_SetResult(interp, "INTEGER", TCL_STATIC);
2326 break;
drh9c054832004-05-31 18:51:57 +00002327 case SQLITE_NULL:
danielk19773cf86062004-05-26 10:11:05 +00002328 Tcl_SetResult(interp, "NULL", TCL_STATIC);
2329 break;
drh9c054832004-05-31 18:51:57 +00002330 case SQLITE_FLOAT:
danielk19773cf86062004-05-26 10:11:05 +00002331 Tcl_SetResult(interp, "FLOAT", TCL_STATIC);
2332 break;
drh9c054832004-05-31 18:51:57 +00002333 case SQLITE_TEXT:
danielk19773cf86062004-05-26 10:11:05 +00002334 Tcl_SetResult(interp, "TEXT", TCL_STATIC);
2335 break;
drh9c054832004-05-31 18:51:57 +00002336 case SQLITE_BLOB:
danielk19773cf86062004-05-26 10:11:05 +00002337 Tcl_SetResult(interp, "BLOB", TCL_STATIC);
2338 break;
2339 default:
2340 assert(0);
2341 }
2342
2343 return TCL_OK;
2344}
2345
2346/*
danielk197704f2e682004-05-27 01:04:07 +00002347** Usage: sqlite3_column_int64 STMT column
danielk19773cf86062004-05-26 10:11:05 +00002348**
2349** Return the data in column 'column' of the current row cast as an
danielk197704f2e682004-05-27 01:04:07 +00002350** wide (64-bit) integer.
danielk19773cf86062004-05-26 10:11:05 +00002351*/
danielk197704f2e682004-05-27 01:04:07 +00002352static int test_column_int64(
danielk19773cf86062004-05-26 10:11:05 +00002353 void * clientData,
2354 Tcl_Interp *interp,
2355 int objc,
2356 Tcl_Obj *CONST objv[]
2357){
2358 sqlite3_stmt *pStmt;
2359 int col;
danielk197704f2e682004-05-27 01:04:07 +00002360 i64 iVal;
danielk19773cf86062004-05-26 10:11:05 +00002361
2362 if( objc!=3 ){
2363 Tcl_AppendResult(interp, "wrong # args: should be \"",
2364 Tcl_GetString(objv[0]), " STMT column", 0);
2365 return TCL_ERROR;
2366 }
2367
2368 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2369 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2370
danielk197704f2e682004-05-27 01:04:07 +00002371 iVal = sqlite3_column_int64(pStmt, col);
2372 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal));
2373 return TCL_OK;
2374}
2375
2376/*
danielk1977ea61b2c2004-05-27 01:49:51 +00002377** Usage: sqlite3_column_blob STMT column
2378*/
2379static int test_column_blob(
2380 void * clientData,
2381 Tcl_Interp *interp,
2382 int objc,
2383 Tcl_Obj *CONST objv[]
2384){
2385 sqlite3_stmt *pStmt;
2386 int col;
2387
2388 int len;
danielk1977c572ef72004-05-27 09:28:41 +00002389 const void *pBlob;
danielk1977ea61b2c2004-05-27 01:49:51 +00002390
2391 if( objc!=3 ){
2392 Tcl_AppendResult(interp, "wrong # args: should be \"",
2393 Tcl_GetString(objv[0]), " STMT column", 0);
2394 return TCL_ERROR;
2395 }
2396
2397 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2398 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2399
2400 pBlob = sqlite3_column_blob(pStmt, col);
2401 len = sqlite3_column_bytes(pStmt, col);
2402 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len));
2403 return TCL_OK;
2404}
2405
2406/*
danielk197704f2e682004-05-27 01:04:07 +00002407** Usage: sqlite3_column_double STMT column
2408**
2409** Return the data in column 'column' of the current row cast as a double.
2410*/
2411static int test_column_double(
2412 void * clientData,
2413 Tcl_Interp *interp,
2414 int objc,
2415 Tcl_Obj *CONST objv[]
2416){
2417 sqlite3_stmt *pStmt;
2418 int col;
2419 double rVal;
2420
2421 if( objc!=3 ){
2422 Tcl_AppendResult(interp, "wrong # args: should be \"",
2423 Tcl_GetString(objv[0]), " STMT column", 0);
2424 return TCL_ERROR;
2425 }
2426
2427 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2428 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2429
2430 rVal = sqlite3_column_double(pStmt, col);
danielk1977c572ef72004-05-27 09:28:41 +00002431 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal));
danielk19773cf86062004-05-26 10:11:05 +00002432 return TCL_OK;
2433}
2434
2435/*
danielk197717240fd2004-05-26 00:07:25 +00002436** Usage: sqlite3_data_count STMT
2437**
2438** Return the number of columns returned by the sql statement STMT.
2439*/
2440static int test_data_count(
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_AppendResult(interp, "wrong # args: should be \"",
2450 Tcl_GetString(objv[0]), " STMT column", 0);
2451 return TCL_ERROR;
2452 }
2453
2454 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2455
2456 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt)));
2457 return TCL_OK;
2458}
2459
2460/*
danielk197704f2e682004-05-27 01:04:07 +00002461** Usage: sqlite3_column_text STMT column
2462**
2463** Usage: sqlite3_column_decltype STMT column
2464**
2465** Usage: sqlite3_column_name STMT column
2466*/
2467static int test_stmt_utf8(
drh241db312004-06-22 12:46:53 +00002468 void * clientData, /* Pointer to SQLite API function to be invoke */
danielk197704f2e682004-05-27 01:04:07 +00002469 Tcl_Interp *interp,
2470 int objc,
2471 Tcl_Obj *CONST objv[]
2472){
2473 sqlite3_stmt *pStmt;
2474 int col;
danielk1977c572ef72004-05-27 09:28:41 +00002475 const char *(*xFunc)(sqlite3_stmt*, int) = clientData;
danielk1977f93bbbe2004-05-27 10:30:52 +00002476 const char *zRet;
danielk197704f2e682004-05-27 01:04:07 +00002477
2478 if( objc!=3 ){
2479 Tcl_AppendResult(interp, "wrong # args: should be \"",
2480 Tcl_GetString(objv[0]), " STMT column", 0);
2481 return TCL_ERROR;
2482 }
2483
2484 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2485 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
danielk1977f93bbbe2004-05-27 10:30:52 +00002486 zRet = xFunc(pStmt, col);
2487 if( zRet ){
2488 Tcl_SetResult(interp, (char *)zRet, 0);
2489 }
danielk197704f2e682004-05-27 01:04:07 +00002490 return TCL_OK;
2491}
2492
danielk19776b456a22005-03-21 04:04:02 +00002493static int test_global_recover(
2494 void * clientData,
2495 Tcl_Interp *interp,
2496 int objc,
2497 Tcl_Obj *CONST objv[]
2498){
2499#ifndef SQLITE_OMIT_GLOBALRECOVER
2500 int rc;
2501 if( objc!=1 ){
2502 Tcl_WrongNumArgs(interp, 1, objv, "");
2503 return TCL_ERROR;
2504 }
2505 rc = sqlite3_global_recover();
2506 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2507#endif
2508 return TCL_OK;
2509}
2510
danielk197704f2e682004-05-27 01:04:07 +00002511/*
2512** Usage: sqlite3_column_text STMT column
2513**
2514** Usage: sqlite3_column_decltype STMT column
2515**
2516** Usage: sqlite3_column_name STMT column
2517*/
2518static int test_stmt_utf16(
drh241db312004-06-22 12:46:53 +00002519 void * clientData, /* Pointer to SQLite API function to be invoked */
danielk197704f2e682004-05-27 01:04:07 +00002520 Tcl_Interp *interp,
2521 int objc,
2522 Tcl_Obj *CONST objv[]
2523){
drh5436dc22004-11-14 04:04:17 +00002524#ifndef SQLITE_OMIT_UTF16
danielk197704f2e682004-05-27 01:04:07 +00002525 sqlite3_stmt *pStmt;
2526 int col;
2527 Tcl_Obj *pRet;
2528 const void *zName16;
danielk1977c572ef72004-05-27 09:28:41 +00002529 const void *(*xFunc)(sqlite3_stmt*, int) = clientData;
danielk197704f2e682004-05-27 01:04:07 +00002530
2531 if( objc!=3 ){
2532 Tcl_AppendResult(interp, "wrong # args: should be \"",
2533 Tcl_GetString(objv[0]), " STMT column", 0);
2534 return TCL_ERROR;
2535 }
2536
2537 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2538 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2539
2540 zName16 = xFunc(pStmt, col);
danielk1977f93bbbe2004-05-27 10:30:52 +00002541 if( zName16 ){
2542 pRet = Tcl_NewByteArrayObj(zName16, sqlite3utf16ByteLen(zName16, -1)+2);
2543 Tcl_SetObjResult(interp, pRet);
2544 }
drh5436dc22004-11-14 04:04:17 +00002545#endif /* SQLITE_OMIT_UTF16 */
danielk197704f2e682004-05-27 01:04:07 +00002546
2547 return TCL_OK;
2548}
2549
2550/*
2551** Usage: sqlite3_column_int STMT column
2552**
2553** Usage: sqlite3_column_bytes STMT column
2554**
2555** Usage: sqlite3_column_bytes16 STMT column
2556**
2557*/
2558static int test_stmt_int(
drh241db312004-06-22 12:46:53 +00002559 void * clientData, /* Pointer to SQLite API function to be invoked */
danielk197704f2e682004-05-27 01:04:07 +00002560 Tcl_Interp *interp,
2561 int objc,
2562 Tcl_Obj *CONST objv[]
2563){
2564 sqlite3_stmt *pStmt;
2565 int col;
danielk1977c572ef72004-05-27 09:28:41 +00002566 int (*xFunc)(sqlite3_stmt*, int) = clientData;
danielk197704f2e682004-05-27 01:04:07 +00002567
2568 if( objc!=3 ){
2569 Tcl_AppendResult(interp, "wrong # args: should be \"",
2570 Tcl_GetString(objv[0]), " STMT column", 0);
2571 return TCL_ERROR;
2572 }
2573
2574 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2575 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2576
2577 Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col)));
2578 return TCL_OK;
2579}
2580
danielk197744ee5bf2005-05-27 09:41:12 +00002581#ifndef SQLITE_OMIT_DISKIO
danielk19779a1d0ab2004-06-01 14:09:28 +00002582/*
2583** Usage: sqlite3OsOpenReadWrite <filename>
2584*/
2585static int test_sqlite3OsOpenReadWrite(
2586 void * clientData,
2587 Tcl_Interp *interp,
2588 int objc,
2589 Tcl_Obj *CONST objv[]
2590){
drh9cbe6352005-11-29 03:13:21 +00002591 OsFile *pFile;
danielk19779a1d0ab2004-06-01 14:09:28 +00002592 int rc;
2593 int dummy;
2594 char zBuf[100];
danielk197704f2e682004-05-27 01:04:07 +00002595
danielk19779a1d0ab2004-06-01 14:09:28 +00002596 if( objc!=2 ){
2597 Tcl_AppendResult(interp, "wrong # args: should be \"",
2598 Tcl_GetString(objv[0]), " filename", 0);
2599 return TCL_ERROR;
2600 }
2601
drh054889e2005-11-30 03:20:31 +00002602 rc = sqlite3Os.xOpenReadWrite(Tcl_GetString(objv[1]), &pFile, &dummy);
danielk19779a1d0ab2004-06-01 14:09:28 +00002603 if( rc!=SQLITE_OK ){
danielk19779a1d0ab2004-06-01 14:09:28 +00002604 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2605 return TCL_ERROR;
2606 }
2607 makePointerStr(interp, zBuf, pFile);
2608 Tcl_SetResult(interp, zBuf, 0);
2609 return TCL_ERROR;
2610}
2611
2612/*
2613** Usage: sqlite3OsClose <file handle>
2614*/
2615static int test_sqlite3OsClose(
2616 void * clientData,
2617 Tcl_Interp *interp,
2618 int objc,
2619 Tcl_Obj *CONST objv[]
2620){
drh9cbe6352005-11-29 03:13:21 +00002621 OsFile *pFile;
danielk19779a1d0ab2004-06-01 14:09:28 +00002622 int rc;
2623
2624 if( objc!=2 ){
2625 Tcl_AppendResult(interp, "wrong # args: should be \"",
2626 Tcl_GetString(objv[0]), " filehandle", 0);
2627 return TCL_ERROR;
2628 }
2629
2630 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
2631 return TCL_ERROR;
2632 }
drh054889e2005-11-30 03:20:31 +00002633 rc = sqlite3OsClose(&pFile);
danielk19779a1d0ab2004-06-01 14:09:28 +00002634 if( rc!=SQLITE_OK ){
2635 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2636 return TCL_ERROR;
2637 }
danielk19779a1d0ab2004-06-01 14:09:28 +00002638 return TCL_OK;
2639}
2640
2641/*
2642** Usage: sqlite3OsLock <file handle> <locktype>
2643*/
2644static int test_sqlite3OsLock(
2645 void * clientData,
2646 Tcl_Interp *interp,
2647 int objc,
2648 Tcl_Obj *CONST objv[]
2649){
2650 OsFile * pFile;
2651 int rc;
2652
2653 if( objc!=3 ){
2654 Tcl_AppendResult(interp, "wrong # args: should be \"",
2655 Tcl_GetString(objv[0]),
2656 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
2657 return TCL_ERROR;
2658 }
2659
2660 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
2661 return TCL_ERROR;
2662 }
2663
2664 if( 0==strcmp("SHARED", Tcl_GetString(objv[2])) ){
drh054889e2005-11-30 03:20:31 +00002665 rc = sqlite3OsLock(pFile, SHARED_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00002666 }
2667 else if( 0==strcmp("RESERVED", Tcl_GetString(objv[2])) ){
drh054889e2005-11-30 03:20:31 +00002668 rc = sqlite3OsLock(pFile, RESERVED_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00002669 }
2670 else if( 0==strcmp("PENDING", Tcl_GetString(objv[2])) ){
drh054889e2005-11-30 03:20:31 +00002671 rc = sqlite3OsLock(pFile, PENDING_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00002672 }
2673 else if( 0==strcmp("EXCLUSIVE", Tcl_GetString(objv[2])) ){
drh054889e2005-11-30 03:20:31 +00002674 rc = sqlite3OsLock(pFile, EXCLUSIVE_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00002675 }else{
2676 Tcl_AppendResult(interp, "wrong # args: should be \"",
2677 Tcl_GetString(objv[0]),
2678 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
2679 return TCL_ERROR;
2680 }
2681
2682 if( rc!=SQLITE_OK ){
2683 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2684 return TCL_ERROR;
2685 }
2686 return TCL_OK;
2687}
2688
2689/*
2690** Usage: sqlite3OsUnlock <file handle>
2691*/
2692static int test_sqlite3OsUnlock(
2693 void * clientData,
2694 Tcl_Interp *interp,
2695 int objc,
2696 Tcl_Obj *CONST objv[]
2697){
2698 OsFile * pFile;
2699 int rc;
2700
2701 if( objc!=2 ){
2702 Tcl_AppendResult(interp, "wrong # args: should be \"",
2703 Tcl_GetString(objv[0]), " filehandle", 0);
2704 return TCL_ERROR;
2705 }
2706
2707 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
2708 return TCL_ERROR;
2709 }
drh054889e2005-11-30 03:20:31 +00002710 rc = sqlite3OsUnlock(pFile, NO_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00002711 if( rc!=SQLITE_OK ){
2712 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2713 return TCL_ERROR;
2714 }
2715 return TCL_OK;
2716}
drhd3d39e92004-05-20 22:16:29 +00002717
drhab3f9fe2004-08-14 17:10:10 +00002718/*
2719** Usage: sqlite3OsTempFileName
2720*/
2721static int test_sqlite3OsTempFileName(
2722 void * clientData,
2723 Tcl_Interp *interp,
2724 int objc,
2725 Tcl_Obj *CONST objv[]
2726){
2727 char zFile[SQLITE_TEMPNAME_SIZE];
2728 int rc;
2729
drh054889e2005-11-30 03:20:31 +00002730 rc = sqlite3Os.xTempFileName(zFile);
drhab3f9fe2004-08-14 17:10:10 +00002731 if( rc!=SQLITE_OK ){
2732 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2733 return TCL_ERROR;
2734 }
2735 Tcl_AppendResult(interp, zFile, 0);
2736 return TCL_OK;
2737}
danielk197744ee5bf2005-05-27 09:41:12 +00002738#endif
danielk1977d8123362004-06-12 09:25:12 +00002739
danielk19776622cce2004-05-20 11:00:52 +00002740/*
drhcacb2082005-01-11 15:28:33 +00002741** Usage: sqlite_set_magic DB MAGIC-NUMBER
2742**
2743** Set the db->magic value. This is used to test error recovery logic.
2744*/
2745static int sqlite_set_magic(
2746 void * clientData,
2747 Tcl_Interp *interp,
2748 int argc,
2749 char **argv
2750){
2751 sqlite3 *db;
2752 if( argc!=3 ){
2753 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2754 " DB MAGIC", 0);
2755 return TCL_ERROR;
2756 }
2757 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2758 if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){
2759 db->magic = SQLITE_MAGIC_OPEN;
2760 }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){
2761 db->magic = SQLITE_MAGIC_CLOSED;
2762 }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){
2763 db->magic = SQLITE_MAGIC_BUSY;
2764 }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){
2765 db->magic = SQLITE_MAGIC_ERROR;
2766 }else if( Tcl_GetInt(interp, argv[2], &db->magic) ){
2767 return TCL_ERROR;
2768 }
2769 return TCL_OK;
2770}
2771
2772/*
drhc5cdca62005-01-11 16:54:14 +00002773** Usage: sqlite3_interrupt DB
2774**
2775** Trigger an interrupt on DB
2776*/
2777static int test_interrupt(
2778 void * clientData,
2779 Tcl_Interp *interp,
2780 int argc,
2781 char **argv
2782){
2783 sqlite3 *db;
2784 if( argc!=2 ){
2785 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
2786 return TCL_ERROR;
2787 }
2788 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2789 sqlite3_interrupt(db);
2790 return TCL_OK;
2791}
2792
drh79158e12005-09-06 21:40:45 +00002793static u8 *sqlite3_stack_baseline = 0;
2794
drhc5cdca62005-01-11 16:54:14 +00002795/*
drh79158e12005-09-06 21:40:45 +00002796** Fill the stack with a known bitpattern.
danielk1977600dd0b2005-01-20 01:14:23 +00002797*/
drh79158e12005-09-06 21:40:45 +00002798static void prepStack(void){
2799 int i;
2800 u32 bigBuf[65536];
2801 for(i=0; i<sizeof(bigBuf); i++) bigBuf[i] = 0xdeadbeef;
2802 sqlite3_stack_baseline = (u8*)&bigBuf[65536];
2803}
2804
2805/*
2806** Get the current stack depth. Used for debugging only.
2807*/
2808u64 sqlite3StackDepth(void){
2809 u8 x;
2810 return (u64)(sqlite3_stack_baseline - &x);
2811}
2812
2813/*
2814** Usage: sqlite3_stack_used DB SQL
2815**
2816** Try to measure the amount of stack space used by a call to sqlite3_exec
2817*/
2818static int test_stack_used(
danielk1977600dd0b2005-01-20 01:14:23 +00002819 void * clientData,
2820 Tcl_Interp *interp,
2821 int argc,
2822 char **argv
2823){
2824 sqlite3 *db;
drh79158e12005-09-06 21:40:45 +00002825 int i;
2826 if( argc!=3 ){
2827 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2828 " DB SQL", 0);
danielk1977600dd0b2005-01-20 01:14:23 +00002829 return TCL_ERROR;
2830 }
drh79158e12005-09-06 21:40:45 +00002831 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2832 prepStack();
2833 sqlite3_exec(db, argv[2], 0, 0, 0);
2834 for(i=65535; i>=0 && ((u32*)sqlite3_stack_baseline)[-i]==0xdeadbeef; i--){}
2835 Tcl_SetObjResult(interp, Tcl_NewIntObj(i*4));
danielk1977600dd0b2005-01-20 01:14:23 +00002836 return TCL_OK;
2837}
danielk1977600dd0b2005-01-20 01:14:23 +00002838
2839/*
danielk19779636c4e2005-01-25 04:27:54 +00002840** Usage: sqlite_delete_function DB function-name
2841**
2842** Delete the user function 'function-name' from database handle DB. It
2843** is assumed that the user function was created as UTF8, any number of
2844** arguments (the way the TCL interface does it).
2845*/
2846static int delete_function(
2847 void * clientData,
2848 Tcl_Interp *interp,
2849 int argc,
2850 char **argv
2851){
2852 int rc;
2853 sqlite3 *db;
2854 if( argc!=3 ){
2855 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2856 " DB function-name", 0);
2857 return TCL_ERROR;
2858 }
2859 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2860 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0);
2861 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2862 return TCL_OK;
2863}
2864
2865/*
2866** Usage: sqlite_delete_collation DB collation-name
2867**
2868** Delete the collation sequence 'collation-name' from database handle
2869** DB. It is assumed that the collation sequence was created as UTF8 (the
2870** way the TCL interface does it).
2871*/
2872static int delete_collation(
2873 void * clientData,
2874 Tcl_Interp *interp,
2875 int argc,
2876 char **argv
2877){
2878 int rc;
2879 sqlite3 *db;
2880 if( argc!=3 ){
2881 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2882 " DB function-name", 0);
2883 return TCL_ERROR;
2884 }
2885 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2886 rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0);
2887 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2888 return TCL_OK;
2889}
2890
2891/*
drh3e1d8e62005-05-26 16:23:34 +00002892** Usage: sqlite3_get_autocommit DB
2893**
2894** Return true if the database DB is currently in auto-commit mode.
2895** Return false if not.
2896*/
2897static int get_autocommit(
2898 void * clientData,
2899 Tcl_Interp *interp,
2900 int argc,
2901 char **argv
2902){
2903 char zBuf[30];
2904 sqlite3 *db;
2905 if( argc!=2 ){
2906 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2907 " DB", 0);
2908 return TCL_ERROR;
2909 }
2910 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2911 sprintf(zBuf, "%d", sqlite3_get_autocommit(db));
2912 Tcl_AppendResult(interp, zBuf, 0);
2913 return TCL_OK;
2914}
2915
2916/*
drh92febd92004-08-20 18:34:20 +00002917** Usage: tcl_variable_type VARIABLENAME
2918**
2919** Return the name of the internal representation for the
2920** value of the given variable.
2921*/
2922static int tcl_variable_type(
2923 void * clientData,
2924 Tcl_Interp *interp,
2925 int objc,
2926 Tcl_Obj *CONST objv[]
2927){
2928 Tcl_Obj *pVar;
2929 if( objc!=2 ){
2930 Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE");
2931 return TCL_ERROR;
2932 }
2933 pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG);
2934 if( pVar==0 ) return TCL_ERROR;
2935 if( pVar->typePtr ){
2936 Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1));
2937 }
2938 return TCL_OK;
2939}
2940
2941/*
drh6aafc292006-01-05 15:50:06 +00002942** Usage: sqlite3_release_memory ?N?
2943**
2944** Attempt to release memory currently held but not actually required.
2945** The integer N is the number of bytes we are trying to release. The
2946** return value is the amount of memory actually released.
2947*/
2948static int test_release_memory(
2949 void * clientData,
2950 Tcl_Interp *interp,
2951 int objc,
2952 Tcl_Obj *CONST objv[]
2953){
2954#ifndef SQLITE_OMIT_MEMORY_MANAGEMENT
2955 int N;
2956 int amt;
2957 if( objc!=1 && objc!=2 ){
2958 Tcl_WrongNumArgs(interp, 1, objv, "?N?");
2959 return TCL_ERROR;
2960 }
2961 if( objc==2 ){
2962 if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
2963 }else{
2964 N = -1;
2965 }
2966 amt = sqlite3_release_memory(N);
2967 Tcl_SetObjResult(interp, Tcl_NewIntObj(amt));
2968#endif
2969 return TCL_OK;
2970}
2971
2972/*
2973** Usage: sqlite3_soft_heap_limit ?N?
2974**
2975** Query or set the soft heap limit for the current thread. The
2976** limit is only changed if the N is present. The previous limit
2977** is returned.
2978*/
2979static int test_soft_heap_limit(
2980 void * clientData,
2981 Tcl_Interp *interp,
2982 int objc,
2983 Tcl_Obj *CONST objv[]
2984){
2985#ifndef SQLITE_OMIT_MEMORY_MANAGEMENT
2986 int amt;
2987 if( objc!=1 && objc!=2 ){
2988 Tcl_WrongNumArgs(interp, 1, objv, "?N?");
2989 return TCL_ERROR;
2990 }
2991 amt = sqlite3Tsd()->nSoftHeapLimit;
2992 if( objc==2 ){
2993 int N;
2994 if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
2995 sqlite3_soft_heap_limit(N);
2996 }
2997 Tcl_SetObjResult(interp, Tcl_NewIntObj(amt));
2998#endif
2999 return TCL_OK;
3000}
3001
3002/*
drh27d258a2004-10-30 20:23:09 +00003003** This routine sets entries in the global ::sqlite_options() array variable
3004** according to the compile-time configuration of the database. Test
3005** procedures use this to determine when tests should be omitted.
3006*/
3007static void set_options(Tcl_Interp *interp){
drh75f86a42005-02-17 00:03:06 +00003008#ifdef SQLITE_32BIT_ROWID
3009 Tcl_SetVar2(interp, "sqlite_options", "rowid32", "1", TCL_GLOBAL_ONLY);
3010#else
3011 Tcl_SetVar2(interp, "sqlite_options", "rowid32", "0", TCL_GLOBAL_ONLY);
3012#endif
3013
drh9f18e8a2005-07-08 12:13:04 +00003014#ifdef SQLITE_CASE_SENSITIVE_LIKE
3015 Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","1",TCL_GLOBAL_ONLY);
3016#else
3017 Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","0",TCL_GLOBAL_ONLY);
3018#endif
3019
danielk1977d7c03f72005-11-25 10:38:22 +00003020#ifdef SQLITE_DISABLE_DIRSYNC
3021 Tcl_SetVar2(interp, "sqlite_options", "dirsync", "0", TCL_GLOBAL_ONLY);
3022#else
3023 Tcl_SetVar2(interp, "sqlite_options", "dirsync", "1", TCL_GLOBAL_ONLY);
3024#endif
3025
danielk197726c5d792005-11-25 09:01:23 +00003026#ifdef SQLITE_DISABLE_LFS
3027 Tcl_SetVar2(interp, "sqlite_options", "lfs", "0", TCL_GLOBAL_ONLY);
3028#else
3029 Tcl_SetVar2(interp, "sqlite_options", "lfs", "1", TCL_GLOBAL_ONLY);
3030#endif
3031
danielk19771c8c23c2004-11-12 15:53:37 +00003032#ifdef SQLITE_OMIT_ALTERTABLE
3033 Tcl_SetVar2(interp, "sqlite_options", "altertable", "0", TCL_GLOBAL_ONLY);
3034#else
3035 Tcl_SetVar2(interp, "sqlite_options", "altertable", "1", TCL_GLOBAL_ONLY);
3036#endif
drh13d70422004-11-13 15:59:14 +00003037
drh9f18e8a2005-07-08 12:13:04 +00003038#ifdef SQLITE_OMIT_ANALYZE
3039 Tcl_SetVar2(interp, "sqlite_options", "analyze", "0", TCL_GLOBAL_ONLY);
3040#else
3041 Tcl_SetVar2(interp, "sqlite_options", "analyze", "1", TCL_GLOBAL_ONLY);
3042#endif
3043
drh13d70422004-11-13 15:59:14 +00003044#ifdef SQLITE_OMIT_AUTHORIZATION
3045 Tcl_SetVar2(interp, "sqlite_options", "auth", "0", TCL_GLOBAL_ONLY);
3046#else
3047 Tcl_SetVar2(interp, "sqlite_options", "auth", "1", TCL_GLOBAL_ONLY);
3048#endif
3049
drhf3388142004-11-13 03:48:06 +00003050#ifdef SQLITE_OMIT_AUTOINCREMENT
3051 Tcl_SetVar2(interp, "sqlite_options", "autoinc", "0", TCL_GLOBAL_ONLY);
3052#else
3053 Tcl_SetVar2(interp, "sqlite_options", "autoinc", "1", TCL_GLOBAL_ONLY);
3054#endif
3055
danielk197745901d62004-11-10 15:27:38 +00003056#ifdef SQLITE_OMIT_AUTOVACUUM
3057 Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "0", TCL_GLOBAL_ONLY);
3058#else
3059 Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "1", TCL_GLOBAL_ONLY);
drhf3388142004-11-13 03:48:06 +00003060#endif /* SQLITE_OMIT_AUTOVACUUM */
danielk19774d36b812004-11-19 07:07:30 +00003061#if !defined(SQLITE_DEFAULT_AUTOVACUUM) || SQLITE_DEFAULT_AUTOVACUUM==0
danielk197745901d62004-11-10 15:27:38 +00003062 Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","0",TCL_GLOBAL_ONLY);
3063#else
3064 Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","1",TCL_GLOBAL_ONLY);
3065#endif
drh13d70422004-11-13 15:59:14 +00003066
drh55ef4d92005-08-14 01:20:37 +00003067#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
3068 Tcl_SetVar2(interp, "sqlite_options", "between_opt", "0", TCL_GLOBAL_ONLY);
3069#else
3070 Tcl_SetVar2(interp, "sqlite_options", "between_opt", "1", TCL_GLOBAL_ONLY);
3071#endif
3072
drh13d70422004-11-13 15:59:14 +00003073#ifdef SQLITE_OMIT_BLOB_LITERAL
3074 Tcl_SetVar2(interp, "sqlite_options", "bloblit", "0", TCL_GLOBAL_ONLY);
3075#else
3076 Tcl_SetVar2(interp, "sqlite_options", "bloblit", "1", TCL_GLOBAL_ONLY);
3077#endif
3078
drh487e2622005-06-25 18:42:14 +00003079#ifdef SQLITE_OMIT_CAST
3080 Tcl_SetVar2(interp, "sqlite_options", "cast", "0", TCL_GLOBAL_ONLY);
3081#else
3082 Tcl_SetVar2(interp, "sqlite_options", "cast", "1", TCL_GLOBAL_ONLY);
3083#endif
3084
drhffe07b22005-11-03 00:41:17 +00003085#ifdef SQLITE_OMIT_CHECK
3086 Tcl_SetVar2(interp, "sqlite_options", "check", "0", TCL_GLOBAL_ONLY);
3087#else
3088 Tcl_SetVar2(interp, "sqlite_options", "check", "1", TCL_GLOBAL_ONLY);
3089#endif
3090
drhccae6022005-02-26 17:31:26 +00003091#ifdef SQLITE_OMIT_COMPLETE
3092 Tcl_SetVar2(interp, "sqlite_options", "complete", "0", TCL_GLOBAL_ONLY);
3093#else
3094 Tcl_SetVar2(interp, "sqlite_options", "complete", "1", TCL_GLOBAL_ONLY);
3095#endif
3096
drh13d70422004-11-13 15:59:14 +00003097#ifdef SQLITE_OMIT_COMPOUND_SELECT
3098 Tcl_SetVar2(interp, "sqlite_options", "compound", "0", TCL_GLOBAL_ONLY);
3099#else
3100 Tcl_SetVar2(interp, "sqlite_options", "compound", "1", TCL_GLOBAL_ONLY);
3101#endif
3102
3103#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
3104 Tcl_SetVar2(interp, "sqlite_options", "conflict", "0", TCL_GLOBAL_ONLY);
3105#else
3106 Tcl_SetVar2(interp, "sqlite_options", "conflict", "1", TCL_GLOBAL_ONLY);
3107#endif
3108
3109#ifdef SQLITE_OMIT_DATETIME_FUNCS
3110 Tcl_SetVar2(interp, "sqlite_options", "datetime", "0", TCL_GLOBAL_ONLY);
3111#else
3112 Tcl_SetVar2(interp, "sqlite_options", "datetime", "1", TCL_GLOBAL_ONLY);
3113#endif
3114
drh2e66f0b2005-04-28 17:18:48 +00003115#ifdef SQLITE_OMIT_DISKIO
3116 Tcl_SetVar2(interp, "sqlite_options", "diskio", "0", TCL_GLOBAL_ONLY);
3117#else
3118 Tcl_SetVar2(interp, "sqlite_options", "diskio", "1", TCL_GLOBAL_ONLY);
3119#endif
3120
drh13d70422004-11-13 15:59:14 +00003121#ifdef SQLITE_OMIT_EXPLAIN
3122 Tcl_SetVar2(interp, "sqlite_options", "explain", "0", TCL_GLOBAL_ONLY);
3123#else
3124 Tcl_SetVar2(interp, "sqlite_options", "explain", "1", TCL_GLOBAL_ONLY);
3125#endif
3126
3127#ifdef SQLITE_OMIT_FLOATING_POINT
3128 Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "0", TCL_GLOBAL_ONLY);
3129#else
3130 Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "1", TCL_GLOBAL_ONLY);
3131#endif
3132
3133#ifdef SQLITE_OMIT_FOREIGN_KEY
3134 Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "0", TCL_GLOBAL_ONLY);
3135#else
3136 Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "1", TCL_GLOBAL_ONLY);
3137#endif
3138
danielk19776b456a22005-03-21 04:04:02 +00003139#ifdef SQLITE_OMIT_GLOBALRECOVER
3140 Tcl_SetVar2(interp, "sqlite_options", "globalrecover", "0", TCL_GLOBAL_ONLY);
3141#else
3142 Tcl_SetVar2(interp, "sqlite_options", "globalrecover", "1", TCL_GLOBAL_ONLY);
3143#endif
3144
drh13d70422004-11-13 15:59:14 +00003145#ifdef SQLITE_OMIT_INTEGRITY_CHECK
3146 Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
3147#else
3148 Tcl_SetVar2(interp, "sqlite_options", "integrityck", "1", TCL_GLOBAL_ONLY);
3149#endif
3150
drh55ef4d92005-08-14 01:20:37 +00003151#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
3152 Tcl_SetVar2(interp, "sqlite_options", "like_opt", "0", TCL_GLOBAL_ONLY);
3153#else
3154 Tcl_SetVar2(interp, "sqlite_options", "like_opt", "1", TCL_GLOBAL_ONLY);
3155#endif
3156
drh13d70422004-11-13 15:59:14 +00003157#ifdef SQLITE_OMIT_MEMORYDB
3158 Tcl_SetVar2(interp, "sqlite_options", "memorydb", "0", TCL_GLOBAL_ONLY);
3159#else
3160 Tcl_SetVar2(interp, "sqlite_options", "memorydb", "1", TCL_GLOBAL_ONLY);
3161#endif
3162
drh6aafc292006-01-05 15:50:06 +00003163#ifdef SQLITE_OMIT_MEMORY_MANAGEMENT
3164 Tcl_SetVar2(interp, "sqlite_options", "memorymanage", "0", TCL_GLOBAL_ONLY);
3165#else
3166 Tcl_SetVar2(interp, "sqlite_options", "memorymanage", "1", TCL_GLOBAL_ONLY);
3167#endif
3168
drh55ef4d92005-08-14 01:20:37 +00003169#ifdef SQLITE_OMIT_OR_OPTIMIZATION
3170 Tcl_SetVar2(interp, "sqlite_options", "or_opt", "0", TCL_GLOBAL_ONLY);
3171#else
3172 Tcl_SetVar2(interp, "sqlite_options", "or_opt", "1", TCL_GLOBAL_ONLY);
3173#endif
3174
drh13d70422004-11-13 15:59:14 +00003175#ifdef SQLITE_OMIT_PAGER_PRAGMAS
3176 Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "0", TCL_GLOBAL_ONLY);
3177#else
3178 Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "1", TCL_GLOBAL_ONLY);
3179#endif
3180
drh2e66f0b2005-04-28 17:18:48 +00003181#ifdef SQLITE_OMIT_PARSER
3182 Tcl_SetVar2(interp, "sqlite_options", "parser", "0", TCL_GLOBAL_ONLY);
3183#else
3184 Tcl_SetVar2(interp, "sqlite_options", "parser", "1", TCL_GLOBAL_ONLY);
3185#endif
3186
drhbf216272005-02-26 18:10:44 +00003187#if defined(SQLITE_OMIT_PRAGMA) || defined(SQLITE_OMIT_FLAG_PRAGMAS)
drh13d70422004-11-13 15:59:14 +00003188 Tcl_SetVar2(interp, "sqlite_options", "pragma", "0", TCL_GLOBAL_ONLY);
3189 Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
3190#else
3191 Tcl_SetVar2(interp, "sqlite_options", "pragma", "1", TCL_GLOBAL_ONLY);
3192#endif
3193
3194#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
3195 Tcl_SetVar2(interp, "sqlite_options", "progress", "0", TCL_GLOBAL_ONLY);
3196#else
3197 Tcl_SetVar2(interp, "sqlite_options", "progress", "1", TCL_GLOBAL_ONLY);
3198#endif
3199
3200#ifdef SQLITE_OMIT_REINDEX
3201 Tcl_SetVar2(interp, "sqlite_options", "reindex", "0", TCL_GLOBAL_ONLY);
3202#else
3203 Tcl_SetVar2(interp, "sqlite_options", "reindex", "1", TCL_GLOBAL_ONLY);
3204#endif
3205
3206#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
3207 Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "0", TCL_GLOBAL_ONLY);
3208#else
3209 Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "1", TCL_GLOBAL_ONLY);
3210#endif
3211
3212#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
3213 Tcl_SetVar2(interp, "sqlite_options", "schema_version", "0", TCL_GLOBAL_ONLY);
3214#else
3215 Tcl_SetVar2(interp, "sqlite_options", "schema_version", "1", TCL_GLOBAL_ONLY);
3216#endif
3217
danielk1977aef0bf62005-12-30 16:28:01 +00003218#ifdef SQLITE_OMIT_SHARED_CACHE
3219 Tcl_SetVar2(interp, "sqlite_options", "shared_cache", "0", TCL_GLOBAL_ONLY);
3220#else
3221 Tcl_SetVar2(interp, "sqlite_options", "shared_cache", "1", TCL_GLOBAL_ONLY);
3222#endif
3223
danielk19773e8c37e2005-01-21 03:12:14 +00003224#ifdef SQLITE_OMIT_SUBQUERY
3225 Tcl_SetVar2(interp, "sqlite_options", "subquery", "0", TCL_GLOBAL_ONLY);
3226#else
3227 Tcl_SetVar2(interp, "sqlite_options", "subquery", "1", TCL_GLOBAL_ONLY);
3228#endif
3229
drh13d70422004-11-13 15:59:14 +00003230#ifdef SQLITE_OMIT_TCL_VARIABLE
3231 Tcl_SetVar2(interp, "sqlite_options", "tclvar", "0", TCL_GLOBAL_ONLY);
3232#else
3233 Tcl_SetVar2(interp, "sqlite_options", "tclvar", "1", TCL_GLOBAL_ONLY);
3234#endif
3235
3236#if defined(THREADSAFE) && THREADSAFE
3237 Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "1", TCL_GLOBAL_ONLY);
3238#else
3239 Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "0", TCL_GLOBAL_ONLY);
3240#endif
3241
drh19e2d372005-08-29 23:00:03 +00003242#ifdef SQLITE_OMIT_TRACE
3243 Tcl_SetVar2(interp, "sqlite_options", "trace", "0", TCL_GLOBAL_ONLY);
3244#else
3245 Tcl_SetVar2(interp, "sqlite_options", "trace", "1", TCL_GLOBAL_ONLY);
3246#endif
3247
drh13d70422004-11-13 15:59:14 +00003248#ifdef SQLITE_OMIT_TRIGGER
3249 Tcl_SetVar2(interp, "sqlite_options", "trigger", "0", TCL_GLOBAL_ONLY);
3250#else
3251 Tcl_SetVar2(interp, "sqlite_options", "trigger", "1", TCL_GLOBAL_ONLY);
3252#endif
3253
danielk197753c0f742005-03-29 03:10:59 +00003254#ifdef SQLITE_OMIT_TEMPDB
3255 Tcl_SetVar2(interp, "sqlite_options", "tempdb", "0", TCL_GLOBAL_ONLY);
3256#else
3257 Tcl_SetVar2(interp, "sqlite_options", "tempdb", "1", TCL_GLOBAL_ONLY);
3258#endif
3259
drh13d70422004-11-13 15:59:14 +00003260#ifdef SQLITE_OMIT_UTF16
3261 Tcl_SetVar2(interp, "sqlite_options", "utf16", "0", TCL_GLOBAL_ONLY);
3262#else
3263 Tcl_SetVar2(interp, "sqlite_options", "utf16", "1", TCL_GLOBAL_ONLY);
3264#endif
3265
3266#ifdef SQLITE_OMIT_VACUUM
3267 Tcl_SetVar2(interp, "sqlite_options", "vacuum", "0", TCL_GLOBAL_ONLY);
3268#else
3269 Tcl_SetVar2(interp, "sqlite_options", "vacuum", "1", TCL_GLOBAL_ONLY);
3270#endif
3271
3272#ifdef SQLITE_OMIT_VIEW
3273 Tcl_SetVar2(interp, "sqlite_options", "view", "0", TCL_GLOBAL_ONLY);
3274#else
3275 Tcl_SetVar2(interp, "sqlite_options", "view", "1", TCL_GLOBAL_ONLY);
3276#endif
drh27d258a2004-10-30 20:23:09 +00003277}
3278
3279/*
drhd1bf3512001-04-07 15:24:33 +00003280** Register commands with the TCL interpreter.
3281*/
3282int Sqlitetest1_Init(Tcl_Interp *interp){
danielk19776f8a5032004-05-10 10:34:51 +00003283 extern int sqlite3_search_count;
3284 extern int sqlite3_interrupt_count;
3285 extern int sqlite3_open_file_count;
drh6bf89572004-11-03 16:27:01 +00003286 extern int sqlite3_sort_count;
danielk19776f8a5032004-05-10 10:34:51 +00003287 extern int sqlite3_current_time;
drhc2eef3b2002-08-31 18:53:06 +00003288 static struct {
3289 char *zName;
3290 Tcl_CmdProc *xProc;
3291 } aCmd[] = {
drhd3d39e92004-05-20 22:16:29 +00003292 { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int },
drhe9707672004-06-25 01:10:48 +00003293 { "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 },
drhd3d39e92004-05-20 22:16:29 +00003294 { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str },
drhe29b1a02004-07-17 21:56:09 +00003295 { "sqlite3_mprintf_stronly", (Tcl_CmdProc*)sqlite3_mprintf_stronly},
drhd3d39e92004-05-20 22:16:29 +00003296 { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double },
3297 { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled },
drh63782852005-08-30 19:30:59 +00003298 { "sqlite3_mprintf_hexdouble", (Tcl_CmdProc*)sqlite3_mprintf_hexdouble},
drhd3d39e92004-05-20 22:16:29 +00003299 { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z },
drhd3d39e92004-05-20 22:16:29 +00003300 { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid },
3301 { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf },
3302 { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf },
3303 { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close },
3304 { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function },
3305 { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate },
3306 { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func },
3307 { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort },
danielk19772c336542005-01-13 02:14:23 +00003308#ifdef SQLITE_MEMDEBUG
drhd3d39e92004-05-20 22:16:29 +00003309 { "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail },
3310 { "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat },
drhc2eef3b2002-08-31 18:53:06 +00003311#endif
drh25d65432004-07-22 15:02:25 +00003312 { "sqlite_bind", (Tcl_CmdProc*)test_bind },
3313 { "breakpoint", (Tcl_CmdProc*)test_breakpoint },
3314 { "sqlite3_key", (Tcl_CmdProc*)test_key },
3315 { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey },
drhcacb2082005-01-11 15:28:33 +00003316 { "sqlite_set_magic", (Tcl_CmdProc*)sqlite_set_magic },
drhc5cdca62005-01-11 16:54:14 +00003317 { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt },
danielk1977600dd0b2005-01-20 01:14:23 +00003318#if 0
3319 { "sqlite3_sleep", (Tcl_CmdProc*)test_sleep },
3320#endif
drh3e1d8e62005-05-26 16:23:34 +00003321 { "sqlite_delete_function", (Tcl_CmdProc*)delete_function },
3322 { "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation },
3323 { "sqlite3_get_autocommit", (Tcl_CmdProc*)get_autocommit },
drh79158e12005-09-06 21:40:45 +00003324 { "sqlite3_stack_used", (Tcl_CmdProc*)test_stack_used },
drhc2eef3b2002-08-31 18:53:06 +00003325 };
danielk197751e3d8e2004-05-20 01:12:34 +00003326 static struct {
3327 char *zName;
3328 Tcl_ObjCmdProc *xProc;
danielk197704f2e682004-05-27 01:04:07 +00003329 void *clientData;
danielk197751e3d8e2004-05-20 01:12:34 +00003330 } aObjCmd[] = {
drhdddca282006-01-03 00:33:50 +00003331 { "sqlite3_connection_pointer", get_sqlite_pointer, 0 },
drh241db312004-06-22 12:46:53 +00003332 { "sqlite3_bind_int", test_bind_int, 0 },
3333 { "sqlite3_bind_int64", test_bind_int64, 0 },
3334 { "sqlite3_bind_double", test_bind_double, 0 },
danielk197704f2e682004-05-27 01:04:07 +00003335 { "sqlite3_bind_null", test_bind_null ,0 },
3336 { "sqlite3_bind_text", test_bind_text ,0 },
3337 { "sqlite3_bind_text16", test_bind_text16 ,0 },
3338 { "sqlite3_bind_blob", test_bind_blob ,0 },
drh75f6a032004-07-15 14:15:00 +00003339 { "sqlite3_bind_parameter_count", test_bind_parameter_count, 0},
drh895d7472004-08-20 16:02:39 +00003340 { "sqlite3_bind_parameter_name", test_bind_parameter_name, 0},
drhfa6bc002004-09-07 16:19:52 +00003341 { "sqlite3_bind_parameter_index", test_bind_parameter_index, 0},
danielk1977600dd0b2005-01-20 01:14:23 +00003342#if 0
3343 { "sqlite3_clear_bindings", test_clear_bindings, 0},
3344#endif
danielk197704f2e682004-05-27 01:04:07 +00003345 { "sqlite3_errcode", test_errcode ,0 },
3346 { "sqlite3_errmsg", test_errmsg ,0 },
3347 { "sqlite3_errmsg16", test_errmsg16 ,0 },
3348 { "sqlite3_open", test_open ,0 },
3349 { "sqlite3_open16", test_open16 ,0 },
danielk1977bc6ada42004-06-30 08:20:16 +00003350 { "sqlite3_complete16", test_complete16 ,0 },
danielk197704f2e682004-05-27 01:04:07 +00003351
3352 { "sqlite3_prepare", test_prepare ,0 },
3353 { "sqlite3_prepare16", test_prepare16 ,0 },
3354 { "sqlite3_finalize", test_finalize ,0 },
3355 { "sqlite3_reset", test_reset ,0 },
drhd89bd002005-01-22 03:03:54 +00003356 { "sqlite3_expired", test_expired ,0 },
drhf8db1bc2005-04-22 02:38:37 +00003357 { "sqlite3_transfer_bindings", test_transfer_bind ,0 },
danielk1977fbcd5852004-06-15 02:44:18 +00003358 { "sqlite3_changes", test_changes ,0 },
3359 { "sqlite3_step", test_step ,0 },
danielk197704f2e682004-05-27 01:04:07 +00003360
drh6aafc292006-01-05 15:50:06 +00003361 { "sqlite3_release_memory", test_release_memory, 0},
3362 { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0},
3363
danielk197704f2e682004-05-27 01:04:07 +00003364 /* sqlite3_column_*() API */
3365 { "sqlite3_column_count", test_column_count ,0 },
3366 { "sqlite3_data_count", test_data_count ,0 },
3367 { "sqlite3_column_type", test_column_type ,0 },
danielk1977ea61b2c2004-05-27 01:49:51 +00003368 { "sqlite3_column_blob", test_column_blob ,0 },
danielk197704f2e682004-05-27 01:04:07 +00003369 { "sqlite3_column_double", test_column_double ,0 },
3370 { "sqlite3_column_int64", test_column_int64 ,0 },
drh241db312004-06-22 12:46:53 +00003371 { "sqlite3_column_text", test_stmt_utf8, sqlite3_column_text },
3372 { "sqlite3_column_decltype", test_stmt_utf8, sqlite3_column_decltype },
3373 { "sqlite3_column_name", test_stmt_utf8, sqlite3_column_name },
drh6c626082004-11-14 21:56:29 +00003374 { "sqlite3_column_int", test_stmt_int, sqlite3_column_int },
3375 { "sqlite3_column_bytes", test_stmt_int, sqlite3_column_bytes },
3376#ifndef SQLITE_OMIT_UTF16
3377 { "sqlite3_column_bytes16", test_stmt_int, sqlite3_column_bytes16 },
drh241db312004-06-22 12:46:53 +00003378 { "sqlite3_column_text16", test_stmt_utf16, sqlite3_column_text16 },
3379 { "sqlite3_column_decltype16", test_stmt_utf16, sqlite3_column_decltype16},
3380 { "sqlite3_column_name16", test_stmt_utf16, sqlite3_column_name16 },
drh6c626082004-11-14 21:56:29 +00003381#endif
danielk19776b456a22005-03-21 04:04:02 +00003382 { "sqlite3_global_recover", test_global_recover, 0 },
danielk197704f2e682004-05-27 01:04:07 +00003383
danielk19779a1d0ab2004-06-01 14:09:28 +00003384 /* Functions from os.h */
danielk197744ee5bf2005-05-27 09:41:12 +00003385#ifndef SQLITE_OMIT_DISKIO
danielk19779a1d0ab2004-06-01 14:09:28 +00003386 { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 },
3387 { "sqlite3OsClose", test_sqlite3OsClose, 0 },
3388 { "sqlite3OsLock", test_sqlite3OsLock, 0 },
drhab3f9fe2004-08-14 17:10:10 +00003389 { "sqlite3OsTempFileName", test_sqlite3OsTempFileName, 0 },
danielk1977312d6b32004-06-29 13:18:23 +00003390
3391 /* Custom test interfaces */
3392 { "sqlite3OsUnlock", test_sqlite3OsUnlock, 0 },
danielk197744ee5bf2005-05-27 09:41:12 +00003393#endif
drh5436dc22004-11-14 04:04:17 +00003394#ifndef SQLITE_OMIT_UTF16
danielk1977312d6b32004-06-29 13:18:23 +00003395 { "add_test_collate", test_collate, 0 },
3396 { "add_test_collate_needed", test_collate_needed, 0 },
3397 { "add_test_function", test_function, 0 },
drh5436dc22004-11-14 04:04:17 +00003398#endif
danielk19775591df52005-12-20 09:19:37 +00003399#ifdef SQLITE_MEMDEBUG
3400 { "sqlite_malloc_outstanding", sqlite_malloc_outstanding, 0},
3401#endif
danielk1977312d6b32004-06-29 13:18:23 +00003402 { "sqlite3_test_errstr", test_errstr, 0 },
drh92febd92004-08-20 18:34:20 +00003403 { "tcl_variable_type", tcl_variable_type, 0 },
danielk1977aef0bf62005-12-30 16:28:01 +00003404#ifndef SQLITE_OMIT_SHARED_CACHE
3405 { "sqlite3_enable_shared_cache", test_enable_shared_cache, 0},
3406#endif
danielk197751e3d8e2004-05-20 01:12:34 +00003407 };
drh1398ad32005-01-19 23:24:50 +00003408 static int bitmask_size = sizeof(Bitmask)*8;
drhc2eef3b2002-08-31 18:53:06 +00003409 int i;
drh2ac3ee92004-06-07 16:27:46 +00003410 extern int sqlite3_os_trace;
drh51147ba2005-07-23 22:59:55 +00003411 extern int sqlite3_where_trace;
drhb851b2c2005-03-10 14:11:12 +00003412 extern int sqlite3_sync_count, sqlite3_fullsync_count;
drhaf6df112005-06-07 02:12:30 +00003413 extern int sqlite3_opentemp_count;
drh01397202005-07-20 14:31:53 +00003414 extern int sqlite3_memUsed;
danielk19772e588c72005-12-09 14:25:08 +00003415 extern int sqlite3_malloc_id;
drh01397202005-07-20 14:31:53 +00003416 extern int sqlite3_memMax;
drh55ef4d92005-08-14 01:20:37 +00003417 extern int sqlite3_like_count;
drhc0929982005-09-05 19:08:29 +00003418#if OS_WIN
3419 extern int sqlite3_os_type;
3420#endif
drh8b3d9902005-08-19 00:14:42 +00003421#ifdef SQLITE_DEBUG
3422 extern int sqlite3_vdbe_addop_trace;
drh549c8b62005-09-19 13:15:23 +00003423#endif
3424#ifdef SQLITE_TEST
3425 extern char sqlite3_query_plan[];
drh9042f392005-07-15 23:24:23 +00003426 static char *query_plan = sqlite3_query_plan;
drh48083ce2005-09-19 12:37:27 +00003427#endif
drhc2eef3b2002-08-31 18:53:06 +00003428
3429 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
3430 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
3431 }
danielk197751e3d8e2004-05-20 01:12:34 +00003432 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
danielk1977c572ef72004-05-27 09:28:41 +00003433 Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
3434 aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
danielk197751e3d8e2004-05-20 01:12:34 +00003435 }
danielk19776490beb2004-05-11 06:17:21 +00003436 Tcl_LinkVar(interp, "sqlite_search_count",
danielk19776f8a5032004-05-10 10:34:51 +00003437 (char*)&sqlite3_search_count, TCL_LINK_INT);
drh6bf89572004-11-03 16:27:01 +00003438 Tcl_LinkVar(interp, "sqlite_sort_count",
3439 (char*)&sqlite3_sort_count, TCL_LINK_INT);
drh55ef4d92005-08-14 01:20:37 +00003440 Tcl_LinkVar(interp, "sqlite_like_count",
3441 (char*)&sqlite3_like_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00003442 Tcl_LinkVar(interp, "sqlite_interrupt_count",
danielk19776f8a5032004-05-10 10:34:51 +00003443 (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00003444 Tcl_LinkVar(interp, "sqlite_open_file_count",
danielk19776f8a5032004-05-10 10:34:51 +00003445 (char*)&sqlite3_open_file_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00003446 Tcl_LinkVar(interp, "sqlite_current_time",
danielk19776f8a5032004-05-10 10:34:51 +00003447 (char*)&sqlite3_current_time, TCL_LINK_INT);
drh2ac3ee92004-06-07 16:27:46 +00003448 Tcl_LinkVar(interp, "sqlite_os_trace",
3449 (char*)&sqlite3_os_trace, TCL_LINK_INT);
drh268803a2005-12-14 20:11:30 +00003450#ifndef SQLITE_OMIT_UTF16
3451 Tcl_LinkVar(interp, "sqlite_last_needed_collation",
3452 (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
3453#endif
danielk197797cb2e92005-12-09 14:39:04 +00003454#ifdef SQLITE_MEMDEBUG
danielk19772e588c72005-12-09 14:25:08 +00003455 Tcl_LinkVar(interp, "sqlite_malloc_id",
3456 (char*)&sqlite3_malloc_id, TCL_LINK_STRING);
danielk197797cb2e92005-12-09 14:39:04 +00003457#endif
drhc0929982005-09-05 19:08:29 +00003458#if OS_WIN
3459 Tcl_LinkVar(interp, "sqlite_os_type",
3460 (char*)&sqlite3_os_type, TCL_LINK_INT);
3461#endif
drh549c8b62005-09-19 13:15:23 +00003462#ifdef SQLITE_TEST
3463 Tcl_LinkVar(interp, "sqlite_query_plan",
3464 (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
3465#endif
drh8b3d9902005-08-19 00:14:42 +00003466#ifdef SQLITE_DEBUG
3467 Tcl_LinkVar(interp, "sqlite_addop_trace",
3468 (char*)&sqlite3_vdbe_addop_trace, TCL_LINK_INT);
drh48083ce2005-09-19 12:37:27 +00003469 Tcl_LinkVar(interp, "sqlite_where_trace",
3470 (char*)&sqlite3_where_trace, TCL_LINK_INT);
drh8b3d9902005-08-19 00:14:42 +00003471#endif
drh70180302005-08-02 21:42:16 +00003472#ifdef SQLITE_MEMDEBUG
drh01397202005-07-20 14:31:53 +00003473 Tcl_LinkVar(interp, "sqlite_memused",
3474 (char*)&sqlite3_memUsed, TCL_LINK_INT | TCL_LINK_READ_ONLY);
3475 Tcl_LinkVar(interp, "sqlite_memmax",
3476 (char*)&sqlite3_memMax, TCL_LINK_INT | TCL_LINK_READ_ONLY);
drh70180302005-08-02 21:42:16 +00003477#endif
danielk1977cbe21be2005-06-07 07:58:48 +00003478#ifndef SQLITE_OMIT_DISKIO
drhaf6df112005-06-07 02:12:30 +00003479 Tcl_LinkVar(interp, "sqlite_opentemp_count",
3480 (char*)&sqlite3_opentemp_count, TCL_LINK_INT);
danielk1977cbe21be2005-06-07 07:58:48 +00003481#endif
drh7c972de2003-09-06 22:18:07 +00003482 Tcl_LinkVar(interp, "sqlite_static_bind_value",
3483 (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
drhab3f9fe2004-08-14 17:10:10 +00003484 Tcl_LinkVar(interp, "sqlite_temp_directory",
drheffd02b2004-08-29 23:42:13 +00003485 (char*)&sqlite3_temp_directory, TCL_LINK_STRING);
drh1398ad32005-01-19 23:24:50 +00003486 Tcl_LinkVar(interp, "bitmask_size",
3487 (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
drh748f7632005-03-11 04:41:39 +00003488#if OS_UNIX
drhb851b2c2005-03-10 14:11:12 +00003489 Tcl_LinkVar(interp, "sqlite_sync_count",
3490 (char*)&sqlite3_sync_count, TCL_LINK_INT);
3491 Tcl_LinkVar(interp, "sqlite_fullsync_count",
3492 (char*)&sqlite3_fullsync_count, TCL_LINK_INT);
drh748f7632005-03-11 04:41:39 +00003493#endif /* OS_UNIX */
drh27d258a2004-10-30 20:23:09 +00003494 set_options(interp);
drhd1bf3512001-04-07 15:24:33 +00003495 return TCL_OK;
3496}