blob: d98640b4c357769d720f26189453fb58b0d08541 [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**
danielk1977b82e7ed2006-01-11 14:09:31 +000016** $Id: test1.c,v 1.187 2006/01/11 14:09:32 danielk1977 Exp $
drhd1bf3512001-04-07 15:24:33 +000017*/
18#include "sqliteInt.h"
19#include "tcl.h"
drh94e92032003-02-16 22:21:32 +000020#include "os.h"
drhd1bf3512001-04-07 15:24:33 +000021#include <stdlib.h>
22#include <string.h>
23
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**
danielk1977e501b892006-01-09 06:29:47 +0000832** Turn off this mechanism and reset the sqlite3ThreadData()->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
danielk197752622822006-01-09 09:59:49 +0000906#ifndef SQLITE_OMIT_MEMORY_MANAGEMENT
danielk19775591df52005-12-20 09:19:37 +0000907 if( objc==2 ){
danielk197752622822006-01-09 09:59:49 +0000908 ThreadData *pTd = sqlite3ThreadData();
danielk19775591df52005-12-20 09:19:37 +0000909 const char *zArg = Tcl_GetString(objv[1]);
910 if( 0==strcmp(zArg, "-bytes") ){
danielk197752622822006-01-09 09:59:49 +0000911 Tcl_SetObjResult(interp, Tcl_NewIntObj(pTd->nAlloc));
danielk19775591df52005-12-20 09:19:37 +0000912 }else if( 0==strcmp(zArg, "-maxbytes") ){
danielk197752622822006-01-09 09:59:49 +0000913 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(pTd->nMaxAlloc));
danielk19775591df52005-12-20 09:19:37 +0000914 }else if( 0==strcmp(zArg, "-clearmaxbytes") ){
danielk197752622822006-01-09 09:59:49 +0000915 pTd->nMaxAlloc = pTd->nAlloc;
danielk19775591df52005-12-20 09:19:37 +0000916 }else{
917 Tcl_AppendResult(interp, "bad option \"", zArg,
918 "\": must be -bytes, -maxbytes or -clearmaxbytes", 0
919 );
920 return TCL_ERROR;
921 }
922
923 return TCL_OK;
924 }
danielk197752622822006-01-09 09:59:49 +0000925#endif
926
927 if( objc!=1 ){
928 Tcl_WrongNumArgs(interp, 1, objv, "?-bytes?");
929 return TCL_ERROR;
930 }
danielk19775591df52005-12-20 09:19:37 +0000931
danielk19772e588c72005-12-09 14:25:08 +0000932 return sqlite3OutstandingMallocs(interp);
933}
drhdaffd0e2001-04-11 14:28:42 +0000934#endif
935
936/*
danielk197752622822006-01-09 09:59:49 +0000937** Usage: sqlite3_enable_shared_cache BOOLEAN
938** Usage: sqlite3_enable_memory_management BOOLEAN
danielk1977aef0bf62005-12-30 16:28:01 +0000939**
940*/
danielk197752622822006-01-09 09:59:49 +0000941#if !defined(SQLITE_OMIT_SHARED_CACHE)||!defined(SQLITE_OMIT_MEMORY_MANAGEMENT)
942static int test_enable(
943 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
danielk1977aef0bf62005-12-30 16:28:01 +0000944 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
945 int objc, /* Number of arguments */
946 Tcl_Obj *CONST objv[] /* Command arguments */
947){
948 int rc;
949 int enable;
danielk197752622822006-01-09 09:59:49 +0000950 int ret = 0;
951 int (*xFunc)(int) = (int(*)(int))clientData;
danielk1977e501b892006-01-09 06:29:47 +0000952 ThreadData *pTsd = sqlite3ThreadData();
danielk1977aef0bf62005-12-30 16:28:01 +0000953
danielk197752622822006-01-09 09:59:49 +0000954#ifndef SQLITE_OMIT_SHARED_CACHE
955 if( xFunc==sqlite3_enable_shared_cache ){
956 ret = pTsd->useSharedData;
957 }else
958#endif
959#ifndef SQLITE_OMIT_MEMORY_MANAGEMENT
960 {
961 assert( xFunc==sqlite3_enable_memory_management );
962 ret = pTsd->useMemoryManagement;
963 }
964#endif
danielk1977aef0bf62005-12-30 16:28:01 +0000965 if( objc!=2 ){
966 Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
967 return TCL_ERROR;
968 }
969 if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){
970 return TCL_ERROR;
971 }
danielk197752622822006-01-09 09:59:49 +0000972 rc = xFunc(enable);
danielk1977aef0bf62005-12-30 16:28:01 +0000973 if( rc!=SQLITE_OK ){
974 Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
975 return TCL_ERROR;
976 }
danielk197752622822006-01-09 09:59:49 +0000977 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ret));
danielk1977aef0bf62005-12-30 16:28:01 +0000978 return TCL_OK;
979}
980#endif
981
982/*
drh28b4e482002-03-11 02:06:13 +0000983** Usage: sqlite_abort
984**
985** Shutdown the process immediately. This is not a clean shutdown.
986** This command is used to test the recoverability of a database in
987** the event of a program crash.
988*/
989static int sqlite_abort(
990 void *NotUsed,
991 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
992 int argc, /* Number of arguments */
993 char **argv /* Text of each argument */
994){
995 assert( interp==0 ); /* This will always fail */
996 return TCL_OK;
997}
998
999/*
drh6cbe1f12002-07-01 00:31:36 +00001000** The following routine is a user-defined SQL function whose purpose
1001** is to test the sqlite_set_result() API.
1002*/
danielk19770ae8b832004-05-25 12:05:56 +00001003static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
drh6cbe1f12002-07-01 00:31:36 +00001004 while( argc>=2 ){
drh03d847e2005-12-09 20:21:58 +00001005 const char *zArg0 = (char*)sqlite3_value_text(argv[0]);
danielk19776d88bad2004-05-27 14:23:36 +00001006 if( zArg0 ){
1007 if( 0==sqlite3StrICmp(zArg0, "int") ){
1008 sqlite3_result_int(context, sqlite3_value_int(argv[1]));
1009 }else if( sqlite3StrICmp(zArg0,"int64")==0 ){
1010 sqlite3_result_int64(context, sqlite3_value_int64(argv[1]));
1011 }else if( sqlite3StrICmp(zArg0,"string")==0 ){
drh03d847e2005-12-09 20:21:58 +00001012 sqlite3_result_text(context, (char*)sqlite3_value_text(argv[1]), -1,
danielk1977d8123362004-06-12 09:25:12 +00001013 SQLITE_TRANSIENT);
danielk19776d88bad2004-05-27 14:23:36 +00001014 }else if( sqlite3StrICmp(zArg0,"double")==0 ){
1015 sqlite3_result_double(context, sqlite3_value_double(argv[1]));
1016 }else if( sqlite3StrICmp(zArg0,"null")==0 ){
1017 sqlite3_result_null(context);
1018 }else if( sqlite3StrICmp(zArg0,"value")==0 ){
1019 sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]);
1020 }else{
1021 goto error_out;
1022 }
drh6cbe1f12002-07-01 00:31:36 +00001023 }else{
danielk19776d88bad2004-05-27 14:23:36 +00001024 goto error_out;
drh6cbe1f12002-07-01 00:31:36 +00001025 }
1026 argc -= 2;
1027 argv += 2;
1028 }
danielk19776d88bad2004-05-27 14:23:36 +00001029 return;
1030
1031error_out:
1032 sqlite3_result_error(context,"first argument should be one of: "
1033 "int int64 string double null value", -1);
drh6cbe1f12002-07-01 00:31:36 +00001034}
1035
1036/*
1037** Usage: sqlite_register_test_function DB NAME
1038**
1039** Register the test SQL function on the database DB under the name NAME.
1040*/
drhc2eef3b2002-08-31 18:53:06 +00001041static int test_register_func(
drh6cbe1f12002-07-01 00:31:36 +00001042 void *NotUsed,
1043 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1044 int argc, /* Number of arguments */
1045 char **argv /* Text of each argument */
1046){
drh9bb575f2004-09-06 17:24:11 +00001047 sqlite3 *db;
drh6cbe1f12002-07-01 00:31:36 +00001048 int rc;
1049 if( argc!=3 ){
1050 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1051 " DB FUNCTION-NAME", 0);
1052 return TCL_ERROR;
1053 }
drhb86ccfb2003-01-28 23:13:10 +00001054 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk1977f9d64d22004-06-19 08:18:07 +00001055 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0,
danielk1977d8123362004-06-12 09:25:12 +00001056 testFunc, 0, 0);
drh6cbe1f12002-07-01 00:31:36 +00001057 if( rc!=0 ){
danielk1977f20b21c2004-05-31 23:56:42 +00001058 Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);
drh6cbe1f12002-07-01 00:31:36 +00001059 return TCL_ERROR;
1060 }
drhc60d0442004-09-30 13:43:13 +00001061 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drh6cbe1f12002-07-01 00:31:36 +00001062 return TCL_OK;
1063}
1064
1065/*
danielk1977106bb232004-05-21 10:08:53 +00001066** Usage: sqlite3_finalize STMT
drhb86ccfb2003-01-28 23:13:10 +00001067**
danielk1977106bb232004-05-21 10:08:53 +00001068** Finalize a statement handle.
drhb86ccfb2003-01-28 23:13:10 +00001069*/
1070static int test_finalize(
danielk1977106bb232004-05-21 10:08:53 +00001071 void * clientData,
1072 Tcl_Interp *interp,
1073 int objc,
1074 Tcl_Obj *CONST objv[]
drhb86ccfb2003-01-28 23:13:10 +00001075){
danielk1977106bb232004-05-21 10:08:53 +00001076 sqlite3_stmt *pStmt;
drhb86ccfb2003-01-28 23:13:10 +00001077 int rc;
drhc60d0442004-09-30 13:43:13 +00001078 sqlite3 *db;
danielk1977106bb232004-05-21 10:08:53 +00001079
1080 if( objc!=2 ){
1081 Tcl_AppendResult(interp, "wrong # args: should be \"",
1082 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
drhb86ccfb2003-01-28 23:13:10 +00001083 return TCL_ERROR;
1084 }
danielk1977106bb232004-05-21 10:08:53 +00001085
1086 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1087
danielk19774397de52005-01-12 12:44:03 +00001088 if( pStmt ){
1089 db = StmtToDb(pStmt);
1090 }
danielk1977fc57d7b2004-05-26 02:04:57 +00001091 rc = sqlite3_finalize(pStmt);
danielk1977b77f5da2004-05-26 13:27:00 +00001092 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
danielk19774397de52005-01-12 12:44:03 +00001093 if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk1977106bb232004-05-21 10:08:53 +00001094 return TCL_OK;
1095}
1096
1097/*
1098** Usage: sqlite3_reset STMT
1099**
danielk1977261919c2005-12-06 12:52:59 +00001100** Reset a statement handle.
danielk1977106bb232004-05-21 10:08:53 +00001101*/
1102static int test_reset(
1103 void * clientData,
1104 Tcl_Interp *interp,
1105 int objc,
1106 Tcl_Obj *CONST objv[]
1107){
1108 sqlite3_stmt *pStmt;
1109 int rc;
1110
1111 if( objc!=2 ){
1112 Tcl_AppendResult(interp, "wrong # args: should be \"",
1113 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
1114 return TCL_ERROR;
1115 }
1116
1117 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1118
danielk1977fc57d7b2004-05-26 02:04:57 +00001119 rc = sqlite3_reset(pStmt);
danielk1977261919c2005-12-06 12:52:59 +00001120 if( pStmt && sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ){
1121 return TCL_ERROR;
1122 }
danielk19774397de52005-01-12 12:44:03 +00001123 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
danielk1977261919c2005-12-06 12:52:59 +00001124/*
danielk1977106bb232004-05-21 10:08:53 +00001125 if( rc ){
drhb86ccfb2003-01-28 23:13:10 +00001126 return TCL_ERROR;
1127 }
danielk1977261919c2005-12-06 12:52:59 +00001128*/
drhb86ccfb2003-01-28 23:13:10 +00001129 return TCL_OK;
1130}
1131
drh5a387052003-01-11 14:19:51 +00001132/*
drhd89bd002005-01-22 03:03:54 +00001133** Usage: sqlite3_expired STMT
1134**
1135** Return TRUE if a recompilation of the statement is recommended.
1136*/
1137static int test_expired(
1138 void * clientData,
1139 Tcl_Interp *interp,
1140 int objc,
1141 Tcl_Obj *CONST objv[]
1142){
1143 sqlite3_stmt *pStmt;
1144 if( objc!=2 ){
1145 Tcl_AppendResult(interp, "wrong # args: should be \"",
1146 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
1147 return TCL_ERROR;
1148 }
1149 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1150 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite3_expired(pStmt)));
1151 return TCL_OK;
1152}
1153
1154/*
drhf8db1bc2005-04-22 02:38:37 +00001155** Usage: sqlite3_transfer_bindings FROMSTMT TOSTMT
1156**
1157** Transfer all bindings from FROMSTMT over to TOSTMT
1158*/
1159static int test_transfer_bind(
1160 void * clientData,
1161 Tcl_Interp *interp,
1162 int objc,
1163 Tcl_Obj *CONST objv[]
1164){
1165 sqlite3_stmt *pStmt1, *pStmt2;
1166 if( objc!=3 ){
1167 Tcl_AppendResult(interp, "wrong # args: should be \"",
1168 Tcl_GetStringFromObj(objv[0], 0), " FROM-STMT TO-STMT", 0);
1169 return TCL_ERROR;
1170 }
1171 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt1)) return TCL_ERROR;
1172 if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt2)) return TCL_ERROR;
1173 Tcl_SetObjResult(interp,
1174 Tcl_NewIntObj(sqlite3_transfer_bindings(pStmt1,pStmt2)));
1175 return TCL_OK;
1176}
1177
1178/*
danielk1977fbcd5852004-06-15 02:44:18 +00001179** Usage: sqlite3_changes DB
drh50457892003-09-06 01:10:47 +00001180**
danielk1977fbcd5852004-06-15 02:44:18 +00001181** Return the number of changes made to the database by the last SQL
1182** execution.
drh50457892003-09-06 01:10:47 +00001183*/
danielk1977fbcd5852004-06-15 02:44:18 +00001184static int test_changes(
1185 void * clientData,
1186 Tcl_Interp *interp,
1187 int objc,
1188 Tcl_Obj *CONST objv[]
1189){
1190 sqlite3 *db;
1191 if( objc!=2 ){
1192 Tcl_AppendResult(interp, "wrong # args: should be \"",
1193 Tcl_GetString(objv[0]), " DB", 0);
1194 return TCL_ERROR;
1195 }
1196 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1197 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db)));
1198 return TCL_OK;
1199}
drh50457892003-09-06 01:10:47 +00001200
1201/*
drh7c972de2003-09-06 22:18:07 +00001202** This is the "static_bind_value" that variables are bound to when
danielk19776f8a5032004-05-10 10:34:51 +00001203** the FLAG option of sqlite3_bind is "static"
drh50457892003-09-06 01:10:47 +00001204*/
drh7c972de2003-09-06 22:18:07 +00001205static char *sqlite_static_bind_value = 0;
1206
1207/*
danielk19776f8a5032004-05-10 10:34:51 +00001208** Usage: sqlite3_bind VM IDX VALUE FLAGS
drh7c972de2003-09-06 22:18:07 +00001209**
1210** Sets the value of the IDX-th occurance of "?" in the original SQL
1211** string. VALUE is the new value. If FLAGS=="null" then VALUE is
1212** ignored and the value is set to NULL. If FLAGS=="static" then
1213** the value is set to the value of a static variable named
1214** "sqlite_static_bind_value". If FLAGS=="normal" then a copy
drhbf8aa2a2005-12-02 02:44:05 +00001215** of the VALUE is made. If FLAGS=="blob10" then a VALUE is ignored
1216** an a 10-byte blob "abc\000xyz\000pq" is inserted.
drh7c972de2003-09-06 22:18:07 +00001217*/
1218static int test_bind(
drh50457892003-09-06 01:10:47 +00001219 void *NotUsed,
1220 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1221 int argc, /* Number of arguments */
1222 char **argv /* Text of each argument */
1223){
danielk1977fc57d7b2004-05-26 02:04:57 +00001224 sqlite3_stmt *pStmt;
drh50457892003-09-06 01:10:47 +00001225 int rc;
drh7c972de2003-09-06 22:18:07 +00001226 int idx;
1227 if( argc!=5 ){
drh50457892003-09-06 01:10:47 +00001228 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
drh7c972de2003-09-06 22:18:07 +00001229 " VM IDX VALUE (null|static|normal)\"", 0);
drh50457892003-09-06 01:10:47 +00001230 return TCL_ERROR;
1231 }
danielk1977fc57d7b2004-05-26 02:04:57 +00001232 if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR;
drh7c972de2003-09-06 22:18:07 +00001233 if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR;
1234 if( strcmp(argv[4],"null")==0 ){
danielk1977fc57d7b2004-05-26 02:04:57 +00001235 rc = sqlite3_bind_null(pStmt, idx);
drh7c972de2003-09-06 22:18:07 +00001236 }else if( strcmp(argv[4],"static")==0 ){
danielk1977fc57d7b2004-05-26 02:04:57 +00001237 rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0);
drh7c972de2003-09-06 22:18:07 +00001238 }else if( strcmp(argv[4],"normal")==0 ){
danielk1977d8123362004-06-12 09:25:12 +00001239 rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT);
drhbf8aa2a2005-12-02 02:44:05 +00001240 }else if( strcmp(argv[4],"blob10")==0 ){
1241 rc = sqlite3_bind_text(pStmt, idx, "abc\000xyz\000pq", 10, SQLITE_STATIC);
drh7c972de2003-09-06 22:18:07 +00001242 }else{
1243 Tcl_AppendResult(interp, "4th argument should be "
1244 "\"null\" or \"static\" or \"normal\"", 0);
1245 return TCL_ERROR;
1246 }
drhc60d0442004-09-30 13:43:13 +00001247 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
drh50457892003-09-06 01:10:47 +00001248 if( rc ){
1249 char zBuf[50];
1250 sprintf(zBuf, "(%d) ", rc);
danielk1977f20b21c2004-05-31 23:56:42 +00001251 Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0);
drh50457892003-09-06 01:10:47 +00001252 return TCL_ERROR;
1253 }
1254 return TCL_OK;
1255}
1256
drh5436dc22004-11-14 04:04:17 +00001257#ifndef SQLITE_OMIT_UTF16
danielk19774e6af132004-06-10 14:01:08 +00001258/*
1259** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be>
1260**
1261** This function is used to test that SQLite selects the correct collation
1262** sequence callback when multiple versions (for different text encodings)
1263** are available.
1264**
1265** Calling this routine registers the collation sequence "test_collate"
1266** with database handle <db>. The second argument must be a list of three
1267** boolean values. If the first is true, then a version of test_collate is
1268** registered for UTF-8, if the second is true, a version is registered for
1269** UTF-16le, if the third is true, a UTF-16be version is available.
1270** Previous versions of test_collate are deleted.
1271**
1272** The collation sequence test_collate is implemented by calling the
1273** following TCL script:
1274**
1275** "test_collate <enc> <lhs> <rhs>"
1276**
1277** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8.
1278** The <enc> parameter is the encoding of the collation function that
1279** SQLite selected to call. The TCL test script implements the
1280** "test_collate" proc.
1281**
1282** Note that this will only work with one intepreter at a time, as the
1283** interp pointer to use when evaluating the TCL script is stored in
1284** pTestCollateInterp.
1285*/
1286static Tcl_Interp* pTestCollateInterp;
1287static int test_collate_func(
1288 void *pCtx,
1289 int nA, const void *zA,
1290 int nB, const void *zB
1291){
1292 Tcl_Interp *i = pTestCollateInterp;
1293 int encin = (int)pCtx;
1294 int res;
drh4db38a72005-09-01 12:16:28 +00001295 int n;
danielk19774e6af132004-06-10 14:01:08 +00001296
1297 sqlite3_value *pVal;
1298 Tcl_Obj *pX;
1299
1300 pX = Tcl_NewStringObj("test_collate", -1);
1301 Tcl_IncrRefCount(pX);
1302
1303 switch( encin ){
1304 case SQLITE_UTF8:
1305 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1));
1306 break;
1307 case SQLITE_UTF16LE:
1308 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1));
1309 break;
1310 case SQLITE_UTF16BE:
1311 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1));
1312 break;
1313 default:
1314 assert(0);
1315 }
1316
1317 pVal = sqlite3ValueNew();
danielk1977bfd6cce2004-06-18 04:24:54 +00001318 sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC);
drh4db38a72005-09-01 12:16:28 +00001319 n = sqlite3_value_bytes(pVal);
drh03d847e2005-12-09 20:21:58 +00001320 Tcl_ListObjAppendElement(i,pX,
1321 Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
danielk1977bfd6cce2004-06-18 04:24:54 +00001322 sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC);
drh4db38a72005-09-01 12:16:28 +00001323 n = sqlite3_value_bytes(pVal);
drh03d847e2005-12-09 20:21:58 +00001324 Tcl_ListObjAppendElement(i,pX,
1325 Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
danielk19774e6af132004-06-10 14:01:08 +00001326 sqlite3ValueFree(pVal);
1327
1328 Tcl_EvalObjEx(i, pX, 0);
1329 Tcl_DecrRefCount(pX);
1330 Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res);
1331 return res;
1332}
1333static int test_collate(
1334 void * clientData,
1335 Tcl_Interp *interp,
1336 int objc,
1337 Tcl_Obj *CONST objv[]
1338){
1339 sqlite3 *db;
1340 int val;
danielk1977312d6b32004-06-29 13:18:23 +00001341 sqlite3_value *pVal;
drhc60d0442004-09-30 13:43:13 +00001342 int rc;
danielk19774e6af132004-06-10 14:01:08 +00001343
1344 if( objc!=5 ) goto bad_args;
1345 pTestCollateInterp = interp;
1346 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1347
1348 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +00001349 rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8,
1350 (void *)SQLITE_UTF8, val?test_collate_func:0);
1351 if( rc==SQLITE_OK ){
1352 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
1353 rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE,
1354 (void *)SQLITE_UTF16LE, val?test_collate_func:0);
1355 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
danielk1977312d6b32004-06-29 13:18:23 +00001356
drhc60d0442004-09-30 13:43:13 +00001357 pVal = sqlite3ValueNew();
1358 sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC);
1359 sqlite3_create_collation16(db, sqlite3ValueText(pVal, SQLITE_UTF16NATIVE),
1360 SQLITE_UTF16BE, (void *)SQLITE_UTF16BE, val?test_collate_func:0);
1361 sqlite3ValueFree(pVal);
1362 }
1363 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk19774e6af132004-06-10 14:01:08 +00001364 return TCL_OK;
1365
1366bad_args:
1367 Tcl_AppendResult(interp, "wrong # args: should be \"",
1368 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
1369 return TCL_ERROR;
1370}
1371
drh268803a2005-12-14 20:11:30 +00001372/*
1373** When the collation needed callback is invoked, record the name of
1374** the requested collating function here. The recorded name is linked
1375** to a TCL variable and used to make sure that the requested collation
1376** name is correct.
1377*/
1378static char zNeededCollation[200];
1379static char *pzNeededCollation = zNeededCollation;
1380
1381
1382/*
1383** Called when a collating sequence is needed. Registered using
1384** sqlite3_collation_needed16().
1385*/
danielk1977312d6b32004-06-29 13:18:23 +00001386static void test_collate_needed_cb(
1387 void *pCtx,
1388 sqlite3 *db,
1389 int eTextRep,
drh268803a2005-12-14 20:11:30 +00001390 const void *pName
danielk1977312d6b32004-06-29 13:18:23 +00001391){
danielk197714db2662006-01-09 16:12:04 +00001392 int enc = ENC(db);
drh268803a2005-12-14 20:11:30 +00001393 int i;
1394 char *z;
1395 for(z = (char*)pName, i=0; *z || z[1]; z++){
1396 if( *z ) zNeededCollation[i++] = *z;
1397 }
1398 zNeededCollation[i] = 0;
danielk1977312d6b32004-06-29 13:18:23 +00001399 sqlite3_create_collation(
danielk197714db2662006-01-09 16:12:04 +00001400 db, "test_collate", ENC(db), (void *)enc, test_collate_func);
danielk1977312d6b32004-06-29 13:18:23 +00001401}
1402
1403/*
1404** Usage: add_test_collate_needed DB
1405*/
1406static int test_collate_needed(
1407 void * clientData,
1408 Tcl_Interp *interp,
1409 int objc,
1410 Tcl_Obj *CONST objv[]
1411){
1412 sqlite3 *db;
drhc60d0442004-09-30 13:43:13 +00001413 int rc;
danielk1977312d6b32004-06-29 13:18:23 +00001414
1415 if( objc!=2 ) goto bad_args;
1416 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +00001417 rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb);
drh268803a2005-12-14 20:11:30 +00001418 zNeededCollation[0] = 0;
drhc60d0442004-09-30 13:43:13 +00001419 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk1977312d6b32004-06-29 13:18:23 +00001420 return TCL_OK;
1421
1422bad_args:
1423 Tcl_WrongNumArgs(interp, 1, objv, "DB");
1424 return TCL_ERROR;
1425}
drh5436dc22004-11-14 04:04:17 +00001426#endif /* SQLITE_OMIT_UTF16 */
danielk1977312d6b32004-06-29 13:18:23 +00001427
danielk1977c8e9a2d2004-06-25 12:08:46 +00001428/*
1429** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
1430**
1431** This function is used to test that SQLite selects the correct user
1432** function callback when multiple versions (for different text encodings)
1433** are available.
1434**
1435** Calling this routine registers up to three versions of the user function
1436** "test_function" with database handle <db>. If the second argument is
1437** true, then a version of test_function is registered for UTF-8, if the
1438** third is true, a version is registered for UTF-16le, if the fourth is
1439** true, a UTF-16be version is available. Previous versions of
1440** test_function are deleted.
1441**
1442** The user function is implemented by calling the following TCL script:
1443**
1444** "test_function <enc> <arg>"
1445**
1446** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the
1447** single argument passed to the SQL function. The value returned by
1448** the TCL script is used as the return value of the SQL function. It
1449** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8
1450** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
1451** prefers UTF-16BE.
1452*/
drh5436dc22004-11-14 04:04:17 +00001453#ifndef SQLITE_OMIT_UTF16
danielk1977c8e9a2d2004-06-25 12:08:46 +00001454static void test_function_utf8(
1455 sqlite3_context *pCtx,
1456 int nArg,
1457 sqlite3_value **argv
1458){
1459 Tcl_Interp *interp;
1460 Tcl_Obj *pX;
1461 sqlite3_value *pVal;
1462 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1463 pX = Tcl_NewStringObj("test_function", -1);
1464 Tcl_IncrRefCount(pX);
1465 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1));
1466 Tcl_ListObjAppendElement(interp, pX,
drh03d847e2005-12-09 20:21:58 +00001467 Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
danielk1977c8e9a2d2004-06-25 12:08:46 +00001468 Tcl_EvalObjEx(interp, pX, 0);
1469 Tcl_DecrRefCount(pX);
1470 sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT);
1471 pVal = sqlite3ValueNew();
1472 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1473 SQLITE_UTF8, SQLITE_STATIC);
1474 sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal),
1475 -1, SQLITE_TRANSIENT);
1476 sqlite3ValueFree(pVal);
1477}
1478static void test_function_utf16le(
1479 sqlite3_context *pCtx,
1480 int nArg,
1481 sqlite3_value **argv
1482){
1483 Tcl_Interp *interp;
1484 Tcl_Obj *pX;
1485 sqlite3_value *pVal;
1486 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1487 pX = Tcl_NewStringObj("test_function", -1);
1488 Tcl_IncrRefCount(pX);
1489 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1));
1490 Tcl_ListObjAppendElement(interp, pX,
drh03d847e2005-12-09 20:21:58 +00001491 Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
danielk1977c8e9a2d2004-06-25 12:08:46 +00001492 Tcl_EvalObjEx(interp, pX, 0);
1493 Tcl_DecrRefCount(pX);
1494 pVal = sqlite3ValueNew();
1495 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1496 SQLITE_UTF8, SQLITE_STATIC);
drh03d847e2005-12-09 20:21:58 +00001497 sqlite3_result_text(pCtx,(char*)sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT);
danielk1977c8e9a2d2004-06-25 12:08:46 +00001498 sqlite3ValueFree(pVal);
1499}
1500static void test_function_utf16be(
1501 sqlite3_context *pCtx,
1502 int nArg,
1503 sqlite3_value **argv
1504){
1505 Tcl_Interp *interp;
1506 Tcl_Obj *pX;
1507 sqlite3_value *pVal;
1508 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1509 pX = Tcl_NewStringObj("test_function", -1);
1510 Tcl_IncrRefCount(pX);
1511 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1));
1512 Tcl_ListObjAppendElement(interp, pX,
drh03d847e2005-12-09 20:21:58 +00001513 Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
danielk1977c8e9a2d2004-06-25 12:08:46 +00001514 Tcl_EvalObjEx(interp, pX, 0);
1515 Tcl_DecrRefCount(pX);
1516 pVal = sqlite3ValueNew();
1517 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1518 SQLITE_UTF8, SQLITE_STATIC);
1519 sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal),
1520 -1, SQLITE_TRANSIENT);
1521 sqlite3ValueFree(pVal);
1522}
drh5436dc22004-11-14 04:04:17 +00001523#endif /* SQLITE_OMIT_UTF16 */
danielk1977c8e9a2d2004-06-25 12:08:46 +00001524static int test_function(
1525 void * clientData,
1526 Tcl_Interp *interp,
1527 int objc,
1528 Tcl_Obj *CONST objv[]
1529){
drh5436dc22004-11-14 04:04:17 +00001530#ifndef SQLITE_OMIT_UTF16
danielk1977c8e9a2d2004-06-25 12:08:46 +00001531 sqlite3 *db;
1532 int val;
1533
1534 if( objc!=5 ) goto bad_args;
1535 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1536
1537 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
1538 if( val ){
1539 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8,
1540 interp, test_function_utf8, 0, 0);
1541 }
1542 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
1543 if( val ){
1544 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE,
1545 interp, test_function_utf16le, 0, 0);
1546 }
1547 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
1548 if( val ){
1549 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE,
1550 interp, test_function_utf16be, 0, 0);
1551 }
1552
1553 return TCL_OK;
1554bad_args:
1555 Tcl_AppendResult(interp, "wrong # args: should be \"",
1556 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
drh5436dc22004-11-14 04:04:17 +00001557#endif /* SQLITE_OMIT_UTF16 */
danielk1977c8e9a2d2004-06-25 12:08:46 +00001558 return TCL_ERROR;
1559}
1560
danielk1977312d6b32004-06-29 13:18:23 +00001561/*
1562** Usage: test_errstr <err code>
1563**
1564** Test that the english language string equivalents for sqlite error codes
1565** are sane. The parameter is an integer representing an sqlite error code.
1566** The result is a list of two elements, the string representation of the
1567** error code and the english language explanation.
1568*/
1569static int test_errstr(
1570 void * clientData,
1571 Tcl_Interp *interp,
1572 int objc,
1573 Tcl_Obj *CONST objv[]
1574){
1575 char *zCode;
1576 int i;
1577 if( objc!=1 ){
1578 Tcl_WrongNumArgs(interp, 1, objv, "<error code>");
1579 }
1580
1581 zCode = Tcl_GetString(objv[1]);
1582 for(i=0; i<200; i++){
1583 if( 0==strcmp(errorName(i), zCode) ) break;
1584 }
1585 Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0);
1586 return TCL_OK;
1587}
1588
drh50457892003-09-06 01:10:47 +00001589/*
drh99ee3602003-02-16 19:13:36 +00001590** Usage: breakpoint
1591**
1592** This routine exists for one purpose - to provide a place to put a
1593** breakpoint with GDB that can be triggered using TCL code. The use
1594** for this is when a particular test fails on (say) the 1485th iteration.
1595** In the TCL test script, we can add code like this:
1596**
1597** if {$i==1485} breakpoint
1598**
1599** Then run testfixture in the debugger and wait for the breakpoint to
1600** fire. Then additional breakpoints can be set to trace down the bug.
1601*/
1602static int test_breakpoint(
1603 void *NotUsed,
1604 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1605 int argc, /* Number of arguments */
1606 char **argv /* Text of each argument */
1607){
1608 return TCL_OK; /* Do nothing */
1609}
1610
drh241db312004-06-22 12:46:53 +00001611/*
1612** Usage: sqlite3_bind_int STMT N VALUE
1613**
1614** Test the sqlite3_bind_int interface. STMT is a prepared statement.
1615** N is the index of a wildcard in the prepared statement. This command
1616** binds a 32-bit integer VALUE to that wildcard.
1617*/
1618static int test_bind_int(
danielk197751e3d8e2004-05-20 01:12:34 +00001619 void * clientData,
1620 Tcl_Interp *interp,
1621 int objc,
1622 Tcl_Obj *CONST objv[]
1623){
1624 sqlite3_stmt *pStmt;
1625 int idx;
1626 int value;
1627 int rc;
1628
1629 if( objc!=4 ){
1630 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001631 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001632 return TCL_ERROR;
1633 }
1634
1635 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1636 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1637 if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
1638
danielk1977c572ef72004-05-27 09:28:41 +00001639 rc = sqlite3_bind_int(pStmt, idx, value);
drhc60d0442004-09-30 13:43:13 +00001640 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001641 if( rc!=SQLITE_OK ){
1642 return TCL_ERROR;
1643 }
1644
1645 return TCL_OK;
1646}
1647
drh241db312004-06-22 12:46:53 +00001648
1649/*
1650** Usage: sqlite3_bind_int64 STMT N VALUE
1651**
1652** Test the sqlite3_bind_int64 interface. STMT is a prepared statement.
1653** N is the index of a wildcard in the prepared statement. This command
1654** binds a 64-bit integer VALUE to that wildcard.
1655*/
danielk197751e3d8e2004-05-20 01:12:34 +00001656static int test_bind_int64(
1657 void * clientData,
1658 Tcl_Interp *interp,
1659 int objc,
1660 Tcl_Obj *CONST objv[]
1661){
1662 sqlite3_stmt *pStmt;
1663 int idx;
1664 i64 value;
1665 int rc;
1666
1667 if( objc!=4 ){
1668 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001669 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001670 return TCL_ERROR;
1671 }
1672
1673 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1674 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1675 if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
1676
1677 rc = sqlite3_bind_int64(pStmt, idx, value);
drhc60d0442004-09-30 13:43:13 +00001678 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001679 if( rc!=SQLITE_OK ){
1680 return TCL_ERROR;
1681 }
1682
1683 return TCL_OK;
1684}
1685
drh241db312004-06-22 12:46:53 +00001686
1687/*
1688** Usage: sqlite3_bind_double STMT N VALUE
1689**
1690** Test the sqlite3_bind_double interface. STMT is a prepared statement.
1691** N is the index of a wildcard in the prepared statement. This command
1692** binds a 64-bit integer VALUE to that wildcard.
1693*/
danielk197751e3d8e2004-05-20 01:12:34 +00001694static int test_bind_double(
1695 void * clientData,
1696 Tcl_Interp *interp,
1697 int objc,
1698 Tcl_Obj *CONST objv[]
1699){
1700 sqlite3_stmt *pStmt;
1701 int idx;
1702 double value;
1703 int rc;
1704
1705 if( objc!=4 ){
1706 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001707 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001708 return TCL_ERROR;
1709 }
1710
1711 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1712 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1713 if( Tcl_GetDoubleFromObj(interp, objv[3], &value) ) return TCL_ERROR;
1714
1715 rc = sqlite3_bind_double(pStmt, idx, value);
drhc60d0442004-09-30 13:43:13 +00001716 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001717 if( rc!=SQLITE_OK ){
1718 return TCL_ERROR;
1719 }
1720
1721 return TCL_OK;
1722}
1723
drh241db312004-06-22 12:46:53 +00001724/*
1725** Usage: sqlite3_bind_null STMT N
1726**
1727** Test the sqlite3_bind_null interface. STMT is a prepared statement.
1728** N is the index of a wildcard in the prepared statement. This command
1729** binds a NULL to the wildcard.
1730*/
danielk197751e3d8e2004-05-20 01:12:34 +00001731static int test_bind_null(
1732 void * clientData,
1733 Tcl_Interp *interp,
1734 int objc,
1735 Tcl_Obj *CONST objv[]
1736){
1737 sqlite3_stmt *pStmt;
1738 int idx;
1739 int rc;
1740
1741 if( objc!=3 ){
1742 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001743 Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001744 return TCL_ERROR;
1745 }
1746
1747 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1748 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1749
1750 rc = sqlite3_bind_null(pStmt, idx);
drhc60d0442004-09-30 13:43:13 +00001751 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001752 if( rc!=SQLITE_OK ){
1753 return TCL_ERROR;
1754 }
1755
1756 return TCL_OK;
1757}
1758
drh241db312004-06-22 12:46:53 +00001759/*
1760** Usage: sqlite3_bind_text STMT N STRING BYTES
1761**
1762** Test the sqlite3_bind_text interface. STMT is a prepared statement.
1763** N is the index of a wildcard in the prepared statement. This command
1764** binds a UTF-8 string STRING to the wildcard. The string is BYTES bytes
1765** long.
1766*/
danielk197751e3d8e2004-05-20 01:12:34 +00001767static int test_bind_text(
1768 void * clientData,
1769 Tcl_Interp *interp,
1770 int objc,
1771 Tcl_Obj *CONST objv[]
1772){
1773 sqlite3_stmt *pStmt;
1774 int idx;
1775 int bytes;
1776 char *value;
1777 int rc;
1778
1779 if( objc!=5 ){
1780 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001781 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001782 return TCL_ERROR;
1783 }
1784
1785 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1786 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1787 value = Tcl_GetString(objv[3]);
1788 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
1789
danielk1977d8123362004-06-12 09:25:12 +00001790 rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
drhc60d0442004-09-30 13:43:13 +00001791 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001792 if( rc!=SQLITE_OK ){
drh473d1792005-06-06 17:54:55 +00001793 Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001794 return TCL_ERROR;
1795 }
1796
1797 return TCL_OK;
1798}
1799
drh241db312004-06-22 12:46:53 +00001800/*
1801** Usage: sqlite3_bind_text16 STMT N STRING BYTES
1802**
1803** Test the sqlite3_bind_text16 interface. STMT is a prepared statement.
1804** N is the index of a wildcard in the prepared statement. This command
1805** binds a UTF-16 string STRING to the wildcard. The string is BYTES bytes
1806** long.
1807*/
danielk197751e3d8e2004-05-20 01:12:34 +00001808static int test_bind_text16(
1809 void * clientData,
1810 Tcl_Interp *interp,
1811 int objc,
1812 Tcl_Obj *CONST objv[]
1813){
drh5436dc22004-11-14 04:04:17 +00001814#ifndef SQLITE_OMIT_UTF16
danielk197751e3d8e2004-05-20 01:12:34 +00001815 sqlite3_stmt *pStmt;
1816 int idx;
1817 int bytes;
1818 char *value;
1819 int rc;
1820
1821 if( objc!=5 ){
1822 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001823 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001824 return TCL_ERROR;
1825 }
1826
1827 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1828 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
drh03d847e2005-12-09 20:21:58 +00001829 value = (char*)Tcl_GetByteArrayFromObj(objv[3], 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001830 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
1831
danielk1977d8123362004-06-12 09:25:12 +00001832 rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, SQLITE_TRANSIENT);
drhc60d0442004-09-30 13:43:13 +00001833 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001834 if( rc!=SQLITE_OK ){
1835 return TCL_ERROR;
1836 }
1837
drh5436dc22004-11-14 04:04:17 +00001838#endif /* SQLITE_OMIT_UTF16 */
danielk197751e3d8e2004-05-20 01:12:34 +00001839 return TCL_OK;
1840}
1841
drh241db312004-06-22 12:46:53 +00001842/*
1843** Usage: sqlite3_bind_blob STMT N DATA BYTES
1844**
1845** Test the sqlite3_bind_blob interface. STMT is a prepared statement.
1846** N is the index of a wildcard in the prepared statement. This command
1847** binds a BLOB to the wildcard. The BLOB is BYTES bytes in size.
1848*/
danielk197751e3d8e2004-05-20 01:12:34 +00001849static int test_bind_blob(
1850 void * clientData,
1851 Tcl_Interp *interp,
1852 int objc,
1853 Tcl_Obj *CONST objv[]
1854){
1855 sqlite3_stmt *pStmt;
1856 int idx;
1857 int bytes;
1858 char *value;
1859 int rc;
1860
1861 if( objc!=5 ){
1862 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001863 Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001864 return TCL_ERROR;
1865 }
1866
1867 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1868 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1869 value = Tcl_GetString(objv[3]);
danielk197749e46432004-05-27 13:55:27 +00001870 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001871
danielk1977d8123362004-06-12 09:25:12 +00001872 rc = sqlite3_bind_blob(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
drhc60d0442004-09-30 13:43:13 +00001873 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001874 if( rc!=SQLITE_OK ){
1875 return TCL_ERROR;
1876 }
1877
1878 return TCL_OK;
1879}
1880
drh99ee3602003-02-16 19:13:36 +00001881/*
drh75f6a032004-07-15 14:15:00 +00001882** Usage: sqlite3_bind_parameter_count STMT
1883**
1884** Return the number of wildcards in the given statement.
1885*/
1886static int test_bind_parameter_count(
1887 void * clientData,
1888 Tcl_Interp *interp,
1889 int objc,
1890 Tcl_Obj *CONST objv[]
1891){
1892 sqlite3_stmt *pStmt;
1893
1894 if( objc!=2 ){
1895 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
1896 return TCL_ERROR;
1897 }
1898 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1899 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt)));
1900 return TCL_OK;
1901}
1902
1903/*
drh895d7472004-08-20 16:02:39 +00001904** Usage: sqlite3_bind_parameter_name STMT N
1905**
1906** Return the name of the Nth wildcard. The first wildcard is 1.
1907** An empty string is returned if N is out of range or if the wildcard
1908** is nameless.
1909*/
1910static int test_bind_parameter_name(
1911 void * clientData,
1912 Tcl_Interp *interp,
1913 int objc,
1914 Tcl_Obj *CONST objv[]
1915){
1916 sqlite3_stmt *pStmt;
1917 int i;
1918
1919 if( objc!=3 ){
1920 Tcl_WrongNumArgs(interp, 1, objv, "STMT N");
1921 return TCL_ERROR;
1922 }
1923 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1924 if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR;
1925 Tcl_SetObjResult(interp,
1926 Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1)
1927 );
1928 return TCL_OK;
1929}
1930
1931/*
drhfa6bc002004-09-07 16:19:52 +00001932** Usage: sqlite3_bind_parameter_index STMT NAME
1933**
1934** Return the index of the wildcard called NAME. Return 0 if there is
1935** no such wildcard.
1936*/
1937static int test_bind_parameter_index(
1938 void * clientData,
1939 Tcl_Interp *interp,
1940 int objc,
1941 Tcl_Obj *CONST objv[]
1942){
1943 sqlite3_stmt *pStmt;
1944
1945 if( objc!=3 ){
1946 Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME");
1947 return TCL_ERROR;
1948 }
1949 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1950 Tcl_SetObjResult(interp,
1951 Tcl_NewIntObj(
1952 sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2]))
1953 )
1954 );
1955 return TCL_OK;
1956}
1957
1958/*
danielk1977600dd0b2005-01-20 01:14:23 +00001959** Usage: sqlite3_clear_bindings STMT
1960**
1961*/
1962#if 0
1963static int test_clear_bindings(
1964 void * clientData,
1965 Tcl_Interp *interp,
1966 int objc,
1967 Tcl_Obj *CONST objv[]
1968){
1969 sqlite3_stmt *pStmt;
1970
1971 if( objc!=2 ){
1972 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
1973 return TCL_ERROR;
1974 }
1975 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1976 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt)));
1977 return TCL_OK;
1978}
1979#endif
1980
1981/*
danielk19776622cce2004-05-20 11:00:52 +00001982** Usage: sqlite3_errcode DB
1983**
1984** Return the string representation of the most recent sqlite3_* API
1985** error code. e.g. "SQLITE_ERROR".
1986*/
1987static int test_errcode(
1988 void * clientData,
1989 Tcl_Interp *interp,
1990 int objc,
1991 Tcl_Obj *CONST objv[]
1992){
1993 sqlite3 *db;
1994
1995 if( objc!=2 ){
1996 Tcl_AppendResult(interp, "wrong # args: should be \"",
1997 Tcl_GetString(objv[0]), " DB", 0);
1998 return TCL_ERROR;
1999 }
2000 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2001 Tcl_SetResult(interp, (char *)errorName(sqlite3_errcode(db)), 0);
2002 return TCL_OK;
2003}
2004
2005/*
2006** Usage: test_errmsg DB
2007**
2008** Returns the UTF-8 representation of the error message string for the
2009** most recent sqlite3_* API call.
2010*/
2011static int test_errmsg(
2012 void * clientData,
2013 Tcl_Interp *interp,
2014 int objc,
2015 Tcl_Obj *CONST objv[]
2016){
drh9bb575f2004-09-06 17:24:11 +00002017 sqlite3 *db;
danielk19776622cce2004-05-20 11:00:52 +00002018 const char *zErr;
2019
2020 if( objc!=2 ){
2021 Tcl_AppendResult(interp, "wrong # args: should be \"",
2022 Tcl_GetString(objv[0]), " DB", 0);
2023 return TCL_ERROR;
2024 }
2025 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2026
2027 zErr = sqlite3_errmsg(db);
2028 Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
2029 return TCL_OK;
2030}
2031
2032/*
2033** Usage: test_errmsg16 DB
2034**
2035** Returns the UTF-16 representation of the error message string for the
2036** most recent sqlite3_* API call. This is a byte array object at the TCL
2037** level, and it includes the 0x00 0x00 terminator bytes at the end of the
2038** UTF-16 string.
2039*/
2040static int test_errmsg16(
2041 void * clientData,
2042 Tcl_Interp *interp,
2043 int objc,
2044 Tcl_Obj *CONST objv[]
2045){
drh5436dc22004-11-14 04:04:17 +00002046#ifndef SQLITE_OMIT_UTF16
drh9bb575f2004-09-06 17:24:11 +00002047 sqlite3 *db;
danielk19776622cce2004-05-20 11:00:52 +00002048 const void *zErr;
2049 int bytes;
2050
2051 if( objc!=2 ){
2052 Tcl_AppendResult(interp, "wrong # args: should be \"",
2053 Tcl_GetString(objv[0]), " DB", 0);
2054 return TCL_ERROR;
2055 }
2056 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2057
2058 zErr = sqlite3_errmsg16(db);
2059 bytes = sqlite3utf16ByteLen(zErr, -1);
2060 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes));
drh5436dc22004-11-14 04:04:17 +00002061#endif /* SQLITE_OMIT_UTF16 */
danielk19776622cce2004-05-20 11:00:52 +00002062 return TCL_OK;
2063}
2064
2065/*
2066** Usage: sqlite3_prepare DB sql bytes tailvar
2067**
2068** Compile up to <bytes> bytes of the supplied SQL string <sql> using
2069** database handle <DB>. The parameter <tailval> is the name of a global
2070** variable that is set to the unused portion of <sql> (if any). A
2071** STMT handle is returned.
2072*/
2073static int test_prepare(
2074 void * clientData,
2075 Tcl_Interp *interp,
2076 int objc,
2077 Tcl_Obj *CONST objv[]
2078){
2079 sqlite3 *db;
2080 const char *zSql;
2081 int bytes;
2082 const char *zTail = 0;
2083 sqlite3_stmt *pStmt = 0;
2084 char zBuf[50];
danielk19774ad17132004-05-21 01:47:26 +00002085 int rc;
danielk19776622cce2004-05-20 11:00:52 +00002086
2087 if( objc!=5 ){
2088 Tcl_AppendResult(interp, "wrong # args: should be \"",
2089 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
2090 return TCL_ERROR;
2091 }
2092 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2093 zSql = Tcl_GetString(objv[2]);
2094 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
2095
danielk19774ad17132004-05-21 01:47:26 +00002096 rc = sqlite3_prepare(db, zSql, bytes, &pStmt, &zTail);
drhc60d0442004-09-30 13:43:13 +00002097 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk19776622cce2004-05-20 11:00:52 +00002098 if( zTail ){
2099 if( bytes>=0 ){
2100 bytes = bytes - (zTail-zSql);
2101 }
2102 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
2103 }
danielk19774ad17132004-05-21 01:47:26 +00002104 if( rc!=SQLITE_OK ){
2105 assert( pStmt==0 );
2106 sprintf(zBuf, "(%d) ", rc);
2107 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
2108 return TCL_ERROR;
2109 }
danielk19776622cce2004-05-20 11:00:52 +00002110
danielk19774ad17132004-05-21 01:47:26 +00002111 if( pStmt ){
2112 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
2113 Tcl_AppendResult(interp, zBuf, 0);
2114 }
danielk19776622cce2004-05-20 11:00:52 +00002115 return TCL_OK;
2116}
2117
2118/*
2119** Usage: sqlite3_prepare DB sql bytes tailvar
2120**
2121** Compile up to <bytes> bytes of the supplied SQL string <sql> using
2122** database handle <DB>. The parameter <tailval> is the name of a global
2123** variable that is set to the unused portion of <sql> (if any). A
2124** STMT handle is returned.
2125*/
2126static int test_prepare16(
2127 void * clientData,
2128 Tcl_Interp *interp,
2129 int objc,
2130 Tcl_Obj *CONST objv[]
2131){
drh5436dc22004-11-14 04:04:17 +00002132#ifndef SQLITE_OMIT_UTF16
danielk19776622cce2004-05-20 11:00:52 +00002133 sqlite3 *db;
2134 const void *zSql;
2135 const void *zTail = 0;
2136 Tcl_Obj *pTail = 0;
2137 sqlite3_stmt *pStmt = 0;
drhc60d0442004-09-30 13:43:13 +00002138 char zBuf[50];
2139 int rc;
danielk19776622cce2004-05-20 11:00:52 +00002140 int bytes; /* The integer specified as arg 3 */
2141 int objlen; /* The byte-array length of arg 2 */
2142
2143 if( objc!=5 ){
2144 Tcl_AppendResult(interp, "wrong # args: should be \"",
2145 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
2146 return TCL_ERROR;
2147 }
2148 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2149 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
2150 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
2151
drhc60d0442004-09-30 13:43:13 +00002152 rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, &zTail);
2153 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
2154 if( rc ){
danielk19776622cce2004-05-20 11:00:52 +00002155 return TCL_ERROR;
2156 }
2157
2158 if( zTail ){
2159 objlen = objlen - ((u8 *)zTail-(u8 *)zSql);
2160 }else{
2161 objlen = 0;
2162 }
2163 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
2164 Tcl_IncrRefCount(pTail);
2165 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
danielk19774ad17132004-05-21 01:47:26 +00002166 Tcl_DecrRefCount(pTail);
danielk19776622cce2004-05-20 11:00:52 +00002167
danielk19774ad17132004-05-21 01:47:26 +00002168 if( pStmt ){
2169 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
2170 }
danielk19776622cce2004-05-20 11:00:52 +00002171 Tcl_AppendResult(interp, zBuf, 0);
drh5436dc22004-11-14 04:04:17 +00002172#endif /* SQLITE_OMIT_UTF16 */
danielk19776622cce2004-05-20 11:00:52 +00002173 return TCL_OK;
2174}
2175
danielk19774ad17132004-05-21 01:47:26 +00002176/*
2177** Usage: sqlite3_open filename ?options-list?
2178*/
2179static int test_open(
2180 void * clientData,
2181 Tcl_Interp *interp,
2182 int objc,
2183 Tcl_Obj *CONST objv[]
2184){
2185 const char *zFilename;
2186 sqlite3 *db;
2187 int rc;
2188 char zBuf[100];
2189
2190 if( objc!=3 && objc!=2 ){
2191 Tcl_AppendResult(interp, "wrong # args: should be \"",
2192 Tcl_GetString(objv[0]), " filename options-list", 0);
2193 return TCL_ERROR;
2194 }
2195
2196 zFilename = Tcl_GetString(objv[1]);
danielk19774f057f92004-06-08 00:02:33 +00002197 rc = sqlite3_open(zFilename, &db);
danielk19774ad17132004-05-21 01:47:26 +00002198
2199 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR;
2200 Tcl_AppendResult(interp, zBuf, 0);
2201 return TCL_OK;
2202}
2203
2204/*
2205** Usage: sqlite3_open16 filename options
2206*/
2207static int test_open16(
2208 void * clientData,
2209 Tcl_Interp *interp,
2210 int objc,
2211 Tcl_Obj *CONST objv[]
2212){
drh5436dc22004-11-14 04:04:17 +00002213#ifndef SQLITE_OMIT_UTF16
danielk19774ad17132004-05-21 01:47:26 +00002214 const void *zFilename;
2215 sqlite3 *db;
2216 int rc;
2217 char zBuf[100];
2218
2219 if( objc!=3 ){
2220 Tcl_AppendResult(interp, "wrong # args: should be \"",
2221 Tcl_GetString(objv[0]), " filename options-list", 0);
2222 return TCL_ERROR;
2223 }
2224
2225 zFilename = Tcl_GetByteArrayFromObj(objv[1], 0);
danielk19774f057f92004-06-08 00:02:33 +00002226 rc = sqlite3_open16(zFilename, &db);
danielk19774ad17132004-05-21 01:47:26 +00002227
2228 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR;
2229 Tcl_AppendResult(interp, zBuf, 0);
drh5436dc22004-11-14 04:04:17 +00002230#endif /* SQLITE_OMIT_UTF16 */
danielk19774ad17132004-05-21 01:47:26 +00002231 return TCL_OK;
2232}
drhd3d39e92004-05-20 22:16:29 +00002233
2234/*
danielk1977bc6ada42004-06-30 08:20:16 +00002235** Usage: sqlite3_complete16 <UTF-16 string>
2236**
2237** Return 1 if the supplied argument is a complete SQL statement, or zero
2238** otherwise.
2239*/
2240static int test_complete16(
2241 void * clientData,
2242 Tcl_Interp *interp,
2243 int objc,
2244 Tcl_Obj *CONST objv[]
2245){
drhccae6022005-02-26 17:31:26 +00002246#if !defined(SQLITE_OMIT_COMPLETE) && !defined(SQLITE_OMIT_UTF16)
danielk1977bc6ada42004-06-30 08:20:16 +00002247 char *zBuf;
2248
2249 if( objc!=2 ){
2250 Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>");
2251 return TCL_ERROR;
2252 }
2253
drh03d847e2005-12-09 20:21:58 +00002254 zBuf = (char*)Tcl_GetByteArrayFromObj(objv[1], 0);
danielk1977bc6ada42004-06-30 08:20:16 +00002255 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf)));
drhccae6022005-02-26 17:31:26 +00002256#endif /* SQLITE_OMIT_COMPLETE && SQLITE_OMIT_UTF16 */
danielk1977bc6ada42004-06-30 08:20:16 +00002257 return TCL_OK;
2258}
2259
2260/*
danielk1977106bb232004-05-21 10:08:53 +00002261** Usage: sqlite3_step STMT
2262**
2263** Advance the statement to the next row.
2264*/
danielk197717240fd2004-05-26 00:07:25 +00002265static int test_step(
danielk1977106bb232004-05-21 10:08:53 +00002266 void * clientData,
2267 Tcl_Interp *interp,
2268 int objc,
2269 Tcl_Obj *CONST objv[]
2270){
2271 sqlite3_stmt *pStmt;
2272 int rc;
2273
danielk1977e1cd9872004-05-22 10:33:04 +00002274 if( objc!=2 ){
danielk1977106bb232004-05-21 10:08:53 +00002275 Tcl_AppendResult(interp, "wrong # args: should be \"",
2276 Tcl_GetString(objv[0]), " STMT", 0);
2277 return TCL_ERROR;
2278 }
2279
2280 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
danielk197717240fd2004-05-26 00:07:25 +00002281 rc = sqlite3_step(pStmt);
danielk1977106bb232004-05-21 10:08:53 +00002282
danielk1977fbcd5852004-06-15 02:44:18 +00002283 /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */
danielk197765904932004-05-26 06:18:37 +00002284 Tcl_SetResult(interp, (char *)errorName(rc), 0);
danielk1977e1cd9872004-05-22 10:33:04 +00002285 return TCL_OK;
2286}
2287
2288/*
danielk197717240fd2004-05-26 00:07:25 +00002289** Usage: sqlite3_column_count STMT
2290**
2291** Return the number of columns returned by the sql statement STMT.
2292*/
2293static int test_column_count(
2294 void * clientData,
2295 Tcl_Interp *interp,
2296 int objc,
2297 Tcl_Obj *CONST objv[]
2298){
2299 sqlite3_stmt *pStmt;
2300
2301 if( objc!=2 ){
2302 Tcl_AppendResult(interp, "wrong # args: should be \"",
2303 Tcl_GetString(objv[0]), " STMT column", 0);
2304 return TCL_ERROR;
2305 }
2306
2307 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2308
2309 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt)));
2310 return TCL_OK;
2311}
2312
2313/*
danielk19773cf86062004-05-26 10:11:05 +00002314** Usage: sqlite3_column_type STMT column
2315**
2316** Return the type of the data in column 'column' of the current row.
2317*/
2318static int test_column_type(
2319 void * clientData,
2320 Tcl_Interp *interp,
2321 int objc,
2322 Tcl_Obj *CONST objv[]
2323){
2324 sqlite3_stmt *pStmt;
2325 int col;
2326 int tp;
2327
2328 if( objc!=3 ){
2329 Tcl_AppendResult(interp, "wrong # args: should be \"",
2330 Tcl_GetString(objv[0]), " STMT column", 0);
2331 return TCL_ERROR;
2332 }
2333
2334 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2335 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2336
2337 tp = sqlite3_column_type(pStmt, col);
2338 switch( tp ){
drh9c054832004-05-31 18:51:57 +00002339 case SQLITE_INTEGER:
danielk19773cf86062004-05-26 10:11:05 +00002340 Tcl_SetResult(interp, "INTEGER", TCL_STATIC);
2341 break;
drh9c054832004-05-31 18:51:57 +00002342 case SQLITE_NULL:
danielk19773cf86062004-05-26 10:11:05 +00002343 Tcl_SetResult(interp, "NULL", TCL_STATIC);
2344 break;
drh9c054832004-05-31 18:51:57 +00002345 case SQLITE_FLOAT:
danielk19773cf86062004-05-26 10:11:05 +00002346 Tcl_SetResult(interp, "FLOAT", TCL_STATIC);
2347 break;
drh9c054832004-05-31 18:51:57 +00002348 case SQLITE_TEXT:
danielk19773cf86062004-05-26 10:11:05 +00002349 Tcl_SetResult(interp, "TEXT", TCL_STATIC);
2350 break;
drh9c054832004-05-31 18:51:57 +00002351 case SQLITE_BLOB:
danielk19773cf86062004-05-26 10:11:05 +00002352 Tcl_SetResult(interp, "BLOB", TCL_STATIC);
2353 break;
2354 default:
2355 assert(0);
2356 }
2357
2358 return TCL_OK;
2359}
2360
2361/*
danielk197704f2e682004-05-27 01:04:07 +00002362** Usage: sqlite3_column_int64 STMT column
danielk19773cf86062004-05-26 10:11:05 +00002363**
2364** Return the data in column 'column' of the current row cast as an
danielk197704f2e682004-05-27 01:04:07 +00002365** wide (64-bit) integer.
danielk19773cf86062004-05-26 10:11:05 +00002366*/
danielk197704f2e682004-05-27 01:04:07 +00002367static int test_column_int64(
danielk19773cf86062004-05-26 10:11:05 +00002368 void * clientData,
2369 Tcl_Interp *interp,
2370 int objc,
2371 Tcl_Obj *CONST objv[]
2372){
2373 sqlite3_stmt *pStmt;
2374 int col;
danielk197704f2e682004-05-27 01:04:07 +00002375 i64 iVal;
danielk19773cf86062004-05-26 10:11:05 +00002376
2377 if( objc!=3 ){
2378 Tcl_AppendResult(interp, "wrong # args: should be \"",
2379 Tcl_GetString(objv[0]), " STMT column", 0);
2380 return TCL_ERROR;
2381 }
2382
2383 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2384 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2385
danielk197704f2e682004-05-27 01:04:07 +00002386 iVal = sqlite3_column_int64(pStmt, col);
2387 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal));
2388 return TCL_OK;
2389}
2390
2391/*
danielk1977ea61b2c2004-05-27 01:49:51 +00002392** Usage: sqlite3_column_blob STMT column
2393*/
2394static int test_column_blob(
2395 void * clientData,
2396 Tcl_Interp *interp,
2397 int objc,
2398 Tcl_Obj *CONST objv[]
2399){
2400 sqlite3_stmt *pStmt;
2401 int col;
2402
2403 int len;
danielk1977c572ef72004-05-27 09:28:41 +00002404 const void *pBlob;
danielk1977ea61b2c2004-05-27 01:49:51 +00002405
2406 if( objc!=3 ){
2407 Tcl_AppendResult(interp, "wrong # args: should be \"",
2408 Tcl_GetString(objv[0]), " STMT column", 0);
2409 return TCL_ERROR;
2410 }
2411
2412 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2413 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2414
2415 pBlob = sqlite3_column_blob(pStmt, col);
2416 len = sqlite3_column_bytes(pStmt, col);
2417 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len));
2418 return TCL_OK;
2419}
2420
2421/*
danielk197704f2e682004-05-27 01:04:07 +00002422** Usage: sqlite3_column_double STMT column
2423**
2424** Return the data in column 'column' of the current row cast as a double.
2425*/
2426static int test_column_double(
2427 void * clientData,
2428 Tcl_Interp *interp,
2429 int objc,
2430 Tcl_Obj *CONST objv[]
2431){
2432 sqlite3_stmt *pStmt;
2433 int col;
2434 double rVal;
2435
2436 if( objc!=3 ){
2437 Tcl_AppendResult(interp, "wrong # args: should be \"",
2438 Tcl_GetString(objv[0]), " STMT column", 0);
2439 return TCL_ERROR;
2440 }
2441
2442 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2443 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2444
2445 rVal = sqlite3_column_double(pStmt, col);
danielk1977c572ef72004-05-27 09:28:41 +00002446 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal));
danielk19773cf86062004-05-26 10:11:05 +00002447 return TCL_OK;
2448}
2449
2450/*
danielk197717240fd2004-05-26 00:07:25 +00002451** Usage: sqlite3_data_count STMT
2452**
2453** Return the number of columns returned by the sql statement STMT.
2454*/
2455static int test_data_count(
2456 void * clientData,
2457 Tcl_Interp *interp,
2458 int objc,
2459 Tcl_Obj *CONST objv[]
2460){
2461 sqlite3_stmt *pStmt;
2462
2463 if( objc!=2 ){
2464 Tcl_AppendResult(interp, "wrong # args: should be \"",
2465 Tcl_GetString(objv[0]), " STMT column", 0);
2466 return TCL_ERROR;
2467 }
2468
2469 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2470
2471 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt)));
2472 return TCL_OK;
2473}
2474
2475/*
danielk197704f2e682004-05-27 01:04:07 +00002476** Usage: sqlite3_column_text STMT column
2477**
2478** Usage: sqlite3_column_decltype STMT column
2479**
2480** Usage: sqlite3_column_name STMT column
2481*/
2482static int test_stmt_utf8(
drh241db312004-06-22 12:46:53 +00002483 void * clientData, /* Pointer to SQLite API function to be invoke */
danielk197704f2e682004-05-27 01:04:07 +00002484 Tcl_Interp *interp,
2485 int objc,
2486 Tcl_Obj *CONST objv[]
2487){
2488 sqlite3_stmt *pStmt;
2489 int col;
danielk1977c572ef72004-05-27 09:28:41 +00002490 const char *(*xFunc)(sqlite3_stmt*, int) = clientData;
danielk1977f93bbbe2004-05-27 10:30:52 +00002491 const char *zRet;
danielk197704f2e682004-05-27 01:04:07 +00002492
2493 if( objc!=3 ){
2494 Tcl_AppendResult(interp, "wrong # args: should be \"",
2495 Tcl_GetString(objv[0]), " STMT column", 0);
2496 return TCL_ERROR;
2497 }
2498
2499 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2500 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
danielk1977f93bbbe2004-05-27 10:30:52 +00002501 zRet = xFunc(pStmt, col);
2502 if( zRet ){
2503 Tcl_SetResult(interp, (char *)zRet, 0);
2504 }
danielk197704f2e682004-05-27 01:04:07 +00002505 return TCL_OK;
2506}
2507
danielk19776b456a22005-03-21 04:04:02 +00002508static int test_global_recover(
2509 void * clientData,
2510 Tcl_Interp *interp,
2511 int objc,
2512 Tcl_Obj *CONST objv[]
2513){
2514#ifndef SQLITE_OMIT_GLOBALRECOVER
2515 int rc;
2516 if( objc!=1 ){
2517 Tcl_WrongNumArgs(interp, 1, objv, "");
2518 return TCL_ERROR;
2519 }
2520 rc = sqlite3_global_recover();
2521 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2522#endif
2523 return TCL_OK;
2524}
2525
danielk197704f2e682004-05-27 01:04:07 +00002526/*
2527** Usage: sqlite3_column_text STMT column
2528**
2529** Usage: sqlite3_column_decltype STMT column
2530**
2531** Usage: sqlite3_column_name STMT column
2532*/
2533static int test_stmt_utf16(
drh241db312004-06-22 12:46:53 +00002534 void * clientData, /* Pointer to SQLite API function to be invoked */
danielk197704f2e682004-05-27 01:04:07 +00002535 Tcl_Interp *interp,
2536 int objc,
2537 Tcl_Obj *CONST objv[]
2538){
drh5436dc22004-11-14 04:04:17 +00002539#ifndef SQLITE_OMIT_UTF16
danielk197704f2e682004-05-27 01:04:07 +00002540 sqlite3_stmt *pStmt;
2541 int col;
2542 Tcl_Obj *pRet;
2543 const void *zName16;
danielk1977c572ef72004-05-27 09:28:41 +00002544 const void *(*xFunc)(sqlite3_stmt*, int) = clientData;
danielk197704f2e682004-05-27 01:04:07 +00002545
2546 if( objc!=3 ){
2547 Tcl_AppendResult(interp, "wrong # args: should be \"",
2548 Tcl_GetString(objv[0]), " STMT column", 0);
2549 return TCL_ERROR;
2550 }
2551
2552 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2553 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2554
2555 zName16 = xFunc(pStmt, col);
danielk1977f93bbbe2004-05-27 10:30:52 +00002556 if( zName16 ){
2557 pRet = Tcl_NewByteArrayObj(zName16, sqlite3utf16ByteLen(zName16, -1)+2);
2558 Tcl_SetObjResult(interp, pRet);
2559 }
drh5436dc22004-11-14 04:04:17 +00002560#endif /* SQLITE_OMIT_UTF16 */
danielk197704f2e682004-05-27 01:04:07 +00002561
2562 return TCL_OK;
2563}
2564
2565/*
2566** Usage: sqlite3_column_int STMT column
2567**
2568** Usage: sqlite3_column_bytes STMT column
2569**
2570** Usage: sqlite3_column_bytes16 STMT column
2571**
2572*/
2573static int test_stmt_int(
drh241db312004-06-22 12:46:53 +00002574 void * clientData, /* Pointer to SQLite API function to be invoked */
danielk197704f2e682004-05-27 01:04:07 +00002575 Tcl_Interp *interp,
2576 int objc,
2577 Tcl_Obj *CONST objv[]
2578){
2579 sqlite3_stmt *pStmt;
2580 int col;
danielk1977c572ef72004-05-27 09:28:41 +00002581 int (*xFunc)(sqlite3_stmt*, int) = clientData;
danielk197704f2e682004-05-27 01:04:07 +00002582
2583 if( objc!=3 ){
2584 Tcl_AppendResult(interp, "wrong # args: should be \"",
2585 Tcl_GetString(objv[0]), " STMT column", 0);
2586 return TCL_ERROR;
2587 }
2588
2589 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2590 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2591
2592 Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col)));
2593 return TCL_OK;
2594}
2595
danielk197744ee5bf2005-05-27 09:41:12 +00002596#ifndef SQLITE_OMIT_DISKIO
danielk19779a1d0ab2004-06-01 14:09:28 +00002597/*
2598** Usage: sqlite3OsOpenReadWrite <filename>
2599*/
2600static int test_sqlite3OsOpenReadWrite(
2601 void * clientData,
2602 Tcl_Interp *interp,
2603 int objc,
2604 Tcl_Obj *CONST objv[]
2605){
drh9cbe6352005-11-29 03:13:21 +00002606 OsFile *pFile;
danielk19779a1d0ab2004-06-01 14:09:28 +00002607 int rc;
2608 int dummy;
2609 char zBuf[100];
danielk197704f2e682004-05-27 01:04:07 +00002610
danielk19779a1d0ab2004-06-01 14:09:28 +00002611 if( objc!=2 ){
2612 Tcl_AppendResult(interp, "wrong # args: should be \"",
2613 Tcl_GetString(objv[0]), " filename", 0);
2614 return TCL_ERROR;
2615 }
2616
drh66560ad2006-01-06 14:32:19 +00002617 rc = sqlite3OsOpenReadWrite(Tcl_GetString(objv[1]), &pFile, &dummy);
danielk19779a1d0ab2004-06-01 14:09:28 +00002618 if( rc!=SQLITE_OK ){
danielk19779a1d0ab2004-06-01 14:09:28 +00002619 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2620 return TCL_ERROR;
2621 }
2622 makePointerStr(interp, zBuf, pFile);
2623 Tcl_SetResult(interp, zBuf, 0);
2624 return TCL_ERROR;
2625}
2626
2627/*
2628** Usage: sqlite3OsClose <file handle>
2629*/
2630static int test_sqlite3OsClose(
2631 void * clientData,
2632 Tcl_Interp *interp,
2633 int objc,
2634 Tcl_Obj *CONST objv[]
2635){
drh9cbe6352005-11-29 03:13:21 +00002636 OsFile *pFile;
danielk19779a1d0ab2004-06-01 14:09:28 +00002637 int rc;
2638
2639 if( objc!=2 ){
2640 Tcl_AppendResult(interp, "wrong # args: should be \"",
2641 Tcl_GetString(objv[0]), " filehandle", 0);
2642 return TCL_ERROR;
2643 }
2644
2645 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
2646 return TCL_ERROR;
2647 }
drh054889e2005-11-30 03:20:31 +00002648 rc = sqlite3OsClose(&pFile);
danielk19779a1d0ab2004-06-01 14:09:28 +00002649 if( rc!=SQLITE_OK ){
2650 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2651 return TCL_ERROR;
2652 }
danielk19779a1d0ab2004-06-01 14:09:28 +00002653 return TCL_OK;
2654}
2655
2656/*
2657** Usage: sqlite3OsLock <file handle> <locktype>
2658*/
2659static int test_sqlite3OsLock(
2660 void * clientData,
2661 Tcl_Interp *interp,
2662 int objc,
2663 Tcl_Obj *CONST objv[]
2664){
2665 OsFile * pFile;
2666 int rc;
2667
2668 if( objc!=3 ){
2669 Tcl_AppendResult(interp, "wrong # args: should be \"",
2670 Tcl_GetString(objv[0]),
2671 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
2672 return TCL_ERROR;
2673 }
2674
2675 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
2676 return TCL_ERROR;
2677 }
2678
2679 if( 0==strcmp("SHARED", Tcl_GetString(objv[2])) ){
drh054889e2005-11-30 03:20:31 +00002680 rc = sqlite3OsLock(pFile, SHARED_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00002681 }
2682 else if( 0==strcmp("RESERVED", Tcl_GetString(objv[2])) ){
drh054889e2005-11-30 03:20:31 +00002683 rc = sqlite3OsLock(pFile, RESERVED_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00002684 }
2685 else if( 0==strcmp("PENDING", Tcl_GetString(objv[2])) ){
drh054889e2005-11-30 03:20:31 +00002686 rc = sqlite3OsLock(pFile, PENDING_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00002687 }
2688 else if( 0==strcmp("EXCLUSIVE", Tcl_GetString(objv[2])) ){
drh054889e2005-11-30 03:20:31 +00002689 rc = sqlite3OsLock(pFile, EXCLUSIVE_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00002690 }else{
2691 Tcl_AppendResult(interp, "wrong # args: should be \"",
2692 Tcl_GetString(objv[0]),
2693 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
2694 return TCL_ERROR;
2695 }
2696
2697 if( rc!=SQLITE_OK ){
2698 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2699 return TCL_ERROR;
2700 }
2701 return TCL_OK;
2702}
2703
2704/*
2705** Usage: sqlite3OsUnlock <file handle>
2706*/
2707static int test_sqlite3OsUnlock(
2708 void * clientData,
2709 Tcl_Interp *interp,
2710 int objc,
2711 Tcl_Obj *CONST objv[]
2712){
2713 OsFile * pFile;
2714 int rc;
2715
2716 if( objc!=2 ){
2717 Tcl_AppendResult(interp, "wrong # args: should be \"",
2718 Tcl_GetString(objv[0]), " filehandle", 0);
2719 return TCL_ERROR;
2720 }
2721
2722 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
2723 return TCL_ERROR;
2724 }
drh054889e2005-11-30 03:20:31 +00002725 rc = sqlite3OsUnlock(pFile, NO_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00002726 if( rc!=SQLITE_OK ){
2727 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2728 return TCL_ERROR;
2729 }
2730 return TCL_OK;
2731}
drhd3d39e92004-05-20 22:16:29 +00002732
drhab3f9fe2004-08-14 17:10:10 +00002733/*
2734** Usage: sqlite3OsTempFileName
2735*/
2736static int test_sqlite3OsTempFileName(
2737 void * clientData,
2738 Tcl_Interp *interp,
2739 int objc,
2740 Tcl_Obj *CONST objv[]
2741){
2742 char zFile[SQLITE_TEMPNAME_SIZE];
2743 int rc;
2744
drh66560ad2006-01-06 14:32:19 +00002745 rc = sqlite3OsTempFileName(zFile);
drhab3f9fe2004-08-14 17:10:10 +00002746 if( rc!=SQLITE_OK ){
2747 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2748 return TCL_ERROR;
2749 }
2750 Tcl_AppendResult(interp, zFile, 0);
2751 return TCL_OK;
2752}
danielk197744ee5bf2005-05-27 09:41:12 +00002753#endif
danielk1977d8123362004-06-12 09:25:12 +00002754
danielk19776622cce2004-05-20 11:00:52 +00002755/*
drhcacb2082005-01-11 15:28:33 +00002756** Usage: sqlite_set_magic DB MAGIC-NUMBER
2757**
2758** Set the db->magic value. This is used to test error recovery logic.
2759*/
2760static int sqlite_set_magic(
2761 void * clientData,
2762 Tcl_Interp *interp,
2763 int argc,
2764 char **argv
2765){
2766 sqlite3 *db;
2767 if( argc!=3 ){
2768 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2769 " DB MAGIC", 0);
2770 return TCL_ERROR;
2771 }
2772 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2773 if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){
2774 db->magic = SQLITE_MAGIC_OPEN;
2775 }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){
2776 db->magic = SQLITE_MAGIC_CLOSED;
2777 }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){
2778 db->magic = SQLITE_MAGIC_BUSY;
2779 }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){
2780 db->magic = SQLITE_MAGIC_ERROR;
2781 }else if( Tcl_GetInt(interp, argv[2], &db->magic) ){
2782 return TCL_ERROR;
2783 }
2784 return TCL_OK;
2785}
2786
2787/*
drhc5cdca62005-01-11 16:54:14 +00002788** Usage: sqlite3_interrupt DB
2789**
2790** Trigger an interrupt on DB
2791*/
2792static int test_interrupt(
2793 void * clientData,
2794 Tcl_Interp *interp,
2795 int argc,
2796 char **argv
2797){
2798 sqlite3 *db;
2799 if( argc!=2 ){
2800 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
2801 return TCL_ERROR;
2802 }
2803 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2804 sqlite3_interrupt(db);
2805 return TCL_OK;
2806}
2807
drh79158e12005-09-06 21:40:45 +00002808static u8 *sqlite3_stack_baseline = 0;
2809
drhc5cdca62005-01-11 16:54:14 +00002810/*
drh79158e12005-09-06 21:40:45 +00002811** Fill the stack with a known bitpattern.
danielk1977600dd0b2005-01-20 01:14:23 +00002812*/
drh79158e12005-09-06 21:40:45 +00002813static void prepStack(void){
2814 int i;
2815 u32 bigBuf[65536];
2816 for(i=0; i<sizeof(bigBuf); i++) bigBuf[i] = 0xdeadbeef;
2817 sqlite3_stack_baseline = (u8*)&bigBuf[65536];
2818}
2819
2820/*
2821** Get the current stack depth. Used for debugging only.
2822*/
2823u64 sqlite3StackDepth(void){
2824 u8 x;
2825 return (u64)(sqlite3_stack_baseline - &x);
2826}
2827
2828/*
2829** Usage: sqlite3_stack_used DB SQL
2830**
2831** Try to measure the amount of stack space used by a call to sqlite3_exec
2832*/
2833static int test_stack_used(
danielk1977600dd0b2005-01-20 01:14:23 +00002834 void * clientData,
2835 Tcl_Interp *interp,
2836 int argc,
2837 char **argv
2838){
2839 sqlite3 *db;
drh79158e12005-09-06 21:40:45 +00002840 int i;
2841 if( argc!=3 ){
2842 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2843 " DB SQL", 0);
danielk1977600dd0b2005-01-20 01:14:23 +00002844 return TCL_ERROR;
2845 }
drh79158e12005-09-06 21:40:45 +00002846 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2847 prepStack();
2848 sqlite3_exec(db, argv[2], 0, 0, 0);
2849 for(i=65535; i>=0 && ((u32*)sqlite3_stack_baseline)[-i]==0xdeadbeef; i--){}
2850 Tcl_SetObjResult(interp, Tcl_NewIntObj(i*4));
danielk1977600dd0b2005-01-20 01:14:23 +00002851 return TCL_OK;
2852}
danielk1977600dd0b2005-01-20 01:14:23 +00002853
2854/*
danielk19779636c4e2005-01-25 04:27:54 +00002855** Usage: sqlite_delete_function DB function-name
2856**
2857** Delete the user function 'function-name' from database handle DB. It
2858** is assumed that the user function was created as UTF8, any number of
2859** arguments (the way the TCL interface does it).
2860*/
2861static int delete_function(
2862 void * clientData,
2863 Tcl_Interp *interp,
2864 int argc,
2865 char **argv
2866){
2867 int rc;
2868 sqlite3 *db;
2869 if( argc!=3 ){
2870 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2871 " DB function-name", 0);
2872 return TCL_ERROR;
2873 }
2874 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2875 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0);
2876 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2877 return TCL_OK;
2878}
2879
2880/*
2881** Usage: sqlite_delete_collation DB collation-name
2882**
2883** Delete the collation sequence 'collation-name' from database handle
2884** DB. It is assumed that the collation sequence was created as UTF8 (the
2885** way the TCL interface does it).
2886*/
2887static int delete_collation(
2888 void * clientData,
2889 Tcl_Interp *interp,
2890 int argc,
2891 char **argv
2892){
2893 int rc;
2894 sqlite3 *db;
2895 if( argc!=3 ){
2896 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2897 " DB function-name", 0);
2898 return TCL_ERROR;
2899 }
2900 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2901 rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0);
2902 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2903 return TCL_OK;
2904}
2905
2906/*
drh3e1d8e62005-05-26 16:23:34 +00002907** Usage: sqlite3_get_autocommit DB
2908**
2909** Return true if the database DB is currently in auto-commit mode.
2910** Return false if not.
2911*/
2912static int get_autocommit(
2913 void * clientData,
2914 Tcl_Interp *interp,
2915 int argc,
2916 char **argv
2917){
2918 char zBuf[30];
2919 sqlite3 *db;
2920 if( argc!=2 ){
2921 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2922 " DB", 0);
2923 return TCL_ERROR;
2924 }
2925 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2926 sprintf(zBuf, "%d", sqlite3_get_autocommit(db));
2927 Tcl_AppendResult(interp, zBuf, 0);
2928 return TCL_OK;
2929}
2930
2931/*
drh92febd92004-08-20 18:34:20 +00002932** Usage: tcl_variable_type VARIABLENAME
2933**
2934** Return the name of the internal representation for the
2935** value of the given variable.
2936*/
2937static int tcl_variable_type(
2938 void * clientData,
2939 Tcl_Interp *interp,
2940 int objc,
2941 Tcl_Obj *CONST objv[]
2942){
2943 Tcl_Obj *pVar;
2944 if( objc!=2 ){
2945 Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE");
2946 return TCL_ERROR;
2947 }
2948 pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG);
2949 if( pVar==0 ) return TCL_ERROR;
2950 if( pVar->typePtr ){
2951 Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1));
2952 }
2953 return TCL_OK;
2954}
2955
2956/*
drh6aafc292006-01-05 15:50:06 +00002957** Usage: sqlite3_release_memory ?N?
2958**
2959** Attempt to release memory currently held but not actually required.
2960** The integer N is the number of bytes we are trying to release. The
2961** return value is the amount of memory actually released.
2962*/
2963static int test_release_memory(
2964 void * clientData,
2965 Tcl_Interp *interp,
2966 int objc,
2967 Tcl_Obj *CONST objv[]
2968){
drh198bf392006-01-06 21:52:49 +00002969#if !defined(SQLITE_OMIT_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
drh6aafc292006-01-05 15:50:06 +00002970 int N;
2971 int amt;
2972 if( objc!=1 && objc!=2 ){
2973 Tcl_WrongNumArgs(interp, 1, objv, "?N?");
2974 return TCL_ERROR;
2975 }
2976 if( objc==2 ){
2977 if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
2978 }else{
2979 N = -1;
2980 }
2981 amt = sqlite3_release_memory(N);
2982 Tcl_SetObjResult(interp, Tcl_NewIntObj(amt));
2983#endif
2984 return TCL_OK;
2985}
2986
2987/*
2988** Usage: sqlite3_soft_heap_limit ?N?
2989**
2990** Query or set the soft heap limit for the current thread. The
2991** limit is only changed if the N is present. The previous limit
2992** is returned.
2993*/
2994static int test_soft_heap_limit(
2995 void * clientData,
2996 Tcl_Interp *interp,
2997 int objc,
2998 Tcl_Obj *CONST objv[]
2999){
drh198bf392006-01-06 21:52:49 +00003000#if !defined(SQLITE_OMIT_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
drh6aafc292006-01-05 15:50:06 +00003001 int amt;
3002 if( objc!=1 && objc!=2 ){
3003 Tcl_WrongNumArgs(interp, 1, objv, "?N?");
3004 return TCL_ERROR;
3005 }
danielk1977e501b892006-01-09 06:29:47 +00003006 amt = sqlite3ThreadData()->nSoftHeapLimit;
drh6aafc292006-01-05 15:50:06 +00003007 if( objc==2 ){
3008 int N;
3009 if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
3010 sqlite3_soft_heap_limit(N);
3011 }
3012 Tcl_SetObjResult(interp, Tcl_NewIntObj(amt));
3013#endif
3014 return TCL_OK;
3015}
3016
3017/*
drh27d258a2004-10-30 20:23:09 +00003018** This routine sets entries in the global ::sqlite_options() array variable
3019** according to the compile-time configuration of the database. Test
3020** procedures use this to determine when tests should be omitted.
3021*/
3022static void set_options(Tcl_Interp *interp){
drh75f86a42005-02-17 00:03:06 +00003023#ifdef SQLITE_32BIT_ROWID
3024 Tcl_SetVar2(interp, "sqlite_options", "rowid32", "1", TCL_GLOBAL_ONLY);
3025#else
3026 Tcl_SetVar2(interp, "sqlite_options", "rowid32", "0", TCL_GLOBAL_ONLY);
3027#endif
3028
drh9f18e8a2005-07-08 12:13:04 +00003029#ifdef SQLITE_CASE_SENSITIVE_LIKE
3030 Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","1",TCL_GLOBAL_ONLY);
3031#else
3032 Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","0",TCL_GLOBAL_ONLY);
3033#endif
3034
danielk1977d7c03f72005-11-25 10:38:22 +00003035#ifdef SQLITE_DISABLE_DIRSYNC
3036 Tcl_SetVar2(interp, "sqlite_options", "dirsync", "0", TCL_GLOBAL_ONLY);
3037#else
3038 Tcl_SetVar2(interp, "sqlite_options", "dirsync", "1", TCL_GLOBAL_ONLY);
3039#endif
3040
danielk197726c5d792005-11-25 09:01:23 +00003041#ifdef SQLITE_DISABLE_LFS
3042 Tcl_SetVar2(interp, "sqlite_options", "lfs", "0", TCL_GLOBAL_ONLY);
3043#else
3044 Tcl_SetVar2(interp, "sqlite_options", "lfs", "1", TCL_GLOBAL_ONLY);
3045#endif
3046
danielk19771c8c23c2004-11-12 15:53:37 +00003047#ifdef SQLITE_OMIT_ALTERTABLE
3048 Tcl_SetVar2(interp, "sqlite_options", "altertable", "0", TCL_GLOBAL_ONLY);
3049#else
3050 Tcl_SetVar2(interp, "sqlite_options", "altertable", "1", TCL_GLOBAL_ONLY);
3051#endif
drh13d70422004-11-13 15:59:14 +00003052
drh9f18e8a2005-07-08 12:13:04 +00003053#ifdef SQLITE_OMIT_ANALYZE
3054 Tcl_SetVar2(interp, "sqlite_options", "analyze", "0", TCL_GLOBAL_ONLY);
3055#else
3056 Tcl_SetVar2(interp, "sqlite_options", "analyze", "1", TCL_GLOBAL_ONLY);
3057#endif
3058
drh13d70422004-11-13 15:59:14 +00003059#ifdef SQLITE_OMIT_AUTHORIZATION
3060 Tcl_SetVar2(interp, "sqlite_options", "auth", "0", TCL_GLOBAL_ONLY);
3061#else
3062 Tcl_SetVar2(interp, "sqlite_options", "auth", "1", TCL_GLOBAL_ONLY);
3063#endif
3064
drhf3388142004-11-13 03:48:06 +00003065#ifdef SQLITE_OMIT_AUTOINCREMENT
3066 Tcl_SetVar2(interp, "sqlite_options", "autoinc", "0", TCL_GLOBAL_ONLY);
3067#else
3068 Tcl_SetVar2(interp, "sqlite_options", "autoinc", "1", TCL_GLOBAL_ONLY);
3069#endif
3070
danielk197745901d62004-11-10 15:27:38 +00003071#ifdef SQLITE_OMIT_AUTOVACUUM
3072 Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "0", TCL_GLOBAL_ONLY);
3073#else
3074 Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "1", TCL_GLOBAL_ONLY);
drhf3388142004-11-13 03:48:06 +00003075#endif /* SQLITE_OMIT_AUTOVACUUM */
danielk19774d36b812004-11-19 07:07:30 +00003076#if !defined(SQLITE_DEFAULT_AUTOVACUUM) || SQLITE_DEFAULT_AUTOVACUUM==0
danielk197745901d62004-11-10 15:27:38 +00003077 Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","0",TCL_GLOBAL_ONLY);
3078#else
3079 Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","1",TCL_GLOBAL_ONLY);
3080#endif
drh13d70422004-11-13 15:59:14 +00003081
drh55ef4d92005-08-14 01:20:37 +00003082#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
3083 Tcl_SetVar2(interp, "sqlite_options", "between_opt", "0", TCL_GLOBAL_ONLY);
3084#else
3085 Tcl_SetVar2(interp, "sqlite_options", "between_opt", "1", TCL_GLOBAL_ONLY);
3086#endif
3087
drh13d70422004-11-13 15:59:14 +00003088#ifdef SQLITE_OMIT_BLOB_LITERAL
3089 Tcl_SetVar2(interp, "sqlite_options", "bloblit", "0", TCL_GLOBAL_ONLY);
3090#else
3091 Tcl_SetVar2(interp, "sqlite_options", "bloblit", "1", TCL_GLOBAL_ONLY);
3092#endif
3093
drh487e2622005-06-25 18:42:14 +00003094#ifdef SQLITE_OMIT_CAST
3095 Tcl_SetVar2(interp, "sqlite_options", "cast", "0", TCL_GLOBAL_ONLY);
3096#else
3097 Tcl_SetVar2(interp, "sqlite_options", "cast", "1", TCL_GLOBAL_ONLY);
3098#endif
3099
drhffe07b22005-11-03 00:41:17 +00003100#ifdef SQLITE_OMIT_CHECK
3101 Tcl_SetVar2(interp, "sqlite_options", "check", "0", TCL_GLOBAL_ONLY);
3102#else
3103 Tcl_SetVar2(interp, "sqlite_options", "check", "1", TCL_GLOBAL_ONLY);
3104#endif
3105
drhccae6022005-02-26 17:31:26 +00003106#ifdef SQLITE_OMIT_COMPLETE
3107 Tcl_SetVar2(interp, "sqlite_options", "complete", "0", TCL_GLOBAL_ONLY);
3108#else
3109 Tcl_SetVar2(interp, "sqlite_options", "complete", "1", TCL_GLOBAL_ONLY);
3110#endif
3111
drh13d70422004-11-13 15:59:14 +00003112#ifdef SQLITE_OMIT_COMPOUND_SELECT
3113 Tcl_SetVar2(interp, "sqlite_options", "compound", "0", TCL_GLOBAL_ONLY);
3114#else
3115 Tcl_SetVar2(interp, "sqlite_options", "compound", "1", TCL_GLOBAL_ONLY);
3116#endif
3117
3118#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
3119 Tcl_SetVar2(interp, "sqlite_options", "conflict", "0", TCL_GLOBAL_ONLY);
3120#else
3121 Tcl_SetVar2(interp, "sqlite_options", "conflict", "1", TCL_GLOBAL_ONLY);
3122#endif
3123
drh66560ad2006-01-06 14:32:19 +00003124#if OS_UNIX
3125 Tcl_SetVar2(interp, "sqlite_options", "crashtest", "1", TCL_GLOBAL_ONLY);
3126#else
3127 Tcl_SetVar2(interp, "sqlite_options", "crashtest", "0", TCL_GLOBAL_ONLY);
3128#endif
3129
drh13d70422004-11-13 15:59:14 +00003130#ifdef SQLITE_OMIT_DATETIME_FUNCS
3131 Tcl_SetVar2(interp, "sqlite_options", "datetime", "0", TCL_GLOBAL_ONLY);
3132#else
3133 Tcl_SetVar2(interp, "sqlite_options", "datetime", "1", TCL_GLOBAL_ONLY);
3134#endif
3135
drh2e66f0b2005-04-28 17:18:48 +00003136#ifdef SQLITE_OMIT_DISKIO
3137 Tcl_SetVar2(interp, "sqlite_options", "diskio", "0", TCL_GLOBAL_ONLY);
3138#else
3139 Tcl_SetVar2(interp, "sqlite_options", "diskio", "1", TCL_GLOBAL_ONLY);
3140#endif
3141
drh13d70422004-11-13 15:59:14 +00003142#ifdef SQLITE_OMIT_EXPLAIN
3143 Tcl_SetVar2(interp, "sqlite_options", "explain", "0", TCL_GLOBAL_ONLY);
3144#else
3145 Tcl_SetVar2(interp, "sqlite_options", "explain", "1", TCL_GLOBAL_ONLY);
3146#endif
3147
3148#ifdef SQLITE_OMIT_FLOATING_POINT
3149 Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "0", TCL_GLOBAL_ONLY);
3150#else
3151 Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "1", TCL_GLOBAL_ONLY);
3152#endif
3153
3154#ifdef SQLITE_OMIT_FOREIGN_KEY
3155 Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "0", TCL_GLOBAL_ONLY);
3156#else
3157 Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "1", TCL_GLOBAL_ONLY);
3158#endif
3159
danielk19776b456a22005-03-21 04:04:02 +00003160#ifdef SQLITE_OMIT_GLOBALRECOVER
3161 Tcl_SetVar2(interp, "sqlite_options", "globalrecover", "0", TCL_GLOBAL_ONLY);
3162#else
3163 Tcl_SetVar2(interp, "sqlite_options", "globalrecover", "1", TCL_GLOBAL_ONLY);
3164#endif
3165
drh13d70422004-11-13 15:59:14 +00003166#ifdef SQLITE_OMIT_INTEGRITY_CHECK
3167 Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
3168#else
3169 Tcl_SetVar2(interp, "sqlite_options", "integrityck", "1", TCL_GLOBAL_ONLY);
3170#endif
3171
drh55ef4d92005-08-14 01:20:37 +00003172#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
3173 Tcl_SetVar2(interp, "sqlite_options", "like_opt", "0", TCL_GLOBAL_ONLY);
3174#else
3175 Tcl_SetVar2(interp, "sqlite_options", "like_opt", "1", TCL_GLOBAL_ONLY);
3176#endif
3177
drh13d70422004-11-13 15:59:14 +00003178#ifdef SQLITE_OMIT_MEMORYDB
3179 Tcl_SetVar2(interp, "sqlite_options", "memorydb", "0", TCL_GLOBAL_ONLY);
3180#else
3181 Tcl_SetVar2(interp, "sqlite_options", "memorydb", "1", TCL_GLOBAL_ONLY);
3182#endif
3183
drh6aafc292006-01-05 15:50:06 +00003184#ifdef SQLITE_OMIT_MEMORY_MANAGEMENT
3185 Tcl_SetVar2(interp, "sqlite_options", "memorymanage", "0", TCL_GLOBAL_ONLY);
3186#else
3187 Tcl_SetVar2(interp, "sqlite_options", "memorymanage", "1", TCL_GLOBAL_ONLY);
3188#endif
3189
drh55ef4d92005-08-14 01:20:37 +00003190#ifdef SQLITE_OMIT_OR_OPTIMIZATION
3191 Tcl_SetVar2(interp, "sqlite_options", "or_opt", "0", TCL_GLOBAL_ONLY);
3192#else
3193 Tcl_SetVar2(interp, "sqlite_options", "or_opt", "1", TCL_GLOBAL_ONLY);
3194#endif
3195
drh13d70422004-11-13 15:59:14 +00003196#ifdef SQLITE_OMIT_PAGER_PRAGMAS
3197 Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "0", TCL_GLOBAL_ONLY);
3198#else
3199 Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "1", TCL_GLOBAL_ONLY);
3200#endif
3201
drh2e66f0b2005-04-28 17:18:48 +00003202#ifdef SQLITE_OMIT_PARSER
3203 Tcl_SetVar2(interp, "sqlite_options", "parser", "0", TCL_GLOBAL_ONLY);
3204#else
3205 Tcl_SetVar2(interp, "sqlite_options", "parser", "1", TCL_GLOBAL_ONLY);
3206#endif
3207
drhbf216272005-02-26 18:10:44 +00003208#if defined(SQLITE_OMIT_PRAGMA) || defined(SQLITE_OMIT_FLAG_PRAGMAS)
drh13d70422004-11-13 15:59:14 +00003209 Tcl_SetVar2(interp, "sqlite_options", "pragma", "0", TCL_GLOBAL_ONLY);
3210 Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
3211#else
3212 Tcl_SetVar2(interp, "sqlite_options", "pragma", "1", TCL_GLOBAL_ONLY);
3213#endif
3214
3215#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
3216 Tcl_SetVar2(interp, "sqlite_options", "progress", "0", TCL_GLOBAL_ONLY);
3217#else
3218 Tcl_SetVar2(interp, "sqlite_options", "progress", "1", TCL_GLOBAL_ONLY);
3219#endif
3220
drh3f459022006-01-07 16:06:07 +00003221#ifdef SQLITE_ENABLE_REDEF_IO
3222 Tcl_SetVar2(interp, "sqlite_options", "redefio", "1", TCL_GLOBAL_ONLY);
3223#else
3224 Tcl_SetVar2(interp, "sqlite_options", "redefio", "0", TCL_GLOBAL_ONLY);
3225#endif
3226
drh13d70422004-11-13 15:59:14 +00003227#ifdef SQLITE_OMIT_REINDEX
3228 Tcl_SetVar2(interp, "sqlite_options", "reindex", "0", TCL_GLOBAL_ONLY);
3229#else
3230 Tcl_SetVar2(interp, "sqlite_options", "reindex", "1", TCL_GLOBAL_ONLY);
3231#endif
3232
3233#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
3234 Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "0", TCL_GLOBAL_ONLY);
3235#else
3236 Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "1", TCL_GLOBAL_ONLY);
3237#endif
3238
3239#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
3240 Tcl_SetVar2(interp, "sqlite_options", "schema_version", "0", TCL_GLOBAL_ONLY);
3241#else
3242 Tcl_SetVar2(interp, "sqlite_options", "schema_version", "1", TCL_GLOBAL_ONLY);
3243#endif
3244
danielk1977aef0bf62005-12-30 16:28:01 +00003245#ifdef SQLITE_OMIT_SHARED_CACHE
3246 Tcl_SetVar2(interp, "sqlite_options", "shared_cache", "0", TCL_GLOBAL_ONLY);
3247#else
3248 Tcl_SetVar2(interp, "sqlite_options", "shared_cache", "1", TCL_GLOBAL_ONLY);
3249#endif
3250
danielk19773e8c37e2005-01-21 03:12:14 +00003251#ifdef SQLITE_OMIT_SUBQUERY
3252 Tcl_SetVar2(interp, "sqlite_options", "subquery", "0", TCL_GLOBAL_ONLY);
3253#else
3254 Tcl_SetVar2(interp, "sqlite_options", "subquery", "1", TCL_GLOBAL_ONLY);
3255#endif
3256
drh13d70422004-11-13 15:59:14 +00003257#ifdef SQLITE_OMIT_TCL_VARIABLE
3258 Tcl_SetVar2(interp, "sqlite_options", "tclvar", "0", TCL_GLOBAL_ONLY);
3259#else
3260 Tcl_SetVar2(interp, "sqlite_options", "tclvar", "1", TCL_GLOBAL_ONLY);
3261#endif
3262
3263#if defined(THREADSAFE) && THREADSAFE
3264 Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "1", TCL_GLOBAL_ONLY);
3265#else
3266 Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "0", TCL_GLOBAL_ONLY);
3267#endif
3268
drh19e2d372005-08-29 23:00:03 +00003269#ifdef SQLITE_OMIT_TRACE
3270 Tcl_SetVar2(interp, "sqlite_options", "trace", "0", TCL_GLOBAL_ONLY);
3271#else
3272 Tcl_SetVar2(interp, "sqlite_options", "trace", "1", TCL_GLOBAL_ONLY);
3273#endif
3274
drh13d70422004-11-13 15:59:14 +00003275#ifdef SQLITE_OMIT_TRIGGER
3276 Tcl_SetVar2(interp, "sqlite_options", "trigger", "0", TCL_GLOBAL_ONLY);
3277#else
3278 Tcl_SetVar2(interp, "sqlite_options", "trigger", "1", TCL_GLOBAL_ONLY);
3279#endif
3280
danielk197753c0f742005-03-29 03:10:59 +00003281#ifdef SQLITE_OMIT_TEMPDB
3282 Tcl_SetVar2(interp, "sqlite_options", "tempdb", "0", TCL_GLOBAL_ONLY);
3283#else
3284 Tcl_SetVar2(interp, "sqlite_options", "tempdb", "1", TCL_GLOBAL_ONLY);
3285#endif
3286
drh13d70422004-11-13 15:59:14 +00003287#ifdef SQLITE_OMIT_UTF16
3288 Tcl_SetVar2(interp, "sqlite_options", "utf16", "0", TCL_GLOBAL_ONLY);
3289#else
3290 Tcl_SetVar2(interp, "sqlite_options", "utf16", "1", TCL_GLOBAL_ONLY);
3291#endif
3292
3293#ifdef SQLITE_OMIT_VACUUM
3294 Tcl_SetVar2(interp, "sqlite_options", "vacuum", "0", TCL_GLOBAL_ONLY);
3295#else
3296 Tcl_SetVar2(interp, "sqlite_options", "vacuum", "1", TCL_GLOBAL_ONLY);
3297#endif
3298
3299#ifdef SQLITE_OMIT_VIEW
3300 Tcl_SetVar2(interp, "sqlite_options", "view", "0", TCL_GLOBAL_ONLY);
3301#else
3302 Tcl_SetVar2(interp, "sqlite_options", "view", "1", TCL_GLOBAL_ONLY);
3303#endif
drh27d258a2004-10-30 20:23:09 +00003304}
3305
3306/*
drhd1bf3512001-04-07 15:24:33 +00003307** Register commands with the TCL interpreter.
3308*/
3309int Sqlitetest1_Init(Tcl_Interp *interp){
danielk19776f8a5032004-05-10 10:34:51 +00003310 extern int sqlite3_search_count;
3311 extern int sqlite3_interrupt_count;
3312 extern int sqlite3_open_file_count;
drh6bf89572004-11-03 16:27:01 +00003313 extern int sqlite3_sort_count;
danielk19776f8a5032004-05-10 10:34:51 +00003314 extern int sqlite3_current_time;
drhc2eef3b2002-08-31 18:53:06 +00003315 static struct {
3316 char *zName;
3317 Tcl_CmdProc *xProc;
3318 } aCmd[] = {
drhd3d39e92004-05-20 22:16:29 +00003319 { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int },
drhe9707672004-06-25 01:10:48 +00003320 { "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 },
drhd3d39e92004-05-20 22:16:29 +00003321 { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str },
drhe29b1a02004-07-17 21:56:09 +00003322 { "sqlite3_mprintf_stronly", (Tcl_CmdProc*)sqlite3_mprintf_stronly},
drhd3d39e92004-05-20 22:16:29 +00003323 { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double },
3324 { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled },
drh63782852005-08-30 19:30:59 +00003325 { "sqlite3_mprintf_hexdouble", (Tcl_CmdProc*)sqlite3_mprintf_hexdouble},
drhd3d39e92004-05-20 22:16:29 +00003326 { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z },
drhd3d39e92004-05-20 22:16:29 +00003327 { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid },
3328 { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf },
3329 { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf },
3330 { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close },
3331 { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function },
3332 { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate },
3333 { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func },
3334 { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort },
danielk19772c336542005-01-13 02:14:23 +00003335#ifdef SQLITE_MEMDEBUG
drhd3d39e92004-05-20 22:16:29 +00003336 { "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail },
3337 { "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat },
drhc2eef3b2002-08-31 18:53:06 +00003338#endif
drh25d65432004-07-22 15:02:25 +00003339 { "sqlite_bind", (Tcl_CmdProc*)test_bind },
3340 { "breakpoint", (Tcl_CmdProc*)test_breakpoint },
3341 { "sqlite3_key", (Tcl_CmdProc*)test_key },
3342 { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey },
drhcacb2082005-01-11 15:28:33 +00003343 { "sqlite_set_magic", (Tcl_CmdProc*)sqlite_set_magic },
drhc5cdca62005-01-11 16:54:14 +00003344 { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt },
danielk1977600dd0b2005-01-20 01:14:23 +00003345#if 0
3346 { "sqlite3_sleep", (Tcl_CmdProc*)test_sleep },
3347#endif
drh3e1d8e62005-05-26 16:23:34 +00003348 { "sqlite_delete_function", (Tcl_CmdProc*)delete_function },
3349 { "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation },
3350 { "sqlite3_get_autocommit", (Tcl_CmdProc*)get_autocommit },
drh79158e12005-09-06 21:40:45 +00003351 { "sqlite3_stack_used", (Tcl_CmdProc*)test_stack_used },
drhc2eef3b2002-08-31 18:53:06 +00003352 };
danielk197751e3d8e2004-05-20 01:12:34 +00003353 static struct {
3354 char *zName;
3355 Tcl_ObjCmdProc *xProc;
danielk197704f2e682004-05-27 01:04:07 +00003356 void *clientData;
danielk197751e3d8e2004-05-20 01:12:34 +00003357 } aObjCmd[] = {
drhdddca282006-01-03 00:33:50 +00003358 { "sqlite3_connection_pointer", get_sqlite_pointer, 0 },
drh241db312004-06-22 12:46:53 +00003359 { "sqlite3_bind_int", test_bind_int, 0 },
3360 { "sqlite3_bind_int64", test_bind_int64, 0 },
3361 { "sqlite3_bind_double", test_bind_double, 0 },
danielk197704f2e682004-05-27 01:04:07 +00003362 { "sqlite3_bind_null", test_bind_null ,0 },
3363 { "sqlite3_bind_text", test_bind_text ,0 },
3364 { "sqlite3_bind_text16", test_bind_text16 ,0 },
3365 { "sqlite3_bind_blob", test_bind_blob ,0 },
drh75f6a032004-07-15 14:15:00 +00003366 { "sqlite3_bind_parameter_count", test_bind_parameter_count, 0},
drh895d7472004-08-20 16:02:39 +00003367 { "sqlite3_bind_parameter_name", test_bind_parameter_name, 0},
drhfa6bc002004-09-07 16:19:52 +00003368 { "sqlite3_bind_parameter_index", test_bind_parameter_index, 0},
danielk1977600dd0b2005-01-20 01:14:23 +00003369#if 0
3370 { "sqlite3_clear_bindings", test_clear_bindings, 0},
3371#endif
danielk197704f2e682004-05-27 01:04:07 +00003372 { "sqlite3_errcode", test_errcode ,0 },
3373 { "sqlite3_errmsg", test_errmsg ,0 },
3374 { "sqlite3_errmsg16", test_errmsg16 ,0 },
3375 { "sqlite3_open", test_open ,0 },
3376 { "sqlite3_open16", test_open16 ,0 },
danielk1977bc6ada42004-06-30 08:20:16 +00003377 { "sqlite3_complete16", test_complete16 ,0 },
danielk197704f2e682004-05-27 01:04:07 +00003378
3379 { "sqlite3_prepare", test_prepare ,0 },
3380 { "sqlite3_prepare16", test_prepare16 ,0 },
3381 { "sqlite3_finalize", test_finalize ,0 },
3382 { "sqlite3_reset", test_reset ,0 },
drhd89bd002005-01-22 03:03:54 +00003383 { "sqlite3_expired", test_expired ,0 },
drhf8db1bc2005-04-22 02:38:37 +00003384 { "sqlite3_transfer_bindings", test_transfer_bind ,0 },
danielk1977fbcd5852004-06-15 02:44:18 +00003385 { "sqlite3_changes", test_changes ,0 },
3386 { "sqlite3_step", test_step ,0 },
danielk197704f2e682004-05-27 01:04:07 +00003387
drh6aafc292006-01-05 15:50:06 +00003388 { "sqlite3_release_memory", test_release_memory, 0},
3389 { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0},
3390
danielk197704f2e682004-05-27 01:04:07 +00003391 /* sqlite3_column_*() API */
3392 { "sqlite3_column_count", test_column_count ,0 },
3393 { "sqlite3_data_count", test_data_count ,0 },
3394 { "sqlite3_column_type", test_column_type ,0 },
danielk1977ea61b2c2004-05-27 01:49:51 +00003395 { "sqlite3_column_blob", test_column_blob ,0 },
danielk197704f2e682004-05-27 01:04:07 +00003396 { "sqlite3_column_double", test_column_double ,0 },
3397 { "sqlite3_column_int64", test_column_int64 ,0 },
drh241db312004-06-22 12:46:53 +00003398 { "sqlite3_column_text", test_stmt_utf8, sqlite3_column_text },
3399 { "sqlite3_column_decltype", test_stmt_utf8, sqlite3_column_decltype },
3400 { "sqlite3_column_name", test_stmt_utf8, sqlite3_column_name },
drh6c626082004-11-14 21:56:29 +00003401 { "sqlite3_column_int", test_stmt_int, sqlite3_column_int },
3402 { "sqlite3_column_bytes", test_stmt_int, sqlite3_column_bytes },
3403#ifndef SQLITE_OMIT_UTF16
3404 { "sqlite3_column_bytes16", test_stmt_int, sqlite3_column_bytes16 },
drh241db312004-06-22 12:46:53 +00003405 { "sqlite3_column_text16", test_stmt_utf16, sqlite3_column_text16 },
3406 { "sqlite3_column_decltype16", test_stmt_utf16, sqlite3_column_decltype16},
3407 { "sqlite3_column_name16", test_stmt_utf16, sqlite3_column_name16 },
drh6c626082004-11-14 21:56:29 +00003408#endif
danielk19776b456a22005-03-21 04:04:02 +00003409 { "sqlite3_global_recover", test_global_recover, 0 },
danielk197704f2e682004-05-27 01:04:07 +00003410
danielk19779a1d0ab2004-06-01 14:09:28 +00003411 /* Functions from os.h */
danielk197744ee5bf2005-05-27 09:41:12 +00003412#ifndef SQLITE_OMIT_DISKIO
danielk19779a1d0ab2004-06-01 14:09:28 +00003413 { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 },
3414 { "sqlite3OsClose", test_sqlite3OsClose, 0 },
3415 { "sqlite3OsLock", test_sqlite3OsLock, 0 },
drhab3f9fe2004-08-14 17:10:10 +00003416 { "sqlite3OsTempFileName", test_sqlite3OsTempFileName, 0 },
danielk1977312d6b32004-06-29 13:18:23 +00003417
3418 /* Custom test interfaces */
3419 { "sqlite3OsUnlock", test_sqlite3OsUnlock, 0 },
danielk197744ee5bf2005-05-27 09:41:12 +00003420#endif
drh5436dc22004-11-14 04:04:17 +00003421#ifndef SQLITE_OMIT_UTF16
danielk1977312d6b32004-06-29 13:18:23 +00003422 { "add_test_collate", test_collate, 0 },
3423 { "add_test_collate_needed", test_collate_needed, 0 },
3424 { "add_test_function", test_function, 0 },
drh5436dc22004-11-14 04:04:17 +00003425#endif
danielk19775591df52005-12-20 09:19:37 +00003426#ifdef SQLITE_MEMDEBUG
3427 { "sqlite_malloc_outstanding", sqlite_malloc_outstanding, 0},
3428#endif
danielk1977312d6b32004-06-29 13:18:23 +00003429 { "sqlite3_test_errstr", test_errstr, 0 },
drh92febd92004-08-20 18:34:20 +00003430 { "tcl_variable_type", tcl_variable_type, 0 },
danielk1977aef0bf62005-12-30 16:28:01 +00003431#ifndef SQLITE_OMIT_SHARED_CACHE
danielk197752622822006-01-09 09:59:49 +00003432 { "sqlite3_enable_shared_cache", test_enable, sqlite3_enable_shared_cache},
3433#endif
3434#ifndef SQLITE_OMIT_MEMORY_MANAGEMENT
3435 { "sqlite3_enable_memory_management", test_enable,
3436 sqlite3_enable_memory_management},
danielk1977aef0bf62005-12-30 16:28:01 +00003437#endif
danielk197751e3d8e2004-05-20 01:12:34 +00003438 };
drh1398ad32005-01-19 23:24:50 +00003439 static int bitmask_size = sizeof(Bitmask)*8;
drhc2eef3b2002-08-31 18:53:06 +00003440 int i;
drh2ac3ee92004-06-07 16:27:46 +00003441 extern int sqlite3_os_trace;
drh51147ba2005-07-23 22:59:55 +00003442 extern int sqlite3_where_trace;
drhb851b2c2005-03-10 14:11:12 +00003443 extern int sqlite3_sync_count, sqlite3_fullsync_count;
drhaf6df112005-06-07 02:12:30 +00003444 extern int sqlite3_opentemp_count;
drh01397202005-07-20 14:31:53 +00003445 extern int sqlite3_memUsed;
danielk19772e588c72005-12-09 14:25:08 +00003446 extern int sqlite3_malloc_id;
drh01397202005-07-20 14:31:53 +00003447 extern int sqlite3_memMax;
drh55ef4d92005-08-14 01:20:37 +00003448 extern int sqlite3_like_count;
drhc0929982005-09-05 19:08:29 +00003449#if OS_WIN
3450 extern int sqlite3_os_type;
3451#endif
drh8b3d9902005-08-19 00:14:42 +00003452#ifdef SQLITE_DEBUG
3453 extern int sqlite3_vdbe_addop_trace;
drh549c8b62005-09-19 13:15:23 +00003454#endif
3455#ifdef SQLITE_TEST
3456 extern char sqlite3_query_plan[];
drh9042f392005-07-15 23:24:23 +00003457 static char *query_plan = sqlite3_query_plan;
drh48083ce2005-09-19 12:37:27 +00003458#endif
drhc2eef3b2002-08-31 18:53:06 +00003459
3460 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
3461 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
3462 }
danielk197751e3d8e2004-05-20 01:12:34 +00003463 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
danielk1977c572ef72004-05-27 09:28:41 +00003464 Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
3465 aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
danielk197751e3d8e2004-05-20 01:12:34 +00003466 }
danielk19776490beb2004-05-11 06:17:21 +00003467 Tcl_LinkVar(interp, "sqlite_search_count",
danielk19776f8a5032004-05-10 10:34:51 +00003468 (char*)&sqlite3_search_count, TCL_LINK_INT);
drh6bf89572004-11-03 16:27:01 +00003469 Tcl_LinkVar(interp, "sqlite_sort_count",
3470 (char*)&sqlite3_sort_count, TCL_LINK_INT);
drh55ef4d92005-08-14 01:20:37 +00003471 Tcl_LinkVar(interp, "sqlite_like_count",
3472 (char*)&sqlite3_like_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00003473 Tcl_LinkVar(interp, "sqlite_interrupt_count",
danielk19776f8a5032004-05-10 10:34:51 +00003474 (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00003475 Tcl_LinkVar(interp, "sqlite_open_file_count",
danielk19776f8a5032004-05-10 10:34:51 +00003476 (char*)&sqlite3_open_file_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00003477 Tcl_LinkVar(interp, "sqlite_current_time",
danielk19776f8a5032004-05-10 10:34:51 +00003478 (char*)&sqlite3_current_time, TCL_LINK_INT);
drh2ac3ee92004-06-07 16:27:46 +00003479 Tcl_LinkVar(interp, "sqlite_os_trace",
3480 (char*)&sqlite3_os_trace, TCL_LINK_INT);
drh268803a2005-12-14 20:11:30 +00003481#ifndef SQLITE_OMIT_UTF16
3482 Tcl_LinkVar(interp, "sqlite_last_needed_collation",
3483 (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
3484#endif
danielk197797cb2e92005-12-09 14:39:04 +00003485#ifdef SQLITE_MEMDEBUG
danielk19772e588c72005-12-09 14:25:08 +00003486 Tcl_LinkVar(interp, "sqlite_malloc_id",
3487 (char*)&sqlite3_malloc_id, TCL_LINK_STRING);
danielk197797cb2e92005-12-09 14:39:04 +00003488#endif
drhc0929982005-09-05 19:08:29 +00003489#if OS_WIN
3490 Tcl_LinkVar(interp, "sqlite_os_type",
3491 (char*)&sqlite3_os_type, TCL_LINK_INT);
3492#endif
drh549c8b62005-09-19 13:15:23 +00003493#ifdef SQLITE_TEST
3494 Tcl_LinkVar(interp, "sqlite_query_plan",
3495 (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
3496#endif
drh8b3d9902005-08-19 00:14:42 +00003497#ifdef SQLITE_DEBUG
3498 Tcl_LinkVar(interp, "sqlite_addop_trace",
3499 (char*)&sqlite3_vdbe_addop_trace, TCL_LINK_INT);
drh48083ce2005-09-19 12:37:27 +00003500 Tcl_LinkVar(interp, "sqlite_where_trace",
3501 (char*)&sqlite3_where_trace, TCL_LINK_INT);
drh8b3d9902005-08-19 00:14:42 +00003502#endif
drh70180302005-08-02 21:42:16 +00003503#ifdef SQLITE_MEMDEBUG
drh01397202005-07-20 14:31:53 +00003504 Tcl_LinkVar(interp, "sqlite_memused",
3505 (char*)&sqlite3_memUsed, TCL_LINK_INT | TCL_LINK_READ_ONLY);
3506 Tcl_LinkVar(interp, "sqlite_memmax",
3507 (char*)&sqlite3_memMax, TCL_LINK_INT | TCL_LINK_READ_ONLY);
drh70180302005-08-02 21:42:16 +00003508#endif
danielk1977cbe21be2005-06-07 07:58:48 +00003509#ifndef SQLITE_OMIT_DISKIO
drhaf6df112005-06-07 02:12:30 +00003510 Tcl_LinkVar(interp, "sqlite_opentemp_count",
3511 (char*)&sqlite3_opentemp_count, TCL_LINK_INT);
danielk1977cbe21be2005-06-07 07:58:48 +00003512#endif
drh7c972de2003-09-06 22:18:07 +00003513 Tcl_LinkVar(interp, "sqlite_static_bind_value",
3514 (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
drhab3f9fe2004-08-14 17:10:10 +00003515 Tcl_LinkVar(interp, "sqlite_temp_directory",
drheffd02b2004-08-29 23:42:13 +00003516 (char*)&sqlite3_temp_directory, TCL_LINK_STRING);
drh1398ad32005-01-19 23:24:50 +00003517 Tcl_LinkVar(interp, "bitmask_size",
3518 (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
drh748f7632005-03-11 04:41:39 +00003519#if OS_UNIX
drhb851b2c2005-03-10 14:11:12 +00003520 Tcl_LinkVar(interp, "sqlite_sync_count",
3521 (char*)&sqlite3_sync_count, TCL_LINK_INT);
3522 Tcl_LinkVar(interp, "sqlite_fullsync_count",
3523 (char*)&sqlite3_fullsync_count, TCL_LINK_INT);
drh748f7632005-03-11 04:41:39 +00003524#endif /* OS_UNIX */
drh27d258a2004-10-30 20:23:09 +00003525 set_options(interp);
danielk1977b82e7ed2006-01-11 14:09:31 +00003526
3527 int sqlite3_shared_cache_report(void *, Tcl_Interp *, int, Tcl_Obj *CONST[]);
3528 Tcl_CreateObjCommand(interp, "sqlite_shared_cache_report",
3529 sqlite3_shared_cache_report, 0, 0);
drhd1bf3512001-04-07 15:24:33 +00003530 return TCL_OK;
3531}