blob: efbb182e88f62ea17428426b36046e075dfbb366 [file] [log] [blame]
drhd1bf3512001-04-07 15:24:33 +00001/*
drhb19a2bc2001-09-16 00:13:26 +00002** 2001 September 15
drhd1bf3512001-04-07 15:24:33 +00003**
drhb19a2bc2001-09-16 00:13:26 +00004** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
drhd1bf3512001-04-07 15:24:33 +00006**
drhb19a2bc2001-09-16 00:13:26 +00007** May you do good and not evil.
8** May you find forgiveness for yourself and forgive others.
9** May you share freely, never taking more than you give.
drhd1bf3512001-04-07 15:24:33 +000010**
11*************************************************************************
drh05a82982006-03-19 13:00:25 +000012** Code for testing all sorts of SQLite interfaces. This code
drhd1bf3512001-04-07 15:24:33 +000013** is not included in the SQLite library. It is used for automated
14** testing of the SQLite library.
15**
drhc2e87a32006-06-27 15:16:14 +000016** $Id: test1.c,v 1.215 2006/06/27 15:16:16 drh Exp $
drhd1bf3512001-04-07 15:24:33 +000017*/
18#include "sqliteInt.h"
19#include "tcl.h"
drh94e92032003-02-16 22:21:32 +000020#include "os.h"
drhd1bf3512001-04-07 15:24:33 +000021#include <stdlib.h>
22#include <string.h>
23
drhdddca282006-01-03 00:33:50 +000024/*
25** This is a copy of the first part of the SqliteDb structure in
26** tclsqlite.c. We need it here so that the get_sqlite_pointer routine
27** can extract the sqlite3* pointer from an existing Tcl SQLite
28** connection.
29*/
30struct SqliteDb {
31 sqlite3 *db;
32};
33
34/*
35** A TCL command that returns the address of the sqlite* pointer
36** for an sqlite connection instance. Bad things happen if the
37** input is not an sqlite connection.
38*/
39static int get_sqlite_pointer(
40 void * clientData,
41 Tcl_Interp *interp,
42 int objc,
43 Tcl_Obj *CONST objv[]
44){
45 struct SqliteDb *p;
46 Tcl_CmdInfo cmdInfo;
47 char zBuf[100];
48 if( objc!=2 ){
49 Tcl_WrongNumArgs(interp, 1, objv, "SQLITE-CONNECTION");
50 return TCL_ERROR;
51 }
52 if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
53 Tcl_AppendResult(interp, "command not found: ",
54 Tcl_GetString(objv[1]), (char*)0);
55 return TCL_ERROR;
56 }
57 p = (struct SqliteDb*)cmdInfo.objClientData;
58 sprintf(zBuf, "%p", p->db);
59 if( strncmp(zBuf,"0x",2) ){
60 sprintf(zBuf, "0x%p", p->db);
61 }
62 Tcl_AppendResult(interp, zBuf, 0);
63 return TCL_OK;
64}
65
drh2e66f0b2005-04-28 17:18:48 +000066const char *sqlite3TestErrorName(int rc){
danielk19776622cce2004-05-20 11:00:52 +000067 const char *zName = 0;
68 switch( rc ){
69 case SQLITE_OK: zName = "SQLITE_OK"; break;
70 case SQLITE_ERROR: zName = "SQLITE_ERROR"; break;
danielk19776622cce2004-05-20 11:00:52 +000071 case SQLITE_PERM: zName = "SQLITE_PERM"; break;
72 case SQLITE_ABORT: zName = "SQLITE_ABORT"; break;
73 case SQLITE_BUSY: zName = "SQLITE_BUSY"; break;
74 case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break;
75 case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break;
76 case SQLITE_READONLY: zName = "SQLITE_READONLY"; break;
77 case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break;
78 case SQLITE_IOERR: zName = "SQLITE_IOERR"; break;
79 case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break;
danielk19776622cce2004-05-20 11:00:52 +000080 case SQLITE_FULL: zName = "SQLITE_FULL"; break;
81 case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break;
82 case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
83 case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break;
84 case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break;
danielk19776622cce2004-05-20 11:00:52 +000085 case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break;
86 case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break;
87 case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break;
88 case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break;
89 case SQLITE_AUTH: zName = "SQLITE_AUTH"; break;
90 case SQLITE_FORMAT: zName = "SQLITE_FORMAT"; break;
91 case SQLITE_RANGE: zName = "SQLITE_RANGE"; break;
92 case SQLITE_ROW: zName = "SQLITE_ROW"; break;
93 case SQLITE_DONE: zName = "SQLITE_DONE"; break;
drhc60d0442004-09-30 13:43:13 +000094 case SQLITE_NOTADB: zName = "SQLITE_NOTADB"; break;
danielk19776622cce2004-05-20 11:00:52 +000095 default: zName = "SQLITE_Unknown"; break;
96 }
97 return zName;
98}
drh2e66f0b2005-04-28 17:18:48 +000099#define errorName sqlite3TestErrorName
danielk19776622cce2004-05-20 11:00:52 +0000100
drhd1bf3512001-04-07 15:24:33 +0000101/*
drhc60d0442004-09-30 13:43:13 +0000102** Convert an sqlite3_stmt* into an sqlite3*. This depends on the
103** fact that the sqlite3* is the first field in the Vdbe structure.
104*/
drh51942bc2005-06-12 22:01:42 +0000105#define StmtToDb(X) sqlite3_db_handle(X)
drhc60d0442004-09-30 13:43:13 +0000106
107/*
108** Check a return value to make sure it agrees with the results
109** from sqlite3_errcode.
110*/
111int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){
112 if( rc!=SQLITE_MISUSE && rc!=SQLITE_OK && sqlite3_errcode(db)!=rc ){
113 char zBuf[200];
114 int r2 = sqlite3_errcode(db);
115 sprintf(zBuf, "error code %s (%d) does not match sqlite3_errcode %s (%d)",
116 errorName(rc), rc, errorName(r2), r2);
117 Tcl_ResetResult(interp);
118 Tcl_AppendResult(interp, zBuf, 0);
119 return 1;
120 }
121 return 0;
122}
123
124/*
drh9bb575f2004-09-06 17:24:11 +0000125** Decode a pointer to an sqlite3 object.
drhb86ccfb2003-01-28 23:13:10 +0000126*/
drh9bb575f2004-09-06 17:24:11 +0000127static int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
drhfe63d1c2004-09-08 20:13:04 +0000128 *ppDb = (sqlite3*)sqlite3TextToPtr(zA);
drhb86ccfb2003-01-28 23:13:10 +0000129 return TCL_OK;
130}
131
132/*
danielk197751e3d8e2004-05-20 01:12:34 +0000133** Decode a pointer to an sqlite3_stmt object.
134*/
135static int getStmtPointer(
136 Tcl_Interp *interp,
137 const char *zArg,
138 sqlite3_stmt **ppStmt
139){
drhfe63d1c2004-09-08 20:13:04 +0000140 *ppStmt = (sqlite3_stmt*)sqlite3TextToPtr(zArg);
danielk197751e3d8e2004-05-20 01:12:34 +0000141 return TCL_OK;
142}
143
144/*
danielk19779a1d0ab2004-06-01 14:09:28 +0000145** Decode a pointer to an sqlite3_stmt object.
146*/
147static int getFilePointer(
148 Tcl_Interp *interp,
149 const char *zArg,
150 OsFile **ppFile
151){
drhfe63d1c2004-09-08 20:13:04 +0000152 *ppFile = (OsFile*)sqlite3TextToPtr(zArg);
danielk19779a1d0ab2004-06-01 14:09:28 +0000153 return TCL_OK;
154}
155
156/*
drh7d8085a2003-04-26 13:19:38 +0000157** Generate a text representation of a pointer that can be understood
158** by the getDbPointer and getVmPointer routines above.
159**
160** The problem is, on some machines (Solaris) if you do a printf with
161** "%p" you cannot turn around and do a scanf with the same "%p" and
162** get your pointer back. You have to prepend a "0x" before it will
163** work. Or at least that is what is reported to me (drh). But this
164** behavior varies from machine to machine. The solution used her is
165** to test the string right after it is generated to see if it can be
166** understood by scanf, and if not, try prepending an "0x" to see if
167** that helps. If nothing works, a fatal error is generated.
168*/
drh64b1bea2006-01-15 02:30:57 +0000169int sqlite3TestMakePointerStr(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);
danielk1977926aab22006-06-27 07:34:40 +0000225 if( zErr ) sqlite3_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**
drh05a82982006-03-19 13:00:25 +0000233** Test the %z format of sqliteMPrintf(). Use multiple mprintf() calls to
drhd93d8a82003-06-16 03:08:18 +0000234** 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/*
drh05a82982006-03-19 13:00:25 +0000255** Usage: sqlite3_mprintf_n_test STRING
256**
257** Test the %n format of sqliteMPrintf(). Return the length of the
258** input string.
259*/
260static int test_mprintf_n(
261 void *NotUsed,
262 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
263 int argc, /* Number of arguments */
264 char **argv /* Text of each argument */
265){
266 char *zStr;
267 int n = 0;
268 zStr = sqlite3MPrintf("%s%n", argv[1], &n);
269 sqliteFree(zStr);
270 Tcl_SetObjResult(interp, Tcl_NewIntObj(n));
271 return TCL_OK;
272}
273
274/*
danielk19776f8a5032004-05-10 10:34:51 +0000275** Usage: sqlite3_get_table_printf DB FORMAT STRING
drhd1bf3512001-04-07 15:24:33 +0000276**
danielk19776f8a5032004-05-10 10:34:51 +0000277** Invoke the sqlite3_get_table_printf() interface using the open database
drhd1bf3512001-04-07 15:24:33 +0000278** DB. The SQL is the string FORMAT. The format string should contain
279** one %s or %q. STRING is the value inserted into %s or %q.
280*/
281static int test_get_table_printf(
282 void *NotUsed,
283 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
284 int argc, /* Number of arguments */
285 char **argv /* Text of each argument */
286){
drh9bb575f2004-09-06 17:24:11 +0000287 sqlite3 *db;
drhd1bf3512001-04-07 15:24:33 +0000288 Tcl_DString str;
289 int rc;
290 char *zErr = 0;
291 int nRow, nCol;
292 char **aResult;
293 int i;
294 char zBuf[30];
drh1211de32004-07-26 12:24:22 +0000295 char *zSql;
drhd1bf3512001-04-07 15:24:33 +0000296 if( argc!=4 ){
297 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
298 " DB FORMAT STRING", 0);
299 return TCL_ERROR;
300 }
drhb86ccfb2003-01-28 23:13:10 +0000301 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000302 Tcl_DStringInit(&str);
drh1211de32004-07-26 12:24:22 +0000303 zSql = sqlite3_mprintf(argv[2],argv[3]);
304 rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr);
305 sqlite3_free(zSql);
drhd1bf3512001-04-07 15:24:33 +0000306 sprintf(zBuf, "%d", rc);
307 Tcl_AppendElement(interp, zBuf);
308 if( rc==SQLITE_OK ){
309 sprintf(zBuf, "%d", nRow);
310 Tcl_AppendElement(interp, zBuf);
311 sprintf(zBuf, "%d", nCol);
312 Tcl_AppendElement(interp, zBuf);
313 for(i=0; i<(nRow+1)*nCol; i++){
314 Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL");
315 }
316 }else{
317 Tcl_AppendElement(interp, zErr);
318 }
danielk19776f8a5032004-05-10 10:34:51 +0000319 sqlite3_free_table(aResult);
danielk1977926aab22006-06-27 07:34:40 +0000320 if( zErr ) sqlite3_free(zErr);
drhc60d0442004-09-30 13:43:13 +0000321 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000322 return TCL_OK;
323}
324
drhaf9ff332002-01-16 21:00:27 +0000325
326/*
danielk19776f8a5032004-05-10 10:34:51 +0000327** Usage: sqlite3_last_insert_rowid DB
drhaf9ff332002-01-16 21:00:27 +0000328**
329** Returns the integer ROWID of the most recent insert.
330*/
331static int test_last_rowid(
332 void *NotUsed,
333 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
334 int argc, /* Number of arguments */
335 char **argv /* Text of each argument */
336){
drh9bb575f2004-09-06 17:24:11 +0000337 sqlite3 *db;
drhaf9ff332002-01-16 21:00:27 +0000338 char zBuf[30];
339
340 if( argc!=2 ){
341 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0);
342 return TCL_ERROR;
343 }
drhb86ccfb2003-01-28 23:13:10 +0000344 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk1977c572ef72004-05-27 09:28:41 +0000345 sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db));
drhaf9ff332002-01-16 21:00:27 +0000346 Tcl_AppendResult(interp, zBuf, 0);
347 return SQLITE_OK;
348}
349
drhd1bf3512001-04-07 15:24:33 +0000350/*
drh25d65432004-07-22 15:02:25 +0000351** Usage: sqlite3_key DB KEY
352**
353** Set the codec key.
354*/
355static int test_key(
356 void *NotUsed,
357 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
358 int argc, /* Number of arguments */
359 char **argv /* Text of each argument */
360){
drh9bb575f2004-09-06 17:24:11 +0000361 sqlite3 *db;
drh25d65432004-07-22 15:02:25 +0000362 const char *zKey;
363 int nKey;
364 if( argc!=3 ){
365 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
366 " FILENAME\"", 0);
367 return TCL_ERROR;
368 }
369 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
370 zKey = argv[2];
371 nKey = strlen(zKey);
372#ifdef SQLITE_HAS_CODEC
373 sqlite3_key(db, zKey, nKey);
374#endif
375 return TCL_OK;
376}
377
378/*
379** Usage: sqlite3_rekey DB KEY
380**
381** Change the codec key.
382*/
383static int test_rekey(
384 void *NotUsed,
385 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
386 int argc, /* Number of arguments */
387 char **argv /* Text of each argument */
388){
drh9bb575f2004-09-06 17:24:11 +0000389 sqlite3 *db;
drh25d65432004-07-22 15:02:25 +0000390 const char *zKey;
391 int nKey;
392 if( argc!=3 ){
393 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
394 " FILENAME\"", 0);
395 return TCL_ERROR;
396 }
397 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
398 zKey = argv[2];
399 nKey = strlen(zKey);
400#ifdef SQLITE_HAS_CODEC
401 sqlite3_rekey(db, zKey, nKey);
402#endif
403 return TCL_OK;
404}
405
406/*
danielk19776f8a5032004-05-10 10:34:51 +0000407** Usage: sqlite3_close DB
drhd1bf3512001-04-07 15:24:33 +0000408**
danielk19776f8a5032004-05-10 10:34:51 +0000409** Closes the database opened by sqlite3_open.
drhd1bf3512001-04-07 15:24:33 +0000410*/
411static int sqlite_test_close(
412 void *NotUsed,
413 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
414 int argc, /* Number of arguments */
415 char **argv /* Text of each argument */
416){
drh9bb575f2004-09-06 17:24:11 +0000417 sqlite3 *db;
danielk197796d81f92004-06-19 03:33:57 +0000418 int rc;
drhd1bf3512001-04-07 15:24:33 +0000419 if( argc!=2 ){
420 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
421 " FILENAME\"", 0);
422 return TCL_ERROR;
423 }
drhb86ccfb2003-01-28 23:13:10 +0000424 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk197796d81f92004-06-19 03:33:57 +0000425 rc = sqlite3_close(db);
danielk1977f9d64d22004-06-19 08:18:07 +0000426 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
drhd1bf3512001-04-07 15:24:33 +0000427 return TCL_OK;
428}
429
430/*
drhc22bd472002-05-10 13:14:07 +0000431** Implementation of the x_coalesce() function.
432** Return the first argument non-NULL argument.
433*/
danielk19770ae8b832004-05-25 12:05:56 +0000434static void ifnullFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
drhc22bd472002-05-10 13:14:07 +0000435 int i;
436 for(i=0; i<argc; i++){
drh9c054832004-05-31 18:51:57 +0000437 if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
drh03d847e2005-12-09 20:21:58 +0000438 sqlite3_result_text(context, (char*)sqlite3_value_text(argv[i]),
drh5c434b72005-12-05 13:20:01 +0000439 sqlite3_value_bytes(argv[i]), SQLITE_TRANSIENT);
drhc22bd472002-05-10 13:14:07 +0000440 break;
441 }
442 }
443}
444
445/*
drhd1d9fc32004-01-07 19:24:48 +0000446** A structure into which to accumulate text.
447*/
448struct dstr {
449 int nAlloc; /* Space allocated */
450 int nUsed; /* Space used */
451 char *z; /* The space */
452};
453
454/*
455** Append text to a dstr
456*/
457static void dstrAppend(struct dstr *p, const char *z, int divider){
458 int n = strlen(z);
459 if( p->nUsed + n + 2 > p->nAlloc ){
460 char *zNew;
461 p->nAlloc = p->nAlloc*2 + n + 200;
462 zNew = sqliteRealloc(p->z, p->nAlloc);
463 if( zNew==0 ){
464 sqliteFree(p->z);
465 memset(p, 0, sizeof(*p));
466 return;
467 }
468 p->z = zNew;
469 }
470 if( divider && p->nUsed>0 ){
471 p->z[p->nUsed++] = divider;
472 }
473 memcpy(&p->z[p->nUsed], z, n+1);
474 p->nUsed += n;
475}
476
477/*
danielk19774adee202004-05-08 08:23:19 +0000478** Invoked for each callback from sqlite3ExecFunc
drhd1d9fc32004-01-07 19:24:48 +0000479*/
480static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){
481 struct dstr *p = (struct dstr*)pData;
482 int i;
483 for(i=0; i<argc; i++){
484 if( argv[i]==0 ){
485 dstrAppend(p, "NULL", ' ');
486 }else{
487 dstrAppend(p, argv[i], ' ');
488 }
489 }
490 return 0;
491}
492
493/*
danielk1977e35ee192004-06-26 09:50:11 +0000494** Implementation of the x_sqlite_exec() function. This function takes
drhc22bd472002-05-10 13:14:07 +0000495** a single argument and attempts to execute that argument as SQL code.
drh6cbe1f12002-07-01 00:31:36 +0000496** This is illegal and should set the SQLITE_MISUSE flag on the database.
drhd1d9fc32004-01-07 19:24:48 +0000497**
danielk19776f8a5032004-05-10 10:34:51 +0000498** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec()
drhd1d9fc32004-01-07 19:24:48 +0000499** from within a function call.
drhc22bd472002-05-10 13:14:07 +0000500**
501** This routine simulates the effect of having two threads attempt to
502** use the same database at the same time.
503*/
danielk197751ad0ec2004-05-24 12:39:02 +0000504static void sqlite3ExecFunc(
danielk19770ae8b832004-05-25 12:05:56 +0000505 sqlite3_context *context,
danielk197751ad0ec2004-05-24 12:39:02 +0000506 int argc,
507 sqlite3_value **argv
508){
drhd1d9fc32004-01-07 19:24:48 +0000509 struct dstr x;
510 memset(&x, 0, sizeof(x));
drh37527852006-03-16 16:19:56 +0000511 (void)sqlite3_exec((sqlite3*)sqlite3_user_data(context),
drh03d847e2005-12-09 20:21:58 +0000512 (char*)sqlite3_value_text(argv[0]),
drhd1d9fc32004-01-07 19:24:48 +0000513 execFuncCallback, &x, 0);
danielk1977d8123362004-06-12 09:25:12 +0000514 sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT);
drhd1d9fc32004-01-07 19:24:48 +0000515 sqliteFree(x.z);
drhc22bd472002-05-10 13:14:07 +0000516}
517
518/*
519** Usage: sqlite_test_create_function DB
520**
danielk19776f8a5032004-05-10 10:34:51 +0000521** Call the sqlite3_create_function API on the given database in order
drhc22bd472002-05-10 13:14:07 +0000522** to create a function named "x_coalesce". This function does the same thing
523** as the "coalesce" function. This function also registers an SQL function
danielk1977e35ee192004-06-26 09:50:11 +0000524** named "x_sqlite_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec()
drhc22bd472002-05-10 13:14:07 +0000525** in this way is illegal recursion and should raise an SQLITE_MISUSE error.
526** The effect is similar to trying to use the same database connection from
527** two threads at the same time.
528**
529** The original motivation for this routine was to be able to call the
danielk19776f8a5032004-05-10 10:34:51 +0000530** sqlite3_create_function function while a query is in progress in order
drhc22bd472002-05-10 13:14:07 +0000531** to test the SQLITE_MISUSE detection logic.
532*/
drhc2eef3b2002-08-31 18:53:06 +0000533static int test_create_function(
drhc22bd472002-05-10 13:14:07 +0000534 void *NotUsed,
535 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
536 int argc, /* Number of arguments */
537 char **argv /* Text of each argument */
538){
drhc60d0442004-09-30 13:43:13 +0000539 int rc;
drh9bb575f2004-09-06 17:24:11 +0000540 sqlite3 *db;
drh9bb575f2004-09-06 17:24:11 +0000541 extern void Md5_Register(sqlite3*);
danielk1977312d6b32004-06-29 13:18:23 +0000542
drhc22bd472002-05-10 13:14:07 +0000543 if( argc!=2 ){
544 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
danielk19774397de52005-01-12 12:44:03 +0000545 " DB\"", 0);
drhc22bd472002-05-10 13:14:07 +0000546 return TCL_ERROR;
547 }
drhb86ccfb2003-01-28 23:13:10 +0000548 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +0000549 rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0,
550 ifnullFunc, 0, 0);
danielk1977312d6b32004-06-29 13:18:23 +0000551
drh5436dc22004-11-14 04:04:17 +0000552#ifndef SQLITE_OMIT_UTF16
danielk1977312d6b32004-06-29 13:18:23 +0000553 /* Use the sqlite3_create_function16() API here. Mainly for fun, but also
554 ** because it is not tested anywhere else. */
drhc60d0442004-09-30 13:43:13 +0000555 if( rc==SQLITE_OK ){
danielk1977576ec6b2005-01-21 11:55:25 +0000556 sqlite3_value *pVal;
danielk1977771151b2006-01-17 13:21:40 +0000557#ifdef SQLITE_MEMDEBUG
558 if( sqlite3_iMallocFail>0 ){
559 sqlite3_iMallocFail++;
560 }
561#endif
drhc60d0442004-09-30 13:43:13 +0000562 pVal = sqlite3ValueNew();
563 sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC);
564 rc = sqlite3_create_function16(db,
565 sqlite3ValueText(pVal, SQLITE_UTF16NATIVE),
566 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
567 sqlite3ValueFree(pVal);
568 }
drh5436dc22004-11-14 04:04:17 +0000569#endif
570
drhc60d0442004-09-30 13:43:13 +0000571 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk19774397de52005-01-12 12:44:03 +0000572 Tcl_SetResult(interp, (char *)errorName(rc), 0);
drhc22bd472002-05-10 13:14:07 +0000573 return TCL_OK;
574}
575
576/*
577** Routines to implement the x_count() aggregate function.
drh90669c12006-01-20 15:45:36 +0000578**
579** x_count() counts the number of non-null arguments. But there are
580** some twists for testing purposes.
581**
582** If the argument to x_count() is 40 then a UTF-8 error is reported
583** on the step function. If x_count(41) is seen, then a UTF-16 error
584** is reported on the step function. If the total count is 42, then
585** a UTF-8 error is reported on the finalize function.
drhc22bd472002-05-10 13:14:07 +0000586*/
587typedef struct CountCtx CountCtx;
588struct CountCtx {
589 int n;
590};
danielk19770ae8b832004-05-25 12:05:56 +0000591static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
drhc22bd472002-05-10 13:14:07 +0000592 CountCtx *p;
drh4f26d6c2004-05-26 23:25:30 +0000593 p = sqlite3_aggregate_context(context, sizeof(*p));
drh9c054832004-05-31 18:51:57 +0000594 if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){
drhc22bd472002-05-10 13:14:07 +0000595 p->n++;
596 }
drh90669c12006-01-20 15:45:36 +0000597 if( argc>0 ){
598 int v = sqlite3_value_int(argv[0]);
599 if( v==40 ){
600 sqlite3_result_error(context, "value of 40 handed to x_count", -1);
danielk1977a1686c92006-01-23 07:52:37 +0000601#ifndef SQLITE_OMIT_UTF16
drh90669c12006-01-20 15:45:36 +0000602 }else if( v==41 ){
603 const char zUtf16ErrMsg[] = { 0, 0x61, 0, 0x62, 0, 0x63, 0, 0, 0};
604 sqlite3_result_error16(context, &zUtf16ErrMsg[1-SQLITE_BIGENDIAN], -1);
danielk1977a1686c92006-01-23 07:52:37 +0000605#endif
drh90669c12006-01-20 15:45:36 +0000606 }
607 }
drhc22bd472002-05-10 13:14:07 +0000608}
danielk19770ae8b832004-05-25 12:05:56 +0000609static void countFinalize(sqlite3_context *context){
drhc22bd472002-05-10 13:14:07 +0000610 CountCtx *p;
drh4f26d6c2004-05-26 23:25:30 +0000611 p = sqlite3_aggregate_context(context, sizeof(*p));
drh90669c12006-01-20 15:45:36 +0000612 if( p ){
613 if( p->n==42 ){
614 sqlite3_result_error(context, "x_count totals to 42", -1);
615 }else{
616 sqlite3_result_int(context, p ? p->n : 0);
617 }
618 }
drhc22bd472002-05-10 13:14:07 +0000619}
620
621/*
622** Usage: sqlite_test_create_aggregate DB
623**
danielk19776f8a5032004-05-10 10:34:51 +0000624** Call the sqlite3_create_function API on the given database in order
drhc22bd472002-05-10 13:14:07 +0000625** to create a function named "x_count". This function does the same thing
626** as the "md5sum" function.
627**
628** The original motivation for this routine was to be able to call the
danielk19776f8a5032004-05-10 10:34:51 +0000629** sqlite3_create_aggregate function while a query is in progress in order
drh90669c12006-01-20 15:45:36 +0000630** to test the SQLITE_MISUSE detection logic. See misuse.test.
631**
632** This routine was later extended to test the use of sqlite3_result_error()
633** within aggregate functions.
drhc22bd472002-05-10 13:14:07 +0000634*/
drhc2eef3b2002-08-31 18:53:06 +0000635static int test_create_aggregate(
drhc22bd472002-05-10 13:14:07 +0000636 void *NotUsed,
637 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
638 int argc, /* Number of arguments */
639 char **argv /* Text of each argument */
640){
drh9bb575f2004-09-06 17:24:11 +0000641 sqlite3 *db;
drhc60d0442004-09-30 13:43:13 +0000642 int rc;
drhc22bd472002-05-10 13:14:07 +0000643 if( argc!=2 ){
644 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
645 " FILENAME\"", 0);
646 return TCL_ERROR;
647 }
drhb86ccfb2003-01-28 23:13:10 +0000648 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +0000649 rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0,
danielk1977d8123362004-06-12 09:25:12 +0000650 countStep,countFinalize);
drhc60d0442004-09-30 13:43:13 +0000651 if( rc==SQLITE_OK ){
652 sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0,
653 countStep,countFinalize);
654 }
655 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drhc22bd472002-05-10 13:14:07 +0000656 return TCL_OK;
657}
658
659
660
661/*
danielk19776f8a5032004-05-10 10:34:51 +0000662** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER
drhd1bf3512001-04-07 15:24:33 +0000663**
664** Call mprintf with three integer arguments
665*/
danielk19776f8a5032004-05-10 10:34:51 +0000666static int sqlite3_mprintf_int(
drhd1bf3512001-04-07 15:24:33 +0000667 void *NotUsed,
668 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
669 int argc, /* Number of arguments */
670 char **argv /* Text of each argument */
671){
672 int a[3], i;
673 char *z;
674 if( argc!=5 ){
675 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
676 " FORMAT INT INT INT\"", 0);
677 return TCL_ERROR;
678 }
679 for(i=2; i<5; i++){
680 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
681 }
danielk19776f8a5032004-05-10 10:34:51 +0000682 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
drhd1bf3512001-04-07 15:24:33 +0000683 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000684 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +0000685 return TCL_OK;
686}
687
688/*
drh9d213ef2004-06-30 04:02:11 +0000689** If zNum represents an integer that will fit in 64-bits, then set
690** *pValue to that integer and return true. Otherwise return false.
691*/
692static int sqlite3GetInt64(const char *zNum, i64 *pValue){
693 if( sqlite3FitsIn64Bits(zNum) ){
694 sqlite3atoi64(zNum, pValue);
695 return 1;
696 }
697 return 0;
698}
699
700/*
drhe9707672004-06-25 01:10:48 +0000701** Usage: sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER
702**
703** Call mprintf with three 64-bit integer arguments
704*/
705static int sqlite3_mprintf_int64(
706 void *NotUsed,
707 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
708 int argc, /* Number of arguments */
709 char **argv /* Text of each argument */
710){
711 int i;
712 sqlite_int64 a[3];
713 char *z;
714 if( argc!=5 ){
715 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
716 " FORMAT INT INT INT\"", 0);
717 return TCL_ERROR;
718 }
719 for(i=2; i<5; i++){
720 if( !sqlite3GetInt64(argv[i], &a[i-2]) ){
721 Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0);
722 return TCL_ERROR;
723 }
724 }
725 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
726 Tcl_AppendResult(interp, z, 0);
727 sqlite3_free(z);
728 return TCL_OK;
729}
730
731/*
danielk19776f8a5032004-05-10 10:34:51 +0000732** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING
drhd1bf3512001-04-07 15:24:33 +0000733**
734** Call mprintf with two integer arguments and one string argument
735*/
danielk19776f8a5032004-05-10 10:34:51 +0000736static int sqlite3_mprintf_str(
drhd1bf3512001-04-07 15:24:33 +0000737 void *NotUsed,
738 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
739 int argc, /* Number of arguments */
740 char **argv /* Text of each argument */
741){
742 int a[3], i;
743 char *z;
chwf220b242002-06-16 04:54:28 +0000744 if( argc<4 || argc>5 ){
drhd1bf3512001-04-07 15:24:33 +0000745 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
chwf220b242002-06-16 04:54:28 +0000746 " FORMAT INT INT ?STRING?\"", 0);
drhd1bf3512001-04-07 15:24:33 +0000747 return TCL_ERROR;
748 }
749 for(i=2; i<4; i++){
750 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
751 }
danielk19776f8a5032004-05-10 10:34:51 +0000752 z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL);
drhd1bf3512001-04-07 15:24:33 +0000753 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000754 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +0000755 return TCL_OK;
756}
757
758/*
drh63782852005-08-30 19:30:59 +0000759** Usage: sqlite3_mprintf_double FORMAT INTEGER INTEGER DOUBLE
drhd1bf3512001-04-07 15:24:33 +0000760**
761** Call mprintf with two integer arguments and one double argument
762*/
danielk19776f8a5032004-05-10 10:34:51 +0000763static int sqlite3_mprintf_double(
drhd1bf3512001-04-07 15:24:33 +0000764 void *NotUsed,
765 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
766 int argc, /* Number of arguments */
767 char **argv /* Text of each argument */
768){
769 int a[3], i;
770 double r;
771 char *z;
772 if( argc!=5 ){
773 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
drh63782852005-08-30 19:30:59 +0000774 " FORMAT INT INT DOUBLE\"", 0);
drhd1bf3512001-04-07 15:24:33 +0000775 return TCL_ERROR;
776 }
777 for(i=2; i<4; i++){
778 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
779 }
780 if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
danielk19776f8a5032004-05-10 10:34:51 +0000781 z = sqlite3_mprintf(argv[1], a[0], a[1], r);
drhd1bf3512001-04-07 15:24:33 +0000782 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000783 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +0000784 return TCL_OK;
785}
786
787/*
drh63782852005-08-30 19:30:59 +0000788** Usage: sqlite3_mprintf_scaled FORMAT DOUBLE DOUBLE
drhb621c232004-02-21 19:41:04 +0000789**
790** Call mprintf with a single double argument which is the product of the
791** two arguments given above. This is used to generate overflow and underflow
792** doubles to test that they are converted properly.
793*/
danielk19776f8a5032004-05-10 10:34:51 +0000794static int sqlite3_mprintf_scaled(
drhb621c232004-02-21 19:41:04 +0000795 void *NotUsed,
796 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
797 int argc, /* Number of arguments */
798 char **argv /* Text of each argument */
799){
800 int i;
801 double r[2];
802 char *z;
803 if( argc!=4 ){
804 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
805 " FORMAT DOUBLE DOUBLE\"", 0);
806 return TCL_ERROR;
807 }
808 for(i=2; i<4; i++){
809 if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR;
810 }
danielk19776f8a5032004-05-10 10:34:51 +0000811 z = sqlite3_mprintf(argv[1], r[0]*r[1]);
drhb621c232004-02-21 19:41:04 +0000812 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000813 sqlite3_free(z);
drhb621c232004-02-21 19:41:04 +0000814 return TCL_OK;
815}
816
817/*
drhe29b1a02004-07-17 21:56:09 +0000818** Usage: sqlite3_mprintf_stronly FORMAT STRING
819**
820** Call mprintf with a single double argument which is the product of the
821** two arguments given above. This is used to generate overflow and underflow
822** doubles to test that they are converted properly.
823*/
824static int sqlite3_mprintf_stronly(
825 void *NotUsed,
826 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
827 int argc, /* Number of arguments */
828 char **argv /* Text of each argument */
829){
830 char *z;
831 if( argc!=3 ){
832 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
833 " FORMAT STRING\"", 0);
834 return TCL_ERROR;
835 }
836 z = sqlite3_mprintf(argv[1], argv[2]);
837 Tcl_AppendResult(interp, z, 0);
838 sqlite3_free(z);
839 return TCL_OK;
840}
841
842/*
drh63782852005-08-30 19:30:59 +0000843** Usage: sqlite3_mprintf_hexdouble FORMAT HEX
844**
845** Call mprintf with a single double argument which is derived from the
846** hexadecimal encoding of an IEEE double.
847*/
848static int sqlite3_mprintf_hexdouble(
849 void *NotUsed,
850 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
851 int argc, /* Number of arguments */
852 char **argv /* Text of each argument */
853){
854 char *z;
855 double r;
856 unsigned x1, x2;
857 long long unsigned d;
858 if( argc!=3 ){
859 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
860 " FORMAT STRING\"", 0);
861 return TCL_ERROR;
862 }
863 if( sscanf(argv[2], "%08x%08x", &x2, &x1)!=2 ){
864 Tcl_AppendResult(interp, "2nd argument should be 16-characters of hex", 0);
865 return TCL_ERROR;
866 }
867 d = x2;
868 d = (d<<32) + x1;
869 memcpy(&r, &d, sizeof(r));
870 z = sqlite3_mprintf(argv[1], r);
871 Tcl_AppendResult(interp, z, 0);
872 sqlite3_free(z);
873 return TCL_OK;
874}
875
876/*
drh46934232004-11-20 19:18:00 +0000877** Usage: sqlite_malloc_fail N ?REPEAT-INTERVAL?
drhdaffd0e2001-04-11 14:28:42 +0000878**
drh46934232004-11-20 19:18:00 +0000879** Rig sqliteMalloc() to fail on the N-th call and every REPEAT-INTERVAL call
880** after that. If REPEAT-INTERVAL is 0 or is omitted, then only a single
881** malloc will fail. If REPEAT-INTERVAL is 1 then all mallocs after the
882** first failure will continue to fail on every call. If REPEAT-INTERVAL is
883** 2 then every other malloc will fail. And so forth.
884**
danielk19779e128002006-01-18 16:51:35 +0000885** Turn off this mechanism and reset the sqlite3ThreadData()->mallocFailed
886** variable if N==0.
drhdaffd0e2001-04-11 14:28:42 +0000887*/
danielk19772c336542005-01-13 02:14:23 +0000888#ifdef SQLITE_MEMDEBUG
drhdaffd0e2001-04-11 14:28:42 +0000889static int sqlite_malloc_fail(
890 void *NotUsed,
891 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
892 int argc, /* Number of arguments */
893 char **argv /* Text of each argument */
894){
895 int n;
drh46934232004-11-20 19:18:00 +0000896 int rep;
897 if( argc!=2 && argc!=3 ){
drhdaffd0e2001-04-11 14:28:42 +0000898 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0);
899 return TCL_ERROR;
900 }
901 if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
drh46934232004-11-20 19:18:00 +0000902 if( argc==3 ){
903 if( Tcl_GetInt(interp, argv[2], &rep) ) return TCL_ERROR;
904 }else{
905 rep = 0;
906 }
danielk19776f8a5032004-05-10 10:34:51 +0000907 sqlite3_iMallocFail = n;
drh46934232004-11-20 19:18:00 +0000908 sqlite3_iMallocReset = rep;
drhdaffd0e2001-04-11 14:28:42 +0000909 return TCL_OK;
910}
911#endif
912
913/*
914** Usage: sqlite_malloc_stat
915**
916** Return the number of prior calls to sqliteMalloc() and sqliteFree().
917*/
danielk19772c336542005-01-13 02:14:23 +0000918#ifdef SQLITE_MEMDEBUG
drhdaffd0e2001-04-11 14:28:42 +0000919static int sqlite_malloc_stat(
920 void *NotUsed,
921 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
922 int argc, /* Number of arguments */
923 char **argv /* Text of each argument */
924){
925 char zBuf[200];
danielk19775591df52005-12-20 09:19:37 +0000926 sprintf(zBuf, "%d %d %d", sqlite3_nMalloc,sqlite3_nFree,sqlite3_iMallocFail);
drhdaffd0e2001-04-11 14:28:42 +0000927 Tcl_AppendResult(interp, zBuf, 0);
928 return TCL_OK;
929}
danielk19775591df52005-12-20 09:19:37 +0000930
931/*
932** This function implements a Tcl command that may be invoked using any of
933** the four forms enumerated below.
934**
935** sqlite_malloc_outstanding
936** Return a summary of all unfreed blocks of memory allocated by the
937** current thread. See comments above function sqlite3OutstandingMallocs()
938** in util.c for a description of the returned value.
939**
940** sqlite_malloc_outstanding -bytes
941** Return the total amount of unfreed memory (in bytes) allocated by
942** this thread.
943**
944** sqlite_malloc_outstanding -maxbytes
945** Return the maximum amount of dynamic memory in use at one time
946** by this thread.
947**
948** sqlite_malloc_outstanding -clearmaxbytes
949** Set the value returned by [sqlite_malloc_outstanding -maxbytes]
950** to the current value of [sqlite_malloc_outstanding -bytes].
951*/
danielk19772e588c72005-12-09 14:25:08 +0000952static int sqlite_malloc_outstanding(
danielk19775591df52005-12-20 09:19:37 +0000953 ClientData clientData,
danielk19772e588c72005-12-09 14:25:08 +0000954 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
danielk19775591df52005-12-20 09:19:37 +0000955 int objc, /* Number of arguments */
956 Tcl_Obj *CONST objv[] /* Command arguments */
danielk19772e588c72005-12-09 14:25:08 +0000957){
958 extern int sqlite3OutstandingMallocs(Tcl_Interp *interp);
danielk19775591df52005-12-20 09:19:37 +0000959
drhdab97c12006-01-19 11:28:06 +0000960#if defined(SQLITE_DEBUG) && defined(SQLITE_MEMDEBUG) && SQLITE_MEMDEBUG>1
danielk19775591df52005-12-20 09:19:37 +0000961 if( objc==2 ){
962 const char *zArg = Tcl_GetString(objv[1]);
danielk1977191c3e72006-01-19 07:18:14 +0000963#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
964 ThreadData const *pTd = sqlite3ThreadDataReadOnly();
danielk19775591df52005-12-20 09:19:37 +0000965 if( 0==strcmp(zArg, "-bytes") ){
danielk197752622822006-01-09 09:59:49 +0000966 Tcl_SetObjResult(interp, Tcl_NewIntObj(pTd->nAlloc));
danielk19775591df52005-12-20 09:19:37 +0000967 }else if( 0==strcmp(zArg, "-clearmaxbytes") ){
danielk19779e128002006-01-18 16:51:35 +0000968 sqlite3_nMaxAlloc = pTd->nAlloc;
danielk1977191c3e72006-01-19 07:18:14 +0000969 }else
970#endif
971 if( 0==strcmp(zArg, "-maxbytes") ){
972 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(sqlite3_nMaxAlloc));
danielk19775591df52005-12-20 09:19:37 +0000973 }else{
974 Tcl_AppendResult(interp, "bad option \"", zArg,
975 "\": must be -bytes, -maxbytes or -clearmaxbytes", 0
976 );
977 return TCL_ERROR;
978 }
979
980 return TCL_OK;
981 }
danielk197752622822006-01-09 09:59:49 +0000982
983 if( objc!=1 ){
984 Tcl_WrongNumArgs(interp, 1, objv, "?-bytes?");
985 return TCL_ERROR;
986 }
danielk19775591df52005-12-20 09:19:37 +0000987
danielk19772e588c72005-12-09 14:25:08 +0000988 return sqlite3OutstandingMallocs(interp);
danielk1977191c3e72006-01-19 07:18:14 +0000989#else
990 return TCL_OK;
991#endif
danielk19772e588c72005-12-09 14:25:08 +0000992}
drhdaffd0e2001-04-11 14:28:42 +0000993#endif
994
995/*
danielk197752622822006-01-09 09:59:49 +0000996** Usage: sqlite3_enable_shared_cache BOOLEAN
danielk1977aef0bf62005-12-30 16:28:01 +0000997**
998*/
drh6f7adc82006-01-11 21:41:20 +0000999#if !defined(SQLITE_OMIT_SHARED_CACHE)
1000static int test_enable_shared(
danielk197752622822006-01-09 09:59:49 +00001001 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
danielk1977aef0bf62005-12-30 16:28:01 +00001002 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1003 int objc, /* Number of arguments */
1004 Tcl_Obj *CONST objv[] /* Command arguments */
1005){
1006 int rc;
1007 int enable;
danielk197752622822006-01-09 09:59:49 +00001008 int ret = 0;
danielk1977aef0bf62005-12-30 16:28:01 +00001009
1010 if( objc!=2 ){
1011 Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
1012 return TCL_ERROR;
1013 }
1014 if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){
1015 return TCL_ERROR;
1016 }
drh6f7adc82006-01-11 21:41:20 +00001017 ret = sqlite3ThreadDataReadOnly()->useSharedData;
1018 rc = sqlite3_enable_shared_cache(enable);
danielk1977aef0bf62005-12-30 16:28:01 +00001019 if( rc!=SQLITE_OK ){
1020 Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
1021 return TCL_ERROR;
1022 }
danielk197752622822006-01-09 09:59:49 +00001023 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ret));
danielk1977aef0bf62005-12-30 16:28:01 +00001024 return TCL_OK;
1025}
1026#endif
1027
1028/*
danielk1977161fb792006-01-24 10:58:21 +00001029** Usage: sqlite3_libversion_number
1030**
1031*/
1032static int test_libversion_number(
1033 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1034 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1035 int objc, /* Number of arguments */
1036 Tcl_Obj *CONST objv[] /* Command arguments */
1037){
1038 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_libversion_number()));
1039 return TCL_OK;
1040}
1041
1042/*
danielk1977deb802c2006-02-09 13:43:28 +00001043** Usage: sqlite3_table_column_metadata DB dbname tblname colname
1044**
1045*/
1046#ifdef SQLITE_ENABLE_COLUMN_METADATA
1047static int test_table_column_metadata(
1048 ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
1049 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1050 int objc, /* Number of arguments */
1051 Tcl_Obj *CONST objv[] /* Command arguments */
1052){
1053 sqlite3 *db;
1054 const char *zDb;
1055 const char *zTbl;
1056 const char *zCol;
1057 int rc;
1058 Tcl_Obj *pRet;
1059
1060 const char *zDatatype;
1061 const char *zCollseq;
1062 int notnull;
1063 int primarykey;
1064 int autoincrement;
1065
1066 if( objc!=5 ){
1067 Tcl_WrongNumArgs(interp, 1, objv, "DB dbname tblname colname");
1068 return TCL_ERROR;
1069 }
1070 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1071 zDb = Tcl_GetString(objv[2]);
1072 zTbl = Tcl_GetString(objv[3]);
1073 zCol = Tcl_GetString(objv[4]);
1074
1075 if( strlen(zDb)==0 ) zDb = 0;
1076
1077 rc = sqlite3_table_column_metadata(db, zDb, zTbl, zCol,
1078 &zDatatype, &zCollseq, &notnull, &primarykey, &autoincrement);
1079
1080 if( rc!=SQLITE_OK ){
1081 Tcl_AppendResult(interp, sqlite3_errmsg(db), 0);
1082 return TCL_ERROR;
1083 }
1084
1085 pRet = Tcl_NewObj();
1086 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zDatatype, -1));
1087 Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zCollseq, -1));
1088 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(notnull));
1089 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(primarykey));
1090 Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(autoincrement));
1091 Tcl_SetObjResult(interp, pRet);
1092
1093 return TCL_OK;
1094}
1095#endif
1096
drhc2e87a32006-06-27 15:16:14 +00001097
danielk1977deb802c2006-02-09 13:43:28 +00001098/*
danielk197769e777f2006-06-14 10:38:02 +00001099** Usage: sqlite3_load_extension DB-HANDLE FILE ?PROC?
1100*/
1101static int test_load_extension(
1102 ClientData clientData, /* Not used */
1103 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1104 int objc, /* Number of arguments */
1105 Tcl_Obj *CONST objv[] /* Command arguments */
1106){
1107 Tcl_CmdInfo cmdInfo;
1108 sqlite3 *db;
1109 int rc;
1110 char *zDb;
1111 char *zFile;
1112 char *zProc = 0;
1113 char *zErr = 0;
1114
1115 if( objc!=4 && objc!=3 ){
1116 Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE FILE ?PROC?");
1117 return TCL_ERROR;
1118 }
1119 zDb = Tcl_GetString(objv[1]);
1120 zFile = Tcl_GetString(objv[2]);
1121 if( objc==4 ){
1122 zProc = Tcl_GetString(objv[3]);
1123 }
1124
1125 /* Extract the C database handle from the Tcl command name */
1126 if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
1127 Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0);
1128 return TCL_ERROR;
1129 }
1130 db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
1131 assert(db);
1132
1133 /* Call the underlying C function. If an error occurs, set rc to
1134 ** TCL_ERROR and load any error string into the interpreter. If no
1135 ** error occurs, set rc to TCL_OK.
1136 */
drhc2e87a32006-06-27 15:16:14 +00001137#ifdef SQLITE_OMIT_LOAD_EXTENSION
1138 rc = SQLITE_ERROR;
1139 zErr = sqlite3_mprintf("this build omits sqlite3_load_extension()");
1140#else
danielk197769e777f2006-06-14 10:38:02 +00001141 rc = sqlite3_load_extension(db, zFile, zProc, &zErr);
drhc2e87a32006-06-27 15:16:14 +00001142#endif
danielk197769e777f2006-06-14 10:38:02 +00001143 if( rc!=SQLITE_OK ){
1144 Tcl_SetResult(interp, zErr ? zErr : "", TCL_VOLATILE);
1145 rc = TCL_ERROR;
1146 }else{
1147 rc = TCL_OK;
1148 }
1149 sqlite3_free(zErr);
1150
1151 return rc;
1152}
1153
1154/*
drhc2e87a32006-06-27 15:16:14 +00001155** Usage: sqlite3_enable_load_extension DB-HANDLE ONOFF
1156*/
1157static int test_enable_load(
1158 ClientData clientData, /* Not used */
1159 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1160 int objc, /* Number of arguments */
1161 Tcl_Obj *CONST objv[] /* Command arguments */
1162){
1163 Tcl_CmdInfo cmdInfo;
1164 sqlite3 *db;
1165 char *zDb;
1166 int onoff;
1167
1168 if( objc!=3 ){
1169 Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE ONOFF");
1170 return TCL_ERROR;
1171 }
1172 zDb = Tcl_GetString(objv[1]);
1173
1174 /* Extract the C database handle from the Tcl command name */
1175 if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
1176 Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0);
1177 return TCL_ERROR;
1178 }
1179 db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
1180 assert(db);
1181
1182 /* Get the onoff parameter */
1183 if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){
1184 return TCL_ERROR;
1185 }
1186
1187#ifdef SQLITE_OMIT_LOAD_EXTENSION
1188 Tcl_AppendResult(interp, "this build omits sqlite3_load_extension()");
1189 return TCL_ERROR;
1190#else
1191 sqlite3_enable_load_extension(db, onoff);
1192 return TCL_OK;
1193#endif
1194}
1195
1196/*
drh28b4e482002-03-11 02:06:13 +00001197** Usage: sqlite_abort
1198**
1199** Shutdown the process immediately. This is not a clean shutdown.
1200** This command is used to test the recoverability of a database in
1201** the event of a program crash.
1202*/
1203static int sqlite_abort(
1204 void *NotUsed,
1205 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1206 int argc, /* Number of arguments */
1207 char **argv /* Text of each argument */
1208){
1209 assert( interp==0 ); /* This will always fail */
1210 return TCL_OK;
1211}
1212
1213/*
drh6cbe1f12002-07-01 00:31:36 +00001214** The following routine is a user-defined SQL function whose purpose
1215** is to test the sqlite_set_result() API.
1216*/
danielk19770ae8b832004-05-25 12:05:56 +00001217static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
drh6cbe1f12002-07-01 00:31:36 +00001218 while( argc>=2 ){
drh03d847e2005-12-09 20:21:58 +00001219 const char *zArg0 = (char*)sqlite3_value_text(argv[0]);
danielk19776d88bad2004-05-27 14:23:36 +00001220 if( zArg0 ){
1221 if( 0==sqlite3StrICmp(zArg0, "int") ){
1222 sqlite3_result_int(context, sqlite3_value_int(argv[1]));
1223 }else if( sqlite3StrICmp(zArg0,"int64")==0 ){
1224 sqlite3_result_int64(context, sqlite3_value_int64(argv[1]));
1225 }else if( sqlite3StrICmp(zArg0,"string")==0 ){
drh03d847e2005-12-09 20:21:58 +00001226 sqlite3_result_text(context, (char*)sqlite3_value_text(argv[1]), -1,
danielk1977d8123362004-06-12 09:25:12 +00001227 SQLITE_TRANSIENT);
danielk19776d88bad2004-05-27 14:23:36 +00001228 }else if( sqlite3StrICmp(zArg0,"double")==0 ){
1229 sqlite3_result_double(context, sqlite3_value_double(argv[1]));
1230 }else if( sqlite3StrICmp(zArg0,"null")==0 ){
1231 sqlite3_result_null(context);
1232 }else if( sqlite3StrICmp(zArg0,"value")==0 ){
1233 sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]);
1234 }else{
1235 goto error_out;
1236 }
drh6cbe1f12002-07-01 00:31:36 +00001237 }else{
danielk19776d88bad2004-05-27 14:23:36 +00001238 goto error_out;
drh6cbe1f12002-07-01 00:31:36 +00001239 }
1240 argc -= 2;
1241 argv += 2;
1242 }
danielk19776d88bad2004-05-27 14:23:36 +00001243 return;
1244
1245error_out:
1246 sqlite3_result_error(context,"first argument should be one of: "
1247 "int int64 string double null value", -1);
drh6cbe1f12002-07-01 00:31:36 +00001248}
1249
1250/*
1251** Usage: sqlite_register_test_function DB NAME
1252**
1253** Register the test SQL function on the database DB under the name NAME.
1254*/
drhc2eef3b2002-08-31 18:53:06 +00001255static int test_register_func(
drh6cbe1f12002-07-01 00:31:36 +00001256 void *NotUsed,
1257 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1258 int argc, /* Number of arguments */
1259 char **argv /* Text of each argument */
1260){
drh9bb575f2004-09-06 17:24:11 +00001261 sqlite3 *db;
drh6cbe1f12002-07-01 00:31:36 +00001262 int rc;
1263 if( argc!=3 ){
1264 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
1265 " DB FUNCTION-NAME", 0);
1266 return TCL_ERROR;
1267 }
drhb86ccfb2003-01-28 23:13:10 +00001268 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk1977f9d64d22004-06-19 08:18:07 +00001269 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0,
danielk1977d8123362004-06-12 09:25:12 +00001270 testFunc, 0, 0);
drh6cbe1f12002-07-01 00:31:36 +00001271 if( rc!=0 ){
danielk1977f20b21c2004-05-31 23:56:42 +00001272 Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);
drh6cbe1f12002-07-01 00:31:36 +00001273 return TCL_ERROR;
1274 }
drhc60d0442004-09-30 13:43:13 +00001275 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drh6cbe1f12002-07-01 00:31:36 +00001276 return TCL_OK;
1277}
1278
1279/*
danielk1977106bb232004-05-21 10:08:53 +00001280** Usage: sqlite3_finalize STMT
drhb86ccfb2003-01-28 23:13:10 +00001281**
danielk1977106bb232004-05-21 10:08:53 +00001282** Finalize a statement handle.
drhb86ccfb2003-01-28 23:13:10 +00001283*/
1284static int test_finalize(
danielk1977106bb232004-05-21 10:08:53 +00001285 void * clientData,
1286 Tcl_Interp *interp,
1287 int objc,
1288 Tcl_Obj *CONST objv[]
drhb86ccfb2003-01-28 23:13:10 +00001289){
danielk1977106bb232004-05-21 10:08:53 +00001290 sqlite3_stmt *pStmt;
drhb86ccfb2003-01-28 23:13:10 +00001291 int rc;
drhc60d0442004-09-30 13:43:13 +00001292 sqlite3 *db;
danielk1977106bb232004-05-21 10:08:53 +00001293
1294 if( objc!=2 ){
1295 Tcl_AppendResult(interp, "wrong # args: should be \"",
1296 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
drhb86ccfb2003-01-28 23:13:10 +00001297 return TCL_ERROR;
1298 }
danielk1977106bb232004-05-21 10:08:53 +00001299
1300 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1301
danielk19774397de52005-01-12 12:44:03 +00001302 if( pStmt ){
1303 db = StmtToDb(pStmt);
1304 }
danielk1977fc57d7b2004-05-26 02:04:57 +00001305 rc = sqlite3_finalize(pStmt);
danielk1977b77f5da2004-05-26 13:27:00 +00001306 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
danielk19774397de52005-01-12 12:44:03 +00001307 if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk1977106bb232004-05-21 10:08:53 +00001308 return TCL_OK;
1309}
1310
1311/*
1312** Usage: sqlite3_reset STMT
1313**
danielk1977261919c2005-12-06 12:52:59 +00001314** Reset a statement handle.
danielk1977106bb232004-05-21 10:08:53 +00001315*/
1316static int test_reset(
1317 void * clientData,
1318 Tcl_Interp *interp,
1319 int objc,
1320 Tcl_Obj *CONST objv[]
1321){
1322 sqlite3_stmt *pStmt;
1323 int rc;
1324
1325 if( objc!=2 ){
1326 Tcl_AppendResult(interp, "wrong # args: should be \"",
1327 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
1328 return TCL_ERROR;
1329 }
1330
1331 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1332
danielk1977fc57d7b2004-05-26 02:04:57 +00001333 rc = sqlite3_reset(pStmt);
danielk1977261919c2005-12-06 12:52:59 +00001334 if( pStmt && sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ){
1335 return TCL_ERROR;
1336 }
danielk19774397de52005-01-12 12:44:03 +00001337 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
danielk1977261919c2005-12-06 12:52:59 +00001338/*
danielk1977106bb232004-05-21 10:08:53 +00001339 if( rc ){
drhb86ccfb2003-01-28 23:13:10 +00001340 return TCL_ERROR;
1341 }
danielk1977261919c2005-12-06 12:52:59 +00001342*/
drhb86ccfb2003-01-28 23:13:10 +00001343 return TCL_OK;
1344}
1345
drh5a387052003-01-11 14:19:51 +00001346/*
drhd89bd002005-01-22 03:03:54 +00001347** Usage: sqlite3_expired STMT
1348**
1349** Return TRUE if a recompilation of the statement is recommended.
1350*/
1351static int test_expired(
1352 void * clientData,
1353 Tcl_Interp *interp,
1354 int objc,
1355 Tcl_Obj *CONST objv[]
1356){
1357 sqlite3_stmt *pStmt;
1358 if( objc!=2 ){
1359 Tcl_AppendResult(interp, "wrong # args: should be \"",
1360 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
1361 return TCL_ERROR;
1362 }
1363 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1364 Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite3_expired(pStmt)));
1365 return TCL_OK;
1366}
1367
1368/*
drhf8db1bc2005-04-22 02:38:37 +00001369** Usage: sqlite3_transfer_bindings FROMSTMT TOSTMT
1370**
1371** Transfer all bindings from FROMSTMT over to TOSTMT
1372*/
1373static int test_transfer_bind(
1374 void * clientData,
1375 Tcl_Interp *interp,
1376 int objc,
1377 Tcl_Obj *CONST objv[]
1378){
1379 sqlite3_stmt *pStmt1, *pStmt2;
1380 if( objc!=3 ){
1381 Tcl_AppendResult(interp, "wrong # args: should be \"",
1382 Tcl_GetStringFromObj(objv[0], 0), " FROM-STMT TO-STMT", 0);
1383 return TCL_ERROR;
1384 }
1385 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt1)) return TCL_ERROR;
1386 if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt2)) return TCL_ERROR;
1387 Tcl_SetObjResult(interp,
1388 Tcl_NewIntObj(sqlite3_transfer_bindings(pStmt1,pStmt2)));
1389 return TCL_OK;
1390}
1391
1392/*
danielk1977fbcd5852004-06-15 02:44:18 +00001393** Usage: sqlite3_changes DB
drh50457892003-09-06 01:10:47 +00001394**
danielk1977fbcd5852004-06-15 02:44:18 +00001395** Return the number of changes made to the database by the last SQL
1396** execution.
drh50457892003-09-06 01:10:47 +00001397*/
danielk1977fbcd5852004-06-15 02:44:18 +00001398static int test_changes(
1399 void * clientData,
1400 Tcl_Interp *interp,
1401 int objc,
1402 Tcl_Obj *CONST objv[]
1403){
1404 sqlite3 *db;
1405 if( objc!=2 ){
1406 Tcl_AppendResult(interp, "wrong # args: should be \"",
1407 Tcl_GetString(objv[0]), " DB", 0);
1408 return TCL_ERROR;
1409 }
1410 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1411 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db)));
1412 return TCL_OK;
1413}
drh50457892003-09-06 01:10:47 +00001414
1415/*
drh7c972de2003-09-06 22:18:07 +00001416** This is the "static_bind_value" that variables are bound to when
danielk19776f8a5032004-05-10 10:34:51 +00001417** the FLAG option of sqlite3_bind is "static"
drh50457892003-09-06 01:10:47 +00001418*/
drh7c972de2003-09-06 22:18:07 +00001419static char *sqlite_static_bind_value = 0;
1420
1421/*
danielk19776f8a5032004-05-10 10:34:51 +00001422** Usage: sqlite3_bind VM IDX VALUE FLAGS
drh7c972de2003-09-06 22:18:07 +00001423**
1424** Sets the value of the IDX-th occurance of "?" in the original SQL
1425** string. VALUE is the new value. If FLAGS=="null" then VALUE is
1426** ignored and the value is set to NULL. If FLAGS=="static" then
1427** the value is set to the value of a static variable named
1428** "sqlite_static_bind_value". If FLAGS=="normal" then a copy
drhbf8aa2a2005-12-02 02:44:05 +00001429** of the VALUE is made. If FLAGS=="blob10" then a VALUE is ignored
1430** an a 10-byte blob "abc\000xyz\000pq" is inserted.
drh7c972de2003-09-06 22:18:07 +00001431*/
1432static int test_bind(
drh50457892003-09-06 01:10:47 +00001433 void *NotUsed,
1434 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1435 int argc, /* Number of arguments */
1436 char **argv /* Text of each argument */
1437){
danielk1977fc57d7b2004-05-26 02:04:57 +00001438 sqlite3_stmt *pStmt;
drh50457892003-09-06 01:10:47 +00001439 int rc;
drh7c972de2003-09-06 22:18:07 +00001440 int idx;
1441 if( argc!=5 ){
drh50457892003-09-06 01:10:47 +00001442 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
drh7c972de2003-09-06 22:18:07 +00001443 " VM IDX VALUE (null|static|normal)\"", 0);
drh50457892003-09-06 01:10:47 +00001444 return TCL_ERROR;
1445 }
danielk1977fc57d7b2004-05-26 02:04:57 +00001446 if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR;
drh7c972de2003-09-06 22:18:07 +00001447 if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR;
1448 if( strcmp(argv[4],"null")==0 ){
danielk1977fc57d7b2004-05-26 02:04:57 +00001449 rc = sqlite3_bind_null(pStmt, idx);
drh7c972de2003-09-06 22:18:07 +00001450 }else if( strcmp(argv[4],"static")==0 ){
danielk1977fc57d7b2004-05-26 02:04:57 +00001451 rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0);
drh7c972de2003-09-06 22:18:07 +00001452 }else if( strcmp(argv[4],"normal")==0 ){
danielk1977d8123362004-06-12 09:25:12 +00001453 rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT);
drhbf8aa2a2005-12-02 02:44:05 +00001454 }else if( strcmp(argv[4],"blob10")==0 ){
1455 rc = sqlite3_bind_text(pStmt, idx, "abc\000xyz\000pq", 10, SQLITE_STATIC);
drh7c972de2003-09-06 22:18:07 +00001456 }else{
1457 Tcl_AppendResult(interp, "4th argument should be "
1458 "\"null\" or \"static\" or \"normal\"", 0);
1459 return TCL_ERROR;
1460 }
drhc60d0442004-09-30 13:43:13 +00001461 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
drh50457892003-09-06 01:10:47 +00001462 if( rc ){
1463 char zBuf[50];
1464 sprintf(zBuf, "(%d) ", rc);
danielk1977f20b21c2004-05-31 23:56:42 +00001465 Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0);
drh50457892003-09-06 01:10:47 +00001466 return TCL_ERROR;
1467 }
1468 return TCL_OK;
1469}
1470
drh5436dc22004-11-14 04:04:17 +00001471#ifndef SQLITE_OMIT_UTF16
danielk19774e6af132004-06-10 14:01:08 +00001472/*
1473** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be>
1474**
1475** This function is used to test that SQLite selects the correct collation
1476** sequence callback when multiple versions (for different text encodings)
1477** are available.
1478**
1479** Calling this routine registers the collation sequence "test_collate"
1480** with database handle <db>. The second argument must be a list of three
1481** boolean values. If the first is true, then a version of test_collate is
1482** registered for UTF-8, if the second is true, a version is registered for
1483** UTF-16le, if the third is true, a UTF-16be version is available.
1484** Previous versions of test_collate are deleted.
1485**
1486** The collation sequence test_collate is implemented by calling the
1487** following TCL script:
1488**
1489** "test_collate <enc> <lhs> <rhs>"
1490**
1491** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8.
1492** The <enc> parameter is the encoding of the collation function that
1493** SQLite selected to call. The TCL test script implements the
1494** "test_collate" proc.
1495**
1496** Note that this will only work with one intepreter at a time, as the
1497** interp pointer to use when evaluating the TCL script is stored in
1498** pTestCollateInterp.
1499*/
1500static Tcl_Interp* pTestCollateInterp;
1501static int test_collate_func(
1502 void *pCtx,
1503 int nA, const void *zA,
1504 int nB, const void *zB
1505){
1506 Tcl_Interp *i = pTestCollateInterp;
1507 int encin = (int)pCtx;
1508 int res;
drh4db38a72005-09-01 12:16:28 +00001509 int n;
danielk19774e6af132004-06-10 14:01:08 +00001510
1511 sqlite3_value *pVal;
1512 Tcl_Obj *pX;
1513
1514 pX = Tcl_NewStringObj("test_collate", -1);
1515 Tcl_IncrRefCount(pX);
1516
1517 switch( encin ){
1518 case SQLITE_UTF8:
1519 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1));
1520 break;
1521 case SQLITE_UTF16LE:
1522 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1));
1523 break;
1524 case SQLITE_UTF16BE:
1525 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1));
1526 break;
1527 default:
1528 assert(0);
1529 }
1530
1531 pVal = sqlite3ValueNew();
danielk1977bfd6cce2004-06-18 04:24:54 +00001532 sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC);
drh4db38a72005-09-01 12:16:28 +00001533 n = sqlite3_value_bytes(pVal);
drh03d847e2005-12-09 20:21:58 +00001534 Tcl_ListObjAppendElement(i,pX,
1535 Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
danielk1977bfd6cce2004-06-18 04:24:54 +00001536 sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC);
drh4db38a72005-09-01 12:16:28 +00001537 n = sqlite3_value_bytes(pVal);
drh03d847e2005-12-09 20:21:58 +00001538 Tcl_ListObjAppendElement(i,pX,
1539 Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
danielk19774e6af132004-06-10 14:01:08 +00001540 sqlite3ValueFree(pVal);
1541
1542 Tcl_EvalObjEx(i, pX, 0);
1543 Tcl_DecrRefCount(pX);
1544 Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res);
1545 return res;
1546}
1547static int test_collate(
1548 void * clientData,
1549 Tcl_Interp *interp,
1550 int objc,
1551 Tcl_Obj *CONST objv[]
1552){
1553 sqlite3 *db;
1554 int val;
danielk1977312d6b32004-06-29 13:18:23 +00001555 sqlite3_value *pVal;
drhc60d0442004-09-30 13:43:13 +00001556 int rc;
danielk19774e6af132004-06-10 14:01:08 +00001557
1558 if( objc!=5 ) goto bad_args;
1559 pTestCollateInterp = interp;
1560 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1561
1562 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +00001563 rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8,
1564 (void *)SQLITE_UTF8, val?test_collate_func:0);
1565 if( rc==SQLITE_OK ){
1566 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
1567 rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE,
1568 (void *)SQLITE_UTF16LE, val?test_collate_func:0);
1569 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
danielk1977312d6b32004-06-29 13:18:23 +00001570
danielk19779a30cf62006-01-18 04:26:07 +00001571#ifdef SQLITE_MEMDEBUG
1572 if( sqlite3_iMallocFail>0 ){
1573 sqlite3_iMallocFail++;
1574 }
1575#endif
drhc60d0442004-09-30 13:43:13 +00001576 pVal = sqlite3ValueNew();
1577 sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC);
danielk19779a30cf62006-01-18 04:26:07 +00001578 rc = sqlite3_create_collation16(db,
1579 sqlite3ValueText(pVal, SQLITE_UTF16NATIVE), SQLITE_UTF16BE,
1580 (void *)SQLITE_UTF16BE, val?test_collate_func:0);
drhc60d0442004-09-30 13:43:13 +00001581 sqlite3ValueFree(pVal);
1582 }
1583 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk19779a30cf62006-01-18 04:26:07 +00001584
1585 if( rc!=SQLITE_OK ){
1586 Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
1587 return TCL_ERROR;
1588 }
danielk19774e6af132004-06-10 14:01:08 +00001589 return TCL_OK;
1590
1591bad_args:
1592 Tcl_AppendResult(interp, "wrong # args: should be \"",
1593 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
1594 return TCL_ERROR;
1595}
1596
drh268803a2005-12-14 20:11:30 +00001597/*
1598** When the collation needed callback is invoked, record the name of
1599** the requested collating function here. The recorded name is linked
1600** to a TCL variable and used to make sure that the requested collation
1601** name is correct.
1602*/
1603static char zNeededCollation[200];
1604static char *pzNeededCollation = zNeededCollation;
1605
1606
1607/*
1608** Called when a collating sequence is needed. Registered using
1609** sqlite3_collation_needed16().
1610*/
danielk1977312d6b32004-06-29 13:18:23 +00001611static void test_collate_needed_cb(
1612 void *pCtx,
1613 sqlite3 *db,
1614 int eTextRep,
drh268803a2005-12-14 20:11:30 +00001615 const void *pName
danielk1977312d6b32004-06-29 13:18:23 +00001616){
danielk197714db2662006-01-09 16:12:04 +00001617 int enc = ENC(db);
drh268803a2005-12-14 20:11:30 +00001618 int i;
1619 char *z;
1620 for(z = (char*)pName, i=0; *z || z[1]; z++){
1621 if( *z ) zNeededCollation[i++] = *z;
1622 }
1623 zNeededCollation[i] = 0;
danielk1977312d6b32004-06-29 13:18:23 +00001624 sqlite3_create_collation(
danielk197714db2662006-01-09 16:12:04 +00001625 db, "test_collate", ENC(db), (void *)enc, test_collate_func);
danielk1977312d6b32004-06-29 13:18:23 +00001626}
1627
1628/*
1629** Usage: add_test_collate_needed DB
1630*/
1631static int test_collate_needed(
1632 void * clientData,
1633 Tcl_Interp *interp,
1634 int objc,
1635 Tcl_Obj *CONST objv[]
1636){
1637 sqlite3 *db;
drhc60d0442004-09-30 13:43:13 +00001638 int rc;
danielk1977312d6b32004-06-29 13:18:23 +00001639
1640 if( objc!=2 ) goto bad_args;
1641 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +00001642 rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb);
drh268803a2005-12-14 20:11:30 +00001643 zNeededCollation[0] = 0;
drhc60d0442004-09-30 13:43:13 +00001644 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk1977312d6b32004-06-29 13:18:23 +00001645 return TCL_OK;
1646
1647bad_args:
1648 Tcl_WrongNumArgs(interp, 1, objv, "DB");
1649 return TCL_ERROR;
1650}
drh7d9bd4e2006-02-16 18:16:36 +00001651
1652/*
1653** tclcmd: add_alignment_test_collations DB
1654**
1655** Add two new collating sequences to the database DB
1656**
1657** utf16_aligned
1658** utf16_unaligned
1659**
1660** Both collating sequences use the same sort order as BINARY.
1661** The only difference is that the utf16_aligned collating
1662** sequence is declared with the SQLITE_UTF16_ALIGNED flag.
1663** Both collating functions increment the unaligned utf16 counter
1664** whenever they see a string that begins on an odd byte boundary.
1665*/
1666static int unaligned_string_counter = 0;
1667static int alignmentCollFunc(
1668 void *NotUsed,
1669 int nKey1, const void *pKey1,
1670 int nKey2, const void *pKey2
1671){
1672 int rc, n;
1673 n = nKey1<nKey2 ? nKey1 : nKey2;
1674 if( nKey1>0 && 1==(1&(int)pKey1) ) unaligned_string_counter++;
1675 if( nKey2>0 && 1==(1&(int)pKey2) ) unaligned_string_counter++;
1676 rc = memcmp(pKey1, pKey2, n);
1677 if( rc==0 ){
1678 rc = nKey1 - nKey2;
1679 }
1680 return rc;
1681}
1682static int add_alignment_test_collations(
1683 void * clientData,
1684 Tcl_Interp *interp,
1685 int objc,
1686 Tcl_Obj *CONST objv[]
1687){
1688 sqlite3 *db;
1689 if( objc>=2 ){
1690 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1691 sqlite3_create_collation(db, "utf16_unaligned",
1692 SQLITE_UTF16,
1693 0, alignmentCollFunc);
1694 sqlite3_create_collation(db, "utf16_aligned",
1695 SQLITE_UTF16 | SQLITE_UTF16_ALIGNED,
1696 0, alignmentCollFunc);
1697 }
1698 return SQLITE_OK;
1699}
1700#endif /* !defined(SQLITE_OMIT_UTF16) */
danielk1977312d6b32004-06-29 13:18:23 +00001701
danielk1977c8e9a2d2004-06-25 12:08:46 +00001702/*
1703** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
1704**
1705** This function is used to test that SQLite selects the correct user
1706** function callback when multiple versions (for different text encodings)
1707** are available.
1708**
1709** Calling this routine registers up to three versions of the user function
1710** "test_function" with database handle <db>. If the second argument is
1711** true, then a version of test_function is registered for UTF-8, if the
1712** third is true, a version is registered for UTF-16le, if the fourth is
1713** true, a UTF-16be version is available. Previous versions of
1714** test_function are deleted.
1715**
1716** The user function is implemented by calling the following TCL script:
1717**
1718** "test_function <enc> <arg>"
1719**
1720** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the
1721** single argument passed to the SQL function. The value returned by
1722** the TCL script is used as the return value of the SQL function. It
1723** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8
1724** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
1725** prefers UTF-16BE.
1726*/
drh5436dc22004-11-14 04:04:17 +00001727#ifndef SQLITE_OMIT_UTF16
danielk1977c8e9a2d2004-06-25 12:08:46 +00001728static void test_function_utf8(
1729 sqlite3_context *pCtx,
1730 int nArg,
1731 sqlite3_value **argv
1732){
1733 Tcl_Interp *interp;
1734 Tcl_Obj *pX;
1735 sqlite3_value *pVal;
1736 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1737 pX = Tcl_NewStringObj("test_function", -1);
1738 Tcl_IncrRefCount(pX);
1739 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1));
1740 Tcl_ListObjAppendElement(interp, pX,
drh03d847e2005-12-09 20:21:58 +00001741 Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
danielk1977c8e9a2d2004-06-25 12:08:46 +00001742 Tcl_EvalObjEx(interp, pX, 0);
1743 Tcl_DecrRefCount(pX);
1744 sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT);
1745 pVal = sqlite3ValueNew();
1746 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1747 SQLITE_UTF8, SQLITE_STATIC);
1748 sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal),
1749 -1, SQLITE_TRANSIENT);
1750 sqlite3ValueFree(pVal);
1751}
1752static void test_function_utf16le(
1753 sqlite3_context *pCtx,
1754 int nArg,
1755 sqlite3_value **argv
1756){
1757 Tcl_Interp *interp;
1758 Tcl_Obj *pX;
1759 sqlite3_value *pVal;
1760 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1761 pX = Tcl_NewStringObj("test_function", -1);
1762 Tcl_IncrRefCount(pX);
1763 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1));
1764 Tcl_ListObjAppendElement(interp, pX,
drh03d847e2005-12-09 20:21:58 +00001765 Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
danielk1977c8e9a2d2004-06-25 12:08:46 +00001766 Tcl_EvalObjEx(interp, pX, 0);
1767 Tcl_DecrRefCount(pX);
1768 pVal = sqlite3ValueNew();
1769 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1770 SQLITE_UTF8, SQLITE_STATIC);
drh03d847e2005-12-09 20:21:58 +00001771 sqlite3_result_text(pCtx,(char*)sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT);
danielk1977c8e9a2d2004-06-25 12:08:46 +00001772 sqlite3ValueFree(pVal);
1773}
1774static void test_function_utf16be(
1775 sqlite3_context *pCtx,
1776 int nArg,
1777 sqlite3_value **argv
1778){
1779 Tcl_Interp *interp;
1780 Tcl_Obj *pX;
1781 sqlite3_value *pVal;
1782 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1783 pX = Tcl_NewStringObj("test_function", -1);
1784 Tcl_IncrRefCount(pX);
1785 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1));
1786 Tcl_ListObjAppendElement(interp, pX,
drh03d847e2005-12-09 20:21:58 +00001787 Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
danielk1977c8e9a2d2004-06-25 12:08:46 +00001788 Tcl_EvalObjEx(interp, pX, 0);
1789 Tcl_DecrRefCount(pX);
1790 pVal = sqlite3ValueNew();
1791 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1792 SQLITE_UTF8, SQLITE_STATIC);
1793 sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal),
1794 -1, SQLITE_TRANSIENT);
1795 sqlite3ValueFree(pVal);
1796}
drh5436dc22004-11-14 04:04:17 +00001797#endif /* SQLITE_OMIT_UTF16 */
danielk1977c8e9a2d2004-06-25 12:08:46 +00001798static int test_function(
1799 void * clientData,
1800 Tcl_Interp *interp,
1801 int objc,
1802 Tcl_Obj *CONST objv[]
1803){
drh5436dc22004-11-14 04:04:17 +00001804#ifndef SQLITE_OMIT_UTF16
danielk1977c8e9a2d2004-06-25 12:08:46 +00001805 sqlite3 *db;
1806 int val;
1807
1808 if( objc!=5 ) goto bad_args;
1809 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1810
1811 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
1812 if( val ){
1813 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8,
1814 interp, test_function_utf8, 0, 0);
1815 }
1816 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
1817 if( val ){
1818 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE,
1819 interp, test_function_utf16le, 0, 0);
1820 }
1821 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
1822 if( val ){
1823 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE,
1824 interp, test_function_utf16be, 0, 0);
1825 }
1826
1827 return TCL_OK;
1828bad_args:
1829 Tcl_AppendResult(interp, "wrong # args: should be \"",
1830 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
drh5436dc22004-11-14 04:04:17 +00001831#endif /* SQLITE_OMIT_UTF16 */
danielk1977c8e9a2d2004-06-25 12:08:46 +00001832 return TCL_ERROR;
1833}
1834
danielk1977312d6b32004-06-29 13:18:23 +00001835/*
1836** Usage: test_errstr <err code>
1837**
1838** Test that the english language string equivalents for sqlite error codes
1839** are sane. The parameter is an integer representing an sqlite error code.
1840** The result is a list of two elements, the string representation of the
1841** error code and the english language explanation.
1842*/
1843static int test_errstr(
1844 void * clientData,
1845 Tcl_Interp *interp,
1846 int objc,
1847 Tcl_Obj *CONST objv[]
1848){
1849 char *zCode;
1850 int i;
1851 if( objc!=1 ){
1852 Tcl_WrongNumArgs(interp, 1, objv, "<error code>");
1853 }
1854
1855 zCode = Tcl_GetString(objv[1]);
1856 for(i=0; i<200; i++){
1857 if( 0==strcmp(errorName(i), zCode) ) break;
1858 }
1859 Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0);
1860 return TCL_OK;
1861}
1862
drh50457892003-09-06 01:10:47 +00001863/*
drh99ee3602003-02-16 19:13:36 +00001864** Usage: breakpoint
1865**
1866** This routine exists for one purpose - to provide a place to put a
1867** breakpoint with GDB that can be triggered using TCL code. The use
1868** for this is when a particular test fails on (say) the 1485th iteration.
1869** In the TCL test script, we can add code like this:
1870**
1871** if {$i==1485} breakpoint
1872**
1873** Then run testfixture in the debugger and wait for the breakpoint to
1874** fire. Then additional breakpoints can be set to trace down the bug.
1875*/
1876static int test_breakpoint(
1877 void *NotUsed,
1878 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1879 int argc, /* Number of arguments */
1880 char **argv /* Text of each argument */
1881){
1882 return TCL_OK; /* Do nothing */
1883}
1884
drh241db312004-06-22 12:46:53 +00001885/*
1886** Usage: sqlite3_bind_int STMT N VALUE
1887**
1888** Test the sqlite3_bind_int interface. STMT is a prepared statement.
1889** N is the index of a wildcard in the prepared statement. This command
1890** binds a 32-bit integer VALUE to that wildcard.
1891*/
1892static int test_bind_int(
danielk197751e3d8e2004-05-20 01:12:34 +00001893 void * clientData,
1894 Tcl_Interp *interp,
1895 int objc,
1896 Tcl_Obj *CONST objv[]
1897){
1898 sqlite3_stmt *pStmt;
1899 int idx;
1900 int value;
1901 int rc;
1902
1903 if( objc!=4 ){
1904 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001905 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001906 return TCL_ERROR;
1907 }
1908
1909 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1910 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1911 if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
1912
danielk1977c572ef72004-05-27 09:28:41 +00001913 rc = sqlite3_bind_int(pStmt, idx, value);
drhc60d0442004-09-30 13:43:13 +00001914 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001915 if( rc!=SQLITE_OK ){
1916 return TCL_ERROR;
1917 }
1918
1919 return TCL_OK;
1920}
1921
drh241db312004-06-22 12:46:53 +00001922
1923/*
1924** Usage: sqlite3_bind_int64 STMT N VALUE
1925**
1926** Test the sqlite3_bind_int64 interface. STMT is a prepared statement.
1927** N is the index of a wildcard in the prepared statement. This command
1928** binds a 64-bit integer VALUE to that wildcard.
1929*/
danielk197751e3d8e2004-05-20 01:12:34 +00001930static int test_bind_int64(
1931 void * clientData,
1932 Tcl_Interp *interp,
1933 int objc,
1934 Tcl_Obj *CONST objv[]
1935){
1936 sqlite3_stmt *pStmt;
1937 int idx;
1938 i64 value;
1939 int rc;
1940
1941 if( objc!=4 ){
1942 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001943 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001944 return TCL_ERROR;
1945 }
1946
1947 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1948 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1949 if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
1950
1951 rc = sqlite3_bind_int64(pStmt, idx, value);
drhc60d0442004-09-30 13:43:13 +00001952 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001953 if( rc!=SQLITE_OK ){
1954 return TCL_ERROR;
1955 }
1956
1957 return TCL_OK;
1958}
1959
drh241db312004-06-22 12:46:53 +00001960
1961/*
1962** Usage: sqlite3_bind_double STMT N VALUE
1963**
1964** Test the sqlite3_bind_double interface. STMT is a prepared statement.
1965** N is the index of a wildcard in the prepared statement. This command
1966** binds a 64-bit integer VALUE to that wildcard.
1967*/
danielk197751e3d8e2004-05-20 01:12:34 +00001968static int test_bind_double(
1969 void * clientData,
1970 Tcl_Interp *interp,
1971 int objc,
1972 Tcl_Obj *CONST objv[]
1973){
1974 sqlite3_stmt *pStmt;
1975 int idx;
1976 double value;
1977 int rc;
1978
1979 if( objc!=4 ){
1980 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001981 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001982 return TCL_ERROR;
1983 }
1984
1985 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1986 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1987 if( Tcl_GetDoubleFromObj(interp, objv[3], &value) ) return TCL_ERROR;
1988
1989 rc = sqlite3_bind_double(pStmt, idx, value);
drhc60d0442004-09-30 13:43:13 +00001990 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001991 if( rc!=SQLITE_OK ){
1992 return TCL_ERROR;
1993 }
1994
1995 return TCL_OK;
1996}
1997
drh241db312004-06-22 12:46:53 +00001998/*
1999** Usage: sqlite3_bind_null STMT N
2000**
2001** Test the sqlite3_bind_null interface. STMT is a prepared statement.
2002** N is the index of a wildcard in the prepared statement. This command
2003** binds a NULL to the wildcard.
2004*/
danielk197751e3d8e2004-05-20 01:12:34 +00002005static int test_bind_null(
2006 void * clientData,
2007 Tcl_Interp *interp,
2008 int objc,
2009 Tcl_Obj *CONST objv[]
2010){
2011 sqlite3_stmt *pStmt;
2012 int idx;
2013 int rc;
2014
2015 if( objc!=3 ){
2016 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00002017 Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00002018 return TCL_ERROR;
2019 }
2020
2021 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2022 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
2023
2024 rc = sqlite3_bind_null(pStmt, idx);
drhc60d0442004-09-30 13:43:13 +00002025 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00002026 if( rc!=SQLITE_OK ){
2027 return TCL_ERROR;
2028 }
2029
2030 return TCL_OK;
2031}
2032
drh241db312004-06-22 12:46:53 +00002033/*
2034** Usage: sqlite3_bind_text STMT N STRING BYTES
2035**
2036** Test the sqlite3_bind_text interface. STMT is a prepared statement.
2037** N is the index of a wildcard in the prepared statement. This command
2038** binds a UTF-8 string STRING to the wildcard. The string is BYTES bytes
2039** long.
2040*/
danielk197751e3d8e2004-05-20 01:12:34 +00002041static int test_bind_text(
2042 void * clientData,
2043 Tcl_Interp *interp,
2044 int objc,
2045 Tcl_Obj *CONST objv[]
2046){
2047 sqlite3_stmt *pStmt;
2048 int idx;
2049 int bytes;
2050 char *value;
2051 int rc;
2052
2053 if( objc!=5 ){
2054 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00002055 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00002056 return TCL_ERROR;
2057 }
2058
2059 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2060 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
2061 value = Tcl_GetString(objv[3]);
2062 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
2063
danielk1977d8123362004-06-12 09:25:12 +00002064 rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
drhc60d0442004-09-30 13:43:13 +00002065 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00002066 if( rc!=SQLITE_OK ){
drh473d1792005-06-06 17:54:55 +00002067 Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
danielk197751e3d8e2004-05-20 01:12:34 +00002068 return TCL_ERROR;
2069 }
2070
2071 return TCL_OK;
2072}
2073
drh241db312004-06-22 12:46:53 +00002074/*
danielk1977161fb792006-01-24 10:58:21 +00002075** Usage: sqlite3_bind_text16 ?-static? STMT N STRING BYTES
drh241db312004-06-22 12:46:53 +00002076**
2077** Test the sqlite3_bind_text16 interface. STMT is a prepared statement.
2078** N is the index of a wildcard in the prepared statement. This command
2079** binds a UTF-16 string STRING to the wildcard. The string is BYTES bytes
2080** long.
2081*/
danielk197751e3d8e2004-05-20 01:12:34 +00002082static int test_bind_text16(
2083 void * clientData,
2084 Tcl_Interp *interp,
2085 int objc,
2086 Tcl_Obj *CONST objv[]
2087){
drh5436dc22004-11-14 04:04:17 +00002088#ifndef SQLITE_OMIT_UTF16
danielk197751e3d8e2004-05-20 01:12:34 +00002089 sqlite3_stmt *pStmt;
2090 int idx;
2091 int bytes;
2092 char *value;
2093 int rc;
2094
danielk1977161fb792006-01-24 10:58:21 +00002095 void (*xDel)() = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT);
2096 Tcl_Obj *oStmt = objv[objc-4];
2097 Tcl_Obj *oN = objv[objc-3];
2098 Tcl_Obj *oString = objv[objc-2];
2099 Tcl_Obj *oBytes = objv[objc-1];
2100
2101 if( objc!=5 && objc!=6){
danielk197751e3d8e2004-05-20 01:12:34 +00002102 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00002103 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00002104 return TCL_ERROR;
2105 }
2106
danielk1977161fb792006-01-24 10:58:21 +00002107 if( getStmtPointer(interp, Tcl_GetString(oStmt), &pStmt) ) return TCL_ERROR;
2108 if( Tcl_GetIntFromObj(interp, oN, &idx) ) return TCL_ERROR;
2109 value = (char*)Tcl_GetByteArrayFromObj(oString, 0);
2110 if( Tcl_GetIntFromObj(interp, oBytes, &bytes) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00002111
danielk1977161fb792006-01-24 10:58:21 +00002112 rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, xDel);
drhc60d0442004-09-30 13:43:13 +00002113 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00002114 if( rc!=SQLITE_OK ){
2115 return TCL_ERROR;
2116 }
2117
drh5436dc22004-11-14 04:04:17 +00002118#endif /* SQLITE_OMIT_UTF16 */
danielk197751e3d8e2004-05-20 01:12:34 +00002119 return TCL_OK;
2120}
2121
drh241db312004-06-22 12:46:53 +00002122/*
2123** Usage: sqlite3_bind_blob STMT N DATA BYTES
2124**
2125** Test the sqlite3_bind_blob interface. STMT is a prepared statement.
2126** N is the index of a wildcard in the prepared statement. This command
2127** binds a BLOB to the wildcard. The BLOB is BYTES bytes in size.
2128*/
danielk197751e3d8e2004-05-20 01:12:34 +00002129static int test_bind_blob(
2130 void * clientData,
2131 Tcl_Interp *interp,
2132 int objc,
2133 Tcl_Obj *CONST objv[]
2134){
2135 sqlite3_stmt *pStmt;
2136 int idx;
2137 int bytes;
2138 char *value;
2139 int rc;
2140
2141 if( objc!=5 ){
2142 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00002143 Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00002144 return TCL_ERROR;
2145 }
2146
2147 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2148 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
2149 value = Tcl_GetString(objv[3]);
danielk197749e46432004-05-27 13:55:27 +00002150 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00002151
danielk1977d8123362004-06-12 09:25:12 +00002152 rc = sqlite3_bind_blob(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
drhc60d0442004-09-30 13:43:13 +00002153 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00002154 if( rc!=SQLITE_OK ){
2155 return TCL_ERROR;
2156 }
2157
2158 return TCL_OK;
2159}
2160
drh99ee3602003-02-16 19:13:36 +00002161/*
drh75f6a032004-07-15 14:15:00 +00002162** Usage: sqlite3_bind_parameter_count STMT
2163**
2164** Return the number of wildcards in the given statement.
2165*/
2166static int test_bind_parameter_count(
2167 void * clientData,
2168 Tcl_Interp *interp,
2169 int objc,
2170 Tcl_Obj *CONST objv[]
2171){
2172 sqlite3_stmt *pStmt;
2173
2174 if( objc!=2 ){
2175 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
2176 return TCL_ERROR;
2177 }
2178 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2179 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt)));
2180 return TCL_OK;
2181}
2182
2183/*
drh895d7472004-08-20 16:02:39 +00002184** Usage: sqlite3_bind_parameter_name STMT N
2185**
2186** Return the name of the Nth wildcard. The first wildcard is 1.
2187** An empty string is returned if N is out of range or if the wildcard
2188** is nameless.
2189*/
2190static int test_bind_parameter_name(
2191 void * clientData,
2192 Tcl_Interp *interp,
2193 int objc,
2194 Tcl_Obj *CONST objv[]
2195){
2196 sqlite3_stmt *pStmt;
2197 int i;
2198
2199 if( objc!=3 ){
2200 Tcl_WrongNumArgs(interp, 1, objv, "STMT N");
2201 return TCL_ERROR;
2202 }
2203 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2204 if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR;
2205 Tcl_SetObjResult(interp,
2206 Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1)
2207 );
2208 return TCL_OK;
2209}
2210
2211/*
drhfa6bc002004-09-07 16:19:52 +00002212** Usage: sqlite3_bind_parameter_index STMT NAME
2213**
2214** Return the index of the wildcard called NAME. Return 0 if there is
2215** no such wildcard.
2216*/
2217static int test_bind_parameter_index(
2218 void * clientData,
2219 Tcl_Interp *interp,
2220 int objc,
2221 Tcl_Obj *CONST objv[]
2222){
2223 sqlite3_stmt *pStmt;
2224
2225 if( objc!=3 ){
2226 Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME");
2227 return TCL_ERROR;
2228 }
2229 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2230 Tcl_SetObjResult(interp,
2231 Tcl_NewIntObj(
2232 sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2]))
2233 )
2234 );
2235 return TCL_OK;
2236}
2237
2238/*
danielk1977600dd0b2005-01-20 01:14:23 +00002239** Usage: sqlite3_clear_bindings STMT
2240**
2241*/
2242#if 0
2243static int test_clear_bindings(
2244 void * clientData,
2245 Tcl_Interp *interp,
2246 int objc,
2247 Tcl_Obj *CONST objv[]
2248){
2249 sqlite3_stmt *pStmt;
2250
2251 if( objc!=2 ){
2252 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
2253 return TCL_ERROR;
2254 }
2255 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2256 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt)));
2257 return TCL_OK;
2258}
2259#endif
2260
2261/*
danielk19776622cce2004-05-20 11:00:52 +00002262** Usage: sqlite3_errcode DB
2263**
2264** Return the string representation of the most recent sqlite3_* API
2265** error code. e.g. "SQLITE_ERROR".
2266*/
2267static int test_errcode(
2268 void * clientData,
2269 Tcl_Interp *interp,
2270 int objc,
2271 Tcl_Obj *CONST objv[]
2272){
2273 sqlite3 *db;
2274
2275 if( objc!=2 ){
2276 Tcl_AppendResult(interp, "wrong # args: should be \"",
2277 Tcl_GetString(objv[0]), " DB", 0);
2278 return TCL_ERROR;
2279 }
2280 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2281 Tcl_SetResult(interp, (char *)errorName(sqlite3_errcode(db)), 0);
2282 return TCL_OK;
2283}
2284
2285/*
2286** Usage: test_errmsg DB
2287**
2288** Returns the UTF-8 representation of the error message string for the
2289** most recent sqlite3_* API call.
2290*/
2291static int test_errmsg(
2292 void * clientData,
2293 Tcl_Interp *interp,
2294 int objc,
2295 Tcl_Obj *CONST objv[]
2296){
drh9bb575f2004-09-06 17:24:11 +00002297 sqlite3 *db;
danielk19776622cce2004-05-20 11:00:52 +00002298 const char *zErr;
2299
2300 if( objc!=2 ){
2301 Tcl_AppendResult(interp, "wrong # args: should be \"",
2302 Tcl_GetString(objv[0]), " DB", 0);
2303 return TCL_ERROR;
2304 }
2305 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2306
2307 zErr = sqlite3_errmsg(db);
2308 Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
2309 return TCL_OK;
2310}
2311
2312/*
2313** Usage: test_errmsg16 DB
2314**
2315** Returns the UTF-16 representation of the error message string for the
2316** most recent sqlite3_* API call. This is a byte array object at the TCL
2317** level, and it includes the 0x00 0x00 terminator bytes at the end of the
2318** UTF-16 string.
2319*/
2320static int test_errmsg16(
2321 void * clientData,
2322 Tcl_Interp *interp,
2323 int objc,
2324 Tcl_Obj *CONST objv[]
2325){
drh5436dc22004-11-14 04:04:17 +00002326#ifndef SQLITE_OMIT_UTF16
drh9bb575f2004-09-06 17:24:11 +00002327 sqlite3 *db;
danielk19776622cce2004-05-20 11:00:52 +00002328 const void *zErr;
danielk1977950f0542006-01-18 05:51:57 +00002329 int bytes = 0;
danielk19776622cce2004-05-20 11:00:52 +00002330
2331 if( objc!=2 ){
2332 Tcl_AppendResult(interp, "wrong # args: should be \"",
2333 Tcl_GetString(objv[0]), " DB", 0);
2334 return TCL_ERROR;
2335 }
2336 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2337
2338 zErr = sqlite3_errmsg16(db);
danielk1977950f0542006-01-18 05:51:57 +00002339 if( zErr ){
2340 bytes = sqlite3utf16ByteLen(zErr, -1);
2341 }
danielk19776622cce2004-05-20 11:00:52 +00002342 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes));
drh5436dc22004-11-14 04:04:17 +00002343#endif /* SQLITE_OMIT_UTF16 */
danielk19776622cce2004-05-20 11:00:52 +00002344 return TCL_OK;
2345}
2346
2347/*
2348** Usage: sqlite3_prepare DB sql bytes tailvar
2349**
2350** Compile up to <bytes> bytes of the supplied SQL string <sql> using
2351** database handle <DB>. The parameter <tailval> is the name of a global
2352** variable that is set to the unused portion of <sql> (if any). A
2353** STMT handle is returned.
2354*/
2355static int test_prepare(
2356 void * clientData,
2357 Tcl_Interp *interp,
2358 int objc,
2359 Tcl_Obj *CONST objv[]
2360){
2361 sqlite3 *db;
2362 const char *zSql;
2363 int bytes;
2364 const char *zTail = 0;
2365 sqlite3_stmt *pStmt = 0;
2366 char zBuf[50];
danielk19774ad17132004-05-21 01:47:26 +00002367 int rc;
danielk19776622cce2004-05-20 11:00:52 +00002368
2369 if( objc!=5 ){
2370 Tcl_AppendResult(interp, "wrong # args: should be \"",
2371 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
2372 return TCL_ERROR;
2373 }
2374 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2375 zSql = Tcl_GetString(objv[2]);
2376 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
2377
danielk19774ad17132004-05-21 01:47:26 +00002378 rc = sqlite3_prepare(db, zSql, bytes, &pStmt, &zTail);
drhc60d0442004-09-30 13:43:13 +00002379 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk19776622cce2004-05-20 11:00:52 +00002380 if( zTail ){
2381 if( bytes>=0 ){
2382 bytes = bytes - (zTail-zSql);
2383 }
2384 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
2385 }
danielk19774ad17132004-05-21 01:47:26 +00002386 if( rc!=SQLITE_OK ){
2387 assert( pStmt==0 );
2388 sprintf(zBuf, "(%d) ", rc);
2389 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
2390 return TCL_ERROR;
2391 }
danielk19776622cce2004-05-20 11:00:52 +00002392
danielk19774ad17132004-05-21 01:47:26 +00002393 if( pStmt ){
drh64b1bea2006-01-15 02:30:57 +00002394 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
danielk19774ad17132004-05-21 01:47:26 +00002395 Tcl_AppendResult(interp, zBuf, 0);
2396 }
danielk19776622cce2004-05-20 11:00:52 +00002397 return TCL_OK;
2398}
2399
2400/*
2401** Usage: sqlite3_prepare DB sql bytes tailvar
2402**
2403** Compile up to <bytes> bytes of the supplied SQL string <sql> using
2404** database handle <DB>. The parameter <tailval> is the name of a global
2405** variable that is set to the unused portion of <sql> (if any). A
2406** STMT handle is returned.
2407*/
2408static int test_prepare16(
2409 void * clientData,
2410 Tcl_Interp *interp,
2411 int objc,
2412 Tcl_Obj *CONST objv[]
2413){
drh5436dc22004-11-14 04:04:17 +00002414#ifndef SQLITE_OMIT_UTF16
danielk19776622cce2004-05-20 11:00:52 +00002415 sqlite3 *db;
2416 const void *zSql;
2417 const void *zTail = 0;
2418 Tcl_Obj *pTail = 0;
2419 sqlite3_stmt *pStmt = 0;
drhc60d0442004-09-30 13:43:13 +00002420 char zBuf[50];
2421 int rc;
danielk19776622cce2004-05-20 11:00:52 +00002422 int bytes; /* The integer specified as arg 3 */
2423 int objlen; /* The byte-array length of arg 2 */
2424
2425 if( objc!=5 ){
2426 Tcl_AppendResult(interp, "wrong # args: should be \"",
2427 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
2428 return TCL_ERROR;
2429 }
2430 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
2431 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
2432 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
2433
drhc60d0442004-09-30 13:43:13 +00002434 rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, &zTail);
2435 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
2436 if( rc ){
danielk19776622cce2004-05-20 11:00:52 +00002437 return TCL_ERROR;
2438 }
2439
2440 if( zTail ){
2441 objlen = objlen - ((u8 *)zTail-(u8 *)zSql);
2442 }else{
2443 objlen = 0;
2444 }
2445 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
2446 Tcl_IncrRefCount(pTail);
2447 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
danielk19774ad17132004-05-21 01:47:26 +00002448 Tcl_DecrRefCount(pTail);
danielk19776622cce2004-05-20 11:00:52 +00002449
danielk19774ad17132004-05-21 01:47:26 +00002450 if( pStmt ){
drh64b1bea2006-01-15 02:30:57 +00002451 if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
danielk19774ad17132004-05-21 01:47:26 +00002452 }
danielk19776622cce2004-05-20 11:00:52 +00002453 Tcl_AppendResult(interp, zBuf, 0);
drh5436dc22004-11-14 04:04:17 +00002454#endif /* SQLITE_OMIT_UTF16 */
danielk19776622cce2004-05-20 11:00:52 +00002455 return TCL_OK;
2456}
2457
danielk19774ad17132004-05-21 01:47:26 +00002458/*
2459** Usage: sqlite3_open filename ?options-list?
2460*/
2461static int test_open(
2462 void * clientData,
2463 Tcl_Interp *interp,
2464 int objc,
2465 Tcl_Obj *CONST objv[]
2466){
2467 const char *zFilename;
2468 sqlite3 *db;
2469 int rc;
2470 char zBuf[100];
2471
2472 if( objc!=3 && objc!=2 ){
2473 Tcl_AppendResult(interp, "wrong # args: should be \"",
2474 Tcl_GetString(objv[0]), " filename options-list", 0);
2475 return TCL_ERROR;
2476 }
2477
2478 zFilename = Tcl_GetString(objv[1]);
danielk19774f057f92004-06-08 00:02:33 +00002479 rc = sqlite3_open(zFilename, &db);
danielk19774ad17132004-05-21 01:47:26 +00002480
drh64b1bea2006-01-15 02:30:57 +00002481 if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
danielk19774ad17132004-05-21 01:47:26 +00002482 Tcl_AppendResult(interp, zBuf, 0);
2483 return TCL_OK;
2484}
2485
2486/*
2487** Usage: sqlite3_open16 filename options
2488*/
2489static int test_open16(
2490 void * clientData,
2491 Tcl_Interp *interp,
2492 int objc,
2493 Tcl_Obj *CONST objv[]
2494){
drh5436dc22004-11-14 04:04:17 +00002495#ifndef SQLITE_OMIT_UTF16
danielk19774ad17132004-05-21 01:47:26 +00002496 const void *zFilename;
2497 sqlite3 *db;
2498 int rc;
2499 char zBuf[100];
2500
2501 if( objc!=3 ){
2502 Tcl_AppendResult(interp, "wrong # args: should be \"",
2503 Tcl_GetString(objv[0]), " filename options-list", 0);
2504 return TCL_ERROR;
2505 }
2506
2507 zFilename = Tcl_GetByteArrayFromObj(objv[1], 0);
danielk19774f057f92004-06-08 00:02:33 +00002508 rc = sqlite3_open16(zFilename, &db);
danielk19774ad17132004-05-21 01:47:26 +00002509
drh64b1bea2006-01-15 02:30:57 +00002510 if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
danielk19774ad17132004-05-21 01:47:26 +00002511 Tcl_AppendResult(interp, zBuf, 0);
drh5436dc22004-11-14 04:04:17 +00002512#endif /* SQLITE_OMIT_UTF16 */
danielk19774ad17132004-05-21 01:47:26 +00002513 return TCL_OK;
2514}
drhd3d39e92004-05-20 22:16:29 +00002515
2516/*
danielk1977bc6ada42004-06-30 08:20:16 +00002517** Usage: sqlite3_complete16 <UTF-16 string>
2518**
2519** Return 1 if the supplied argument is a complete SQL statement, or zero
2520** otherwise.
2521*/
2522static int test_complete16(
2523 void * clientData,
2524 Tcl_Interp *interp,
2525 int objc,
2526 Tcl_Obj *CONST objv[]
2527){
drhccae6022005-02-26 17:31:26 +00002528#if !defined(SQLITE_OMIT_COMPLETE) && !defined(SQLITE_OMIT_UTF16)
danielk1977bc6ada42004-06-30 08:20:16 +00002529 char *zBuf;
2530
2531 if( objc!=2 ){
2532 Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>");
2533 return TCL_ERROR;
2534 }
2535
drh03d847e2005-12-09 20:21:58 +00002536 zBuf = (char*)Tcl_GetByteArrayFromObj(objv[1], 0);
danielk1977bc6ada42004-06-30 08:20:16 +00002537 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf)));
drhccae6022005-02-26 17:31:26 +00002538#endif /* SQLITE_OMIT_COMPLETE && SQLITE_OMIT_UTF16 */
danielk1977bc6ada42004-06-30 08:20:16 +00002539 return TCL_OK;
2540}
2541
2542/*
danielk1977106bb232004-05-21 10:08:53 +00002543** Usage: sqlite3_step STMT
2544**
2545** Advance the statement to the next row.
2546*/
danielk197717240fd2004-05-26 00:07:25 +00002547static int test_step(
danielk1977106bb232004-05-21 10:08:53 +00002548 void * clientData,
2549 Tcl_Interp *interp,
2550 int objc,
2551 Tcl_Obj *CONST objv[]
2552){
2553 sqlite3_stmt *pStmt;
2554 int rc;
2555
danielk1977e1cd9872004-05-22 10:33:04 +00002556 if( objc!=2 ){
danielk1977106bb232004-05-21 10:08:53 +00002557 Tcl_AppendResult(interp, "wrong # args: should be \"",
2558 Tcl_GetString(objv[0]), " STMT", 0);
2559 return TCL_ERROR;
2560 }
2561
2562 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
danielk197717240fd2004-05-26 00:07:25 +00002563 rc = sqlite3_step(pStmt);
danielk1977106bb232004-05-21 10:08:53 +00002564
danielk1977fbcd5852004-06-15 02:44:18 +00002565 /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */
danielk197765904932004-05-26 06:18:37 +00002566 Tcl_SetResult(interp, (char *)errorName(rc), 0);
danielk1977e1cd9872004-05-22 10:33:04 +00002567 return TCL_OK;
2568}
2569
2570/*
danielk197717240fd2004-05-26 00:07:25 +00002571** Usage: sqlite3_column_count STMT
2572**
2573** Return the number of columns returned by the sql statement STMT.
2574*/
2575static int test_column_count(
2576 void * clientData,
2577 Tcl_Interp *interp,
2578 int objc,
2579 Tcl_Obj *CONST objv[]
2580){
2581 sqlite3_stmt *pStmt;
2582
2583 if( objc!=2 ){
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
2591 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt)));
2592 return TCL_OK;
2593}
2594
2595/*
danielk19773cf86062004-05-26 10:11:05 +00002596** Usage: sqlite3_column_type STMT column
2597**
2598** Return the type of the data in column 'column' of the current row.
2599*/
2600static int test_column_type(
2601 void * clientData,
2602 Tcl_Interp *interp,
2603 int objc,
2604 Tcl_Obj *CONST objv[]
2605){
2606 sqlite3_stmt *pStmt;
2607 int col;
2608 int tp;
2609
2610 if( objc!=3 ){
2611 Tcl_AppendResult(interp, "wrong # args: should be \"",
2612 Tcl_GetString(objv[0]), " STMT column", 0);
2613 return TCL_ERROR;
2614 }
2615
2616 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2617 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2618
2619 tp = sqlite3_column_type(pStmt, col);
2620 switch( tp ){
drh9c054832004-05-31 18:51:57 +00002621 case SQLITE_INTEGER:
danielk19773cf86062004-05-26 10:11:05 +00002622 Tcl_SetResult(interp, "INTEGER", TCL_STATIC);
2623 break;
drh9c054832004-05-31 18:51:57 +00002624 case SQLITE_NULL:
danielk19773cf86062004-05-26 10:11:05 +00002625 Tcl_SetResult(interp, "NULL", TCL_STATIC);
2626 break;
drh9c054832004-05-31 18:51:57 +00002627 case SQLITE_FLOAT:
danielk19773cf86062004-05-26 10:11:05 +00002628 Tcl_SetResult(interp, "FLOAT", TCL_STATIC);
2629 break;
drh9c054832004-05-31 18:51:57 +00002630 case SQLITE_TEXT:
danielk19773cf86062004-05-26 10:11:05 +00002631 Tcl_SetResult(interp, "TEXT", TCL_STATIC);
2632 break;
drh9c054832004-05-31 18:51:57 +00002633 case SQLITE_BLOB:
danielk19773cf86062004-05-26 10:11:05 +00002634 Tcl_SetResult(interp, "BLOB", TCL_STATIC);
2635 break;
2636 default:
2637 assert(0);
2638 }
2639
2640 return TCL_OK;
2641}
2642
2643/*
danielk197704f2e682004-05-27 01:04:07 +00002644** Usage: sqlite3_column_int64 STMT column
danielk19773cf86062004-05-26 10:11:05 +00002645**
2646** Return the data in column 'column' of the current row cast as an
danielk197704f2e682004-05-27 01:04:07 +00002647** wide (64-bit) integer.
danielk19773cf86062004-05-26 10:11:05 +00002648*/
danielk197704f2e682004-05-27 01:04:07 +00002649static int test_column_int64(
danielk19773cf86062004-05-26 10:11:05 +00002650 void * clientData,
2651 Tcl_Interp *interp,
2652 int objc,
2653 Tcl_Obj *CONST objv[]
2654){
2655 sqlite3_stmt *pStmt;
2656 int col;
danielk197704f2e682004-05-27 01:04:07 +00002657 i64 iVal;
danielk19773cf86062004-05-26 10:11:05 +00002658
2659 if( objc!=3 ){
2660 Tcl_AppendResult(interp, "wrong # args: should be \"",
2661 Tcl_GetString(objv[0]), " STMT column", 0);
2662 return TCL_ERROR;
2663 }
2664
2665 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2666 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2667
danielk197704f2e682004-05-27 01:04:07 +00002668 iVal = sqlite3_column_int64(pStmt, col);
2669 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal));
2670 return TCL_OK;
2671}
2672
2673/*
danielk1977ea61b2c2004-05-27 01:49:51 +00002674** Usage: sqlite3_column_blob STMT column
2675*/
2676static int test_column_blob(
2677 void * clientData,
2678 Tcl_Interp *interp,
2679 int objc,
2680 Tcl_Obj *CONST objv[]
2681){
2682 sqlite3_stmt *pStmt;
2683 int col;
2684
2685 int len;
danielk1977c572ef72004-05-27 09:28:41 +00002686 const void *pBlob;
danielk1977ea61b2c2004-05-27 01:49:51 +00002687
2688 if( objc!=3 ){
2689 Tcl_AppendResult(interp, "wrong # args: should be \"",
2690 Tcl_GetString(objv[0]), " STMT column", 0);
2691 return TCL_ERROR;
2692 }
2693
2694 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2695 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2696
2697 pBlob = sqlite3_column_blob(pStmt, col);
2698 len = sqlite3_column_bytes(pStmt, col);
2699 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len));
2700 return TCL_OK;
2701}
2702
2703/*
danielk197704f2e682004-05-27 01:04:07 +00002704** Usage: sqlite3_column_double STMT column
2705**
2706** Return the data in column 'column' of the current row cast as a double.
2707*/
2708static int test_column_double(
2709 void * clientData,
2710 Tcl_Interp *interp,
2711 int objc,
2712 Tcl_Obj *CONST objv[]
2713){
2714 sqlite3_stmt *pStmt;
2715 int col;
2716 double rVal;
2717
2718 if( objc!=3 ){
2719 Tcl_AppendResult(interp, "wrong # args: should be \"",
2720 Tcl_GetString(objv[0]), " STMT column", 0);
2721 return TCL_ERROR;
2722 }
2723
2724 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2725 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2726
2727 rVal = sqlite3_column_double(pStmt, col);
danielk1977c572ef72004-05-27 09:28:41 +00002728 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal));
danielk19773cf86062004-05-26 10:11:05 +00002729 return TCL_OK;
2730}
2731
2732/*
danielk197717240fd2004-05-26 00:07:25 +00002733** Usage: sqlite3_data_count STMT
2734**
2735** Return the number of columns returned by the sql statement STMT.
2736*/
2737static int test_data_count(
2738 void * clientData,
2739 Tcl_Interp *interp,
2740 int objc,
2741 Tcl_Obj *CONST objv[]
2742){
2743 sqlite3_stmt *pStmt;
2744
2745 if( objc!=2 ){
2746 Tcl_AppendResult(interp, "wrong # args: should be \"",
2747 Tcl_GetString(objv[0]), " STMT column", 0);
2748 return TCL_ERROR;
2749 }
2750
2751 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2752
2753 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt)));
2754 return TCL_OK;
2755}
2756
2757/*
danielk197704f2e682004-05-27 01:04:07 +00002758** Usage: sqlite3_column_text STMT column
2759**
2760** Usage: sqlite3_column_decltype STMT column
2761**
2762** Usage: sqlite3_column_name STMT column
2763*/
2764static int test_stmt_utf8(
drh241db312004-06-22 12:46:53 +00002765 void * clientData, /* Pointer to SQLite API function to be invoke */
danielk197704f2e682004-05-27 01:04:07 +00002766 Tcl_Interp *interp,
2767 int objc,
2768 Tcl_Obj *CONST objv[]
2769){
2770 sqlite3_stmt *pStmt;
2771 int col;
danielk1977c572ef72004-05-27 09:28:41 +00002772 const char *(*xFunc)(sqlite3_stmt*, int) = clientData;
danielk1977f93bbbe2004-05-27 10:30:52 +00002773 const char *zRet;
danielk197704f2e682004-05-27 01:04:07 +00002774
2775 if( objc!=3 ){
2776 Tcl_AppendResult(interp, "wrong # args: should be \"",
2777 Tcl_GetString(objv[0]), " STMT column", 0);
2778 return TCL_ERROR;
2779 }
2780
2781 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2782 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
danielk1977f93bbbe2004-05-27 10:30:52 +00002783 zRet = xFunc(pStmt, col);
2784 if( zRet ){
2785 Tcl_SetResult(interp, (char *)zRet, 0);
2786 }
danielk197704f2e682004-05-27 01:04:07 +00002787 return TCL_OK;
2788}
2789
danielk19776b456a22005-03-21 04:04:02 +00002790static int test_global_recover(
2791 void * clientData,
2792 Tcl_Interp *interp,
2793 int objc,
2794 Tcl_Obj *CONST objv[]
2795){
2796#ifndef SQLITE_OMIT_GLOBALRECOVER
2797 int rc;
2798 if( objc!=1 ){
2799 Tcl_WrongNumArgs(interp, 1, objv, "");
2800 return TCL_ERROR;
2801 }
2802 rc = sqlite3_global_recover();
2803 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2804#endif
2805 return TCL_OK;
2806}
2807
danielk197704f2e682004-05-27 01:04:07 +00002808/*
2809** Usage: sqlite3_column_text STMT column
2810**
2811** Usage: sqlite3_column_decltype STMT column
2812**
2813** Usage: sqlite3_column_name STMT column
2814*/
2815static int test_stmt_utf16(
drh241db312004-06-22 12:46:53 +00002816 void * clientData, /* Pointer to SQLite API function to be invoked */
danielk197704f2e682004-05-27 01:04:07 +00002817 Tcl_Interp *interp,
2818 int objc,
2819 Tcl_Obj *CONST objv[]
2820){
drh5436dc22004-11-14 04:04:17 +00002821#ifndef SQLITE_OMIT_UTF16
danielk197704f2e682004-05-27 01:04:07 +00002822 sqlite3_stmt *pStmt;
2823 int col;
2824 Tcl_Obj *pRet;
2825 const void *zName16;
danielk1977c572ef72004-05-27 09:28:41 +00002826 const void *(*xFunc)(sqlite3_stmt*, int) = clientData;
danielk197704f2e682004-05-27 01:04:07 +00002827
2828 if( objc!=3 ){
2829 Tcl_AppendResult(interp, "wrong # args: should be \"",
2830 Tcl_GetString(objv[0]), " STMT column", 0);
2831 return TCL_ERROR;
2832 }
2833
2834 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2835 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2836
2837 zName16 = xFunc(pStmt, col);
danielk1977f93bbbe2004-05-27 10:30:52 +00002838 if( zName16 ){
2839 pRet = Tcl_NewByteArrayObj(zName16, sqlite3utf16ByteLen(zName16, -1)+2);
2840 Tcl_SetObjResult(interp, pRet);
2841 }
drh5436dc22004-11-14 04:04:17 +00002842#endif /* SQLITE_OMIT_UTF16 */
danielk197704f2e682004-05-27 01:04:07 +00002843
2844 return TCL_OK;
2845}
2846
2847/*
2848** Usage: sqlite3_column_int STMT column
2849**
2850** Usage: sqlite3_column_bytes STMT column
2851**
2852** Usage: sqlite3_column_bytes16 STMT column
2853**
2854*/
2855static int test_stmt_int(
drh241db312004-06-22 12:46:53 +00002856 void * clientData, /* Pointer to SQLite API function to be invoked */
danielk197704f2e682004-05-27 01:04:07 +00002857 Tcl_Interp *interp,
2858 int objc,
2859 Tcl_Obj *CONST objv[]
2860){
2861 sqlite3_stmt *pStmt;
2862 int col;
danielk1977c572ef72004-05-27 09:28:41 +00002863 int (*xFunc)(sqlite3_stmt*, int) = clientData;
danielk197704f2e682004-05-27 01:04:07 +00002864
2865 if( objc!=3 ){
2866 Tcl_AppendResult(interp, "wrong # args: should be \"",
2867 Tcl_GetString(objv[0]), " STMT column", 0);
2868 return TCL_ERROR;
2869 }
2870
2871 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2872 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2873
2874 Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col)));
2875 return TCL_OK;
2876}
2877
danielk197744ee5bf2005-05-27 09:41:12 +00002878#ifndef SQLITE_OMIT_DISKIO
danielk19779a1d0ab2004-06-01 14:09:28 +00002879/*
2880** Usage: sqlite3OsOpenReadWrite <filename>
2881*/
2882static int test_sqlite3OsOpenReadWrite(
2883 void * clientData,
2884 Tcl_Interp *interp,
2885 int objc,
2886 Tcl_Obj *CONST objv[]
2887){
drh9cbe6352005-11-29 03:13:21 +00002888 OsFile *pFile;
danielk19779a1d0ab2004-06-01 14:09:28 +00002889 int rc;
2890 int dummy;
2891 char zBuf[100];
danielk197704f2e682004-05-27 01:04:07 +00002892
danielk19779a1d0ab2004-06-01 14:09:28 +00002893 if( objc!=2 ){
2894 Tcl_AppendResult(interp, "wrong # args: should be \"",
2895 Tcl_GetString(objv[0]), " filename", 0);
2896 return TCL_ERROR;
2897 }
2898
drh66560ad2006-01-06 14:32:19 +00002899 rc = sqlite3OsOpenReadWrite(Tcl_GetString(objv[1]), &pFile, &dummy);
danielk19779a1d0ab2004-06-01 14:09:28 +00002900 if( rc!=SQLITE_OK ){
danielk19779a1d0ab2004-06-01 14:09:28 +00002901 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2902 return TCL_ERROR;
2903 }
drh64b1bea2006-01-15 02:30:57 +00002904 sqlite3TestMakePointerStr(interp, zBuf, pFile);
danielk19779a1d0ab2004-06-01 14:09:28 +00002905 Tcl_SetResult(interp, zBuf, 0);
2906 return TCL_ERROR;
2907}
2908
2909/*
2910** Usage: sqlite3OsClose <file handle>
2911*/
2912static int test_sqlite3OsClose(
2913 void * clientData,
2914 Tcl_Interp *interp,
2915 int objc,
2916 Tcl_Obj *CONST objv[]
2917){
drh9cbe6352005-11-29 03:13:21 +00002918 OsFile *pFile;
danielk19779a1d0ab2004-06-01 14:09:28 +00002919 int rc;
2920
2921 if( objc!=2 ){
2922 Tcl_AppendResult(interp, "wrong # args: should be \"",
2923 Tcl_GetString(objv[0]), " filehandle", 0);
2924 return TCL_ERROR;
2925 }
2926
2927 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
2928 return TCL_ERROR;
2929 }
drh054889e2005-11-30 03:20:31 +00002930 rc = sqlite3OsClose(&pFile);
danielk19779a1d0ab2004-06-01 14:09:28 +00002931 if( rc!=SQLITE_OK ){
2932 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2933 return TCL_ERROR;
2934 }
danielk19779a1d0ab2004-06-01 14:09:28 +00002935 return TCL_OK;
2936}
2937
2938/*
2939** Usage: sqlite3OsLock <file handle> <locktype>
2940*/
2941static int test_sqlite3OsLock(
2942 void * clientData,
2943 Tcl_Interp *interp,
2944 int objc,
2945 Tcl_Obj *CONST objv[]
2946){
2947 OsFile * pFile;
2948 int rc;
2949
2950 if( objc!=3 ){
2951 Tcl_AppendResult(interp, "wrong # args: should be \"",
2952 Tcl_GetString(objv[0]),
2953 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
2954 return TCL_ERROR;
2955 }
2956
2957 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
2958 return TCL_ERROR;
2959 }
2960
2961 if( 0==strcmp("SHARED", Tcl_GetString(objv[2])) ){
drh054889e2005-11-30 03:20:31 +00002962 rc = sqlite3OsLock(pFile, SHARED_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00002963 }
2964 else if( 0==strcmp("RESERVED", Tcl_GetString(objv[2])) ){
drh054889e2005-11-30 03:20:31 +00002965 rc = sqlite3OsLock(pFile, RESERVED_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00002966 }
2967 else if( 0==strcmp("PENDING", Tcl_GetString(objv[2])) ){
drh054889e2005-11-30 03:20:31 +00002968 rc = sqlite3OsLock(pFile, PENDING_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00002969 }
2970 else if( 0==strcmp("EXCLUSIVE", Tcl_GetString(objv[2])) ){
drh054889e2005-11-30 03:20:31 +00002971 rc = sqlite3OsLock(pFile, EXCLUSIVE_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00002972 }else{
2973 Tcl_AppendResult(interp, "wrong # args: should be \"",
2974 Tcl_GetString(objv[0]),
2975 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
2976 return TCL_ERROR;
2977 }
2978
2979 if( rc!=SQLITE_OK ){
2980 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2981 return TCL_ERROR;
2982 }
2983 return TCL_OK;
2984}
2985
2986/*
2987** Usage: sqlite3OsUnlock <file handle>
2988*/
2989static int test_sqlite3OsUnlock(
2990 void * clientData,
2991 Tcl_Interp *interp,
2992 int objc,
2993 Tcl_Obj *CONST objv[]
2994){
2995 OsFile * pFile;
2996 int rc;
2997
2998 if( objc!=2 ){
2999 Tcl_AppendResult(interp, "wrong # args: should be \"",
3000 Tcl_GetString(objv[0]), " filehandle", 0);
3001 return TCL_ERROR;
3002 }
3003
3004 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
3005 return TCL_ERROR;
3006 }
drh054889e2005-11-30 03:20:31 +00003007 rc = sqlite3OsUnlock(pFile, NO_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00003008 if( rc!=SQLITE_OK ){
3009 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
3010 return TCL_ERROR;
3011 }
3012 return TCL_OK;
3013}
drhd3d39e92004-05-20 22:16:29 +00003014
drhab3f9fe2004-08-14 17:10:10 +00003015/*
3016** Usage: sqlite3OsTempFileName
3017*/
3018static int test_sqlite3OsTempFileName(
3019 void * clientData,
3020 Tcl_Interp *interp,
3021 int objc,
3022 Tcl_Obj *CONST objv[]
3023){
3024 char zFile[SQLITE_TEMPNAME_SIZE];
3025 int rc;
3026
drh66560ad2006-01-06 14:32:19 +00003027 rc = sqlite3OsTempFileName(zFile);
drhab3f9fe2004-08-14 17:10:10 +00003028 if( rc!=SQLITE_OK ){
3029 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
3030 return TCL_ERROR;
3031 }
3032 Tcl_AppendResult(interp, zFile, 0);
3033 return TCL_OK;
3034}
danielk197744ee5bf2005-05-27 09:41:12 +00003035#endif
danielk1977d8123362004-06-12 09:25:12 +00003036
danielk19776622cce2004-05-20 11:00:52 +00003037/*
drhcacb2082005-01-11 15:28:33 +00003038** Usage: sqlite_set_magic DB MAGIC-NUMBER
3039**
3040** Set the db->magic value. This is used to test error recovery logic.
3041*/
3042static int sqlite_set_magic(
3043 void * clientData,
3044 Tcl_Interp *interp,
3045 int argc,
3046 char **argv
3047){
3048 sqlite3 *db;
3049 if( argc!=3 ){
3050 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
3051 " DB MAGIC", 0);
3052 return TCL_ERROR;
3053 }
3054 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
3055 if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){
3056 db->magic = SQLITE_MAGIC_OPEN;
3057 }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){
3058 db->magic = SQLITE_MAGIC_CLOSED;
3059 }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){
3060 db->magic = SQLITE_MAGIC_BUSY;
3061 }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){
3062 db->magic = SQLITE_MAGIC_ERROR;
3063 }else if( Tcl_GetInt(interp, argv[2], &db->magic) ){
3064 return TCL_ERROR;
3065 }
3066 return TCL_OK;
3067}
3068
3069/*
drhc5cdca62005-01-11 16:54:14 +00003070** Usage: sqlite3_interrupt DB
3071**
3072** Trigger an interrupt on DB
3073*/
3074static int test_interrupt(
3075 void * clientData,
3076 Tcl_Interp *interp,
3077 int argc,
3078 char **argv
3079){
3080 sqlite3 *db;
3081 if( argc!=2 ){
3082 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
3083 return TCL_ERROR;
3084 }
3085 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
3086 sqlite3_interrupt(db);
3087 return TCL_OK;
3088}
3089
drh79158e12005-09-06 21:40:45 +00003090static u8 *sqlite3_stack_baseline = 0;
3091
drhc5cdca62005-01-11 16:54:14 +00003092/*
drh79158e12005-09-06 21:40:45 +00003093** Fill the stack with a known bitpattern.
danielk1977600dd0b2005-01-20 01:14:23 +00003094*/
drh79158e12005-09-06 21:40:45 +00003095static void prepStack(void){
3096 int i;
3097 u32 bigBuf[65536];
3098 for(i=0; i<sizeof(bigBuf); i++) bigBuf[i] = 0xdeadbeef;
3099 sqlite3_stack_baseline = (u8*)&bigBuf[65536];
3100}
3101
3102/*
3103** Get the current stack depth. Used for debugging only.
3104*/
3105u64 sqlite3StackDepth(void){
3106 u8 x;
3107 return (u64)(sqlite3_stack_baseline - &x);
3108}
3109
3110/*
3111** Usage: sqlite3_stack_used DB SQL
3112**
3113** Try to measure the amount of stack space used by a call to sqlite3_exec
3114*/
3115static int test_stack_used(
danielk1977600dd0b2005-01-20 01:14:23 +00003116 void * clientData,
3117 Tcl_Interp *interp,
3118 int argc,
3119 char **argv
3120){
3121 sqlite3 *db;
drh79158e12005-09-06 21:40:45 +00003122 int i;
3123 if( argc!=3 ){
3124 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
3125 " DB SQL", 0);
danielk1977600dd0b2005-01-20 01:14:23 +00003126 return TCL_ERROR;
3127 }
drh79158e12005-09-06 21:40:45 +00003128 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
3129 prepStack();
drh37527852006-03-16 16:19:56 +00003130 (void)sqlite3_exec(db, argv[2], 0, 0, 0);
drh79158e12005-09-06 21:40:45 +00003131 for(i=65535; i>=0 && ((u32*)sqlite3_stack_baseline)[-i]==0xdeadbeef; i--){}
3132 Tcl_SetObjResult(interp, Tcl_NewIntObj(i*4));
danielk1977600dd0b2005-01-20 01:14:23 +00003133 return TCL_OK;
3134}
danielk1977600dd0b2005-01-20 01:14:23 +00003135
3136/*
danielk19779636c4e2005-01-25 04:27:54 +00003137** Usage: sqlite_delete_function DB function-name
3138**
3139** Delete the user function 'function-name' from database handle DB. It
3140** is assumed that the user function was created as UTF8, any number of
3141** arguments (the way the TCL interface does it).
3142*/
3143static int delete_function(
3144 void * clientData,
3145 Tcl_Interp *interp,
3146 int argc,
3147 char **argv
3148){
3149 int rc;
3150 sqlite3 *db;
3151 if( argc!=3 ){
3152 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
3153 " DB function-name", 0);
3154 return TCL_ERROR;
3155 }
3156 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
3157 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0);
3158 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
3159 return TCL_OK;
3160}
3161
3162/*
3163** Usage: sqlite_delete_collation DB collation-name
3164**
3165** Delete the collation sequence 'collation-name' from database handle
3166** DB. It is assumed that the collation sequence was created as UTF8 (the
3167** way the TCL interface does it).
3168*/
3169static int delete_collation(
3170 void * clientData,
3171 Tcl_Interp *interp,
3172 int argc,
3173 char **argv
3174){
3175 int rc;
3176 sqlite3 *db;
3177 if( argc!=3 ){
3178 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
3179 " DB function-name", 0);
3180 return TCL_ERROR;
3181 }
3182 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
3183 rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0);
3184 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
3185 return TCL_OK;
3186}
3187
3188/*
drh3e1d8e62005-05-26 16:23:34 +00003189** Usage: sqlite3_get_autocommit DB
3190**
3191** Return true if the database DB is currently in auto-commit mode.
3192** Return false if not.
3193*/
3194static int get_autocommit(
3195 void * clientData,
3196 Tcl_Interp *interp,
3197 int argc,
3198 char **argv
3199){
3200 char zBuf[30];
3201 sqlite3 *db;
3202 if( argc!=2 ){
3203 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
3204 " DB", 0);
3205 return TCL_ERROR;
3206 }
3207 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
3208 sprintf(zBuf, "%d", sqlite3_get_autocommit(db));
3209 Tcl_AppendResult(interp, zBuf, 0);
3210 return TCL_OK;
3211}
3212
3213/*
drh92febd92004-08-20 18:34:20 +00003214** Usage: tcl_variable_type VARIABLENAME
3215**
3216** Return the name of the internal representation for the
3217** value of the given variable.
3218*/
3219static int tcl_variable_type(
3220 void * clientData,
3221 Tcl_Interp *interp,
3222 int objc,
3223 Tcl_Obj *CONST objv[]
3224){
3225 Tcl_Obj *pVar;
3226 if( objc!=2 ){
3227 Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE");
3228 return TCL_ERROR;
3229 }
3230 pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG);
3231 if( pVar==0 ) return TCL_ERROR;
3232 if( pVar->typePtr ){
3233 Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1));
3234 }
3235 return TCL_OK;
3236}
3237
3238/*
drh6aafc292006-01-05 15:50:06 +00003239** Usage: sqlite3_release_memory ?N?
3240**
3241** Attempt to release memory currently held but not actually required.
3242** The integer N is the number of bytes we are trying to release. The
3243** return value is the amount of memory actually released.
3244*/
3245static int test_release_memory(
3246 void * clientData,
3247 Tcl_Interp *interp,
3248 int objc,
3249 Tcl_Obj *CONST objv[]
3250){
drh6f7adc82006-01-11 21:41:20 +00003251#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
drh6aafc292006-01-05 15:50:06 +00003252 int N;
3253 int amt;
3254 if( objc!=1 && objc!=2 ){
3255 Tcl_WrongNumArgs(interp, 1, objv, "?N?");
3256 return TCL_ERROR;
3257 }
3258 if( objc==2 ){
3259 if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
3260 }else{
3261 N = -1;
3262 }
3263 amt = sqlite3_release_memory(N);
3264 Tcl_SetObjResult(interp, Tcl_NewIntObj(amt));
3265#endif
3266 return TCL_OK;
3267}
3268
3269/*
3270** Usage: sqlite3_soft_heap_limit ?N?
3271**
3272** Query or set the soft heap limit for the current thread. The
3273** limit is only changed if the N is present. The previous limit
3274** is returned.
3275*/
3276static int test_soft_heap_limit(
3277 void * clientData,
3278 Tcl_Interp *interp,
3279 int objc,
3280 Tcl_Obj *CONST objv[]
3281){
drh6f7adc82006-01-11 21:41:20 +00003282#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
drh6aafc292006-01-05 15:50:06 +00003283 int amt;
3284 if( objc!=1 && objc!=2 ){
3285 Tcl_WrongNumArgs(interp, 1, objv, "?N?");
3286 return TCL_ERROR;
3287 }
drh6f7adc82006-01-11 21:41:20 +00003288 amt = sqlite3ThreadDataReadOnly()->nSoftHeapLimit;
drh6aafc292006-01-05 15:50:06 +00003289 if( objc==2 ){
3290 int N;
3291 if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
3292 sqlite3_soft_heap_limit(N);
3293 }
3294 Tcl_SetObjResult(interp, Tcl_NewIntObj(amt));
3295#endif
3296 return TCL_OK;
3297}
3298
3299/*
drhb4bc7052006-01-11 23:40:33 +00003300** Usage: sqlite3_clear_tsd_memdebug
3301**
3302** Clear all of the MEMDEBUG information out of thread-specific data.
3303** This will allow it to be deallocated.
3304*/
3305static int test_clear_tsd_memdebug(
3306 void * clientData,
3307 Tcl_Interp *interp,
3308 int objc,
3309 Tcl_Obj *CONST objv[]
3310){
drhb4bc7052006-01-11 23:40:33 +00003311 return TCL_OK;
3312}
3313
3314/*
3315** Usage: sqlite3_tsd_release
3316**
3317** Call sqlite3ReleaseThreadData.
3318*/
3319static int test_tsd_release(
3320 void * clientData,
3321 Tcl_Interp *interp,
3322 int objc,
3323 Tcl_Obj *CONST objv[]
3324){
3325#if defined(SQLITE_MEMDEBUG)
3326 sqlite3ReleaseThreadData();
3327#endif
3328 return TCL_OK;
3329}
3330
3331/*
3332** Usage: sqlite3_thread_cleanup
3333**
3334** Call the sqlite3_thread_cleanup API.
3335*/
3336static int test_thread_cleanup(
3337 void * clientData,
3338 Tcl_Interp *interp,
3339 int objc,
3340 Tcl_Obj *CONST objv[]
3341){
3342 sqlite3_thread_cleanup();
3343 return TCL_OK;
3344}
3345
3346
3347/*
drh27d258a2004-10-30 20:23:09 +00003348** This routine sets entries in the global ::sqlite_options() array variable
3349** according to the compile-time configuration of the database. Test
3350** procedures use this to determine when tests should be omitted.
3351*/
3352static void set_options(Tcl_Interp *interp){
drh75f86a42005-02-17 00:03:06 +00003353#ifdef SQLITE_32BIT_ROWID
3354 Tcl_SetVar2(interp, "sqlite_options", "rowid32", "1", TCL_GLOBAL_ONLY);
3355#else
3356 Tcl_SetVar2(interp, "sqlite_options", "rowid32", "0", TCL_GLOBAL_ONLY);
3357#endif
3358
drh9f18e8a2005-07-08 12:13:04 +00003359#ifdef SQLITE_CASE_SENSITIVE_LIKE
3360 Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","1",TCL_GLOBAL_ONLY);
3361#else
3362 Tcl_SetVar2(interp, "sqlite_options","casesensitivelike","0",TCL_GLOBAL_ONLY);
3363#endif
3364
danielk1977d7c03f72005-11-25 10:38:22 +00003365#ifdef SQLITE_DISABLE_DIRSYNC
3366 Tcl_SetVar2(interp, "sqlite_options", "dirsync", "0", TCL_GLOBAL_ONLY);
3367#else
3368 Tcl_SetVar2(interp, "sqlite_options", "dirsync", "1", TCL_GLOBAL_ONLY);
3369#endif
3370
danielk197726c5d792005-11-25 09:01:23 +00003371#ifdef SQLITE_DISABLE_LFS
3372 Tcl_SetVar2(interp, "sqlite_options", "lfs", "0", TCL_GLOBAL_ONLY);
3373#else
3374 Tcl_SetVar2(interp, "sqlite_options", "lfs", "1", TCL_GLOBAL_ONLY);
3375#endif
3376
danielk19771c8c23c2004-11-12 15:53:37 +00003377#ifdef SQLITE_OMIT_ALTERTABLE
3378 Tcl_SetVar2(interp, "sqlite_options", "altertable", "0", TCL_GLOBAL_ONLY);
3379#else
3380 Tcl_SetVar2(interp, "sqlite_options", "altertable", "1", TCL_GLOBAL_ONLY);
3381#endif
drh13d70422004-11-13 15:59:14 +00003382
drh9f18e8a2005-07-08 12:13:04 +00003383#ifdef SQLITE_OMIT_ANALYZE
3384 Tcl_SetVar2(interp, "sqlite_options", "analyze", "0", TCL_GLOBAL_ONLY);
3385#else
3386 Tcl_SetVar2(interp, "sqlite_options", "analyze", "1", TCL_GLOBAL_ONLY);
3387#endif
3388
drh13d70422004-11-13 15:59:14 +00003389#ifdef SQLITE_OMIT_AUTHORIZATION
3390 Tcl_SetVar2(interp, "sqlite_options", "auth", "0", TCL_GLOBAL_ONLY);
3391#else
3392 Tcl_SetVar2(interp, "sqlite_options", "auth", "1", TCL_GLOBAL_ONLY);
3393#endif
3394
drhf3388142004-11-13 03:48:06 +00003395#ifdef SQLITE_OMIT_AUTOINCREMENT
3396 Tcl_SetVar2(interp, "sqlite_options", "autoinc", "0", TCL_GLOBAL_ONLY);
3397#else
3398 Tcl_SetVar2(interp, "sqlite_options", "autoinc", "1", TCL_GLOBAL_ONLY);
3399#endif
3400
danielk197745901d62004-11-10 15:27:38 +00003401#ifdef SQLITE_OMIT_AUTOVACUUM
3402 Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "0", TCL_GLOBAL_ONLY);
3403#else
3404 Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "1", TCL_GLOBAL_ONLY);
drhf3388142004-11-13 03:48:06 +00003405#endif /* SQLITE_OMIT_AUTOVACUUM */
danielk19774d36b812004-11-19 07:07:30 +00003406#if !defined(SQLITE_DEFAULT_AUTOVACUUM) || SQLITE_DEFAULT_AUTOVACUUM==0
danielk197745901d62004-11-10 15:27:38 +00003407 Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","0",TCL_GLOBAL_ONLY);
3408#else
3409 Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","1",TCL_GLOBAL_ONLY);
3410#endif
drh13d70422004-11-13 15:59:14 +00003411
drh55ef4d92005-08-14 01:20:37 +00003412#ifdef SQLITE_OMIT_BETWEEN_OPTIMIZATION
3413 Tcl_SetVar2(interp, "sqlite_options", "between_opt", "0", TCL_GLOBAL_ONLY);
3414#else
3415 Tcl_SetVar2(interp, "sqlite_options", "between_opt", "1", TCL_GLOBAL_ONLY);
3416#endif
3417
drh13d70422004-11-13 15:59:14 +00003418#ifdef SQLITE_OMIT_BLOB_LITERAL
3419 Tcl_SetVar2(interp, "sqlite_options", "bloblit", "0", TCL_GLOBAL_ONLY);
3420#else
3421 Tcl_SetVar2(interp, "sqlite_options", "bloblit", "1", TCL_GLOBAL_ONLY);
3422#endif
3423
drh487e2622005-06-25 18:42:14 +00003424#ifdef SQLITE_OMIT_CAST
3425 Tcl_SetVar2(interp, "sqlite_options", "cast", "0", TCL_GLOBAL_ONLY);
3426#else
3427 Tcl_SetVar2(interp, "sqlite_options", "cast", "1", TCL_GLOBAL_ONLY);
3428#endif
3429
drhffe07b22005-11-03 00:41:17 +00003430#ifdef SQLITE_OMIT_CHECK
3431 Tcl_SetVar2(interp, "sqlite_options", "check", "0", TCL_GLOBAL_ONLY);
3432#else
3433 Tcl_SetVar2(interp, "sqlite_options", "check", "1", TCL_GLOBAL_ONLY);
3434#endif
3435
danielk1977deb802c2006-02-09 13:43:28 +00003436#ifdef SQLITE_ENABLE_COLUMN_METADATA
3437 Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "1", TCL_GLOBAL_ONLY);
3438#else
3439 Tcl_SetVar2(interp, "sqlite_options", "columnmetadata", "0", TCL_GLOBAL_ONLY);
3440#endif
3441
drhccae6022005-02-26 17:31:26 +00003442#ifdef SQLITE_OMIT_COMPLETE
3443 Tcl_SetVar2(interp, "sqlite_options", "complete", "0", TCL_GLOBAL_ONLY);
3444#else
3445 Tcl_SetVar2(interp, "sqlite_options", "complete", "1", TCL_GLOBAL_ONLY);
3446#endif
3447
drh13d70422004-11-13 15:59:14 +00003448#ifdef SQLITE_OMIT_COMPOUND_SELECT
3449 Tcl_SetVar2(interp, "sqlite_options", "compound", "0", TCL_GLOBAL_ONLY);
3450#else
3451 Tcl_SetVar2(interp, "sqlite_options", "compound", "1", TCL_GLOBAL_ONLY);
3452#endif
3453
3454#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
3455 Tcl_SetVar2(interp, "sqlite_options", "conflict", "0", TCL_GLOBAL_ONLY);
3456#else
3457 Tcl_SetVar2(interp, "sqlite_options", "conflict", "1", TCL_GLOBAL_ONLY);
3458#endif
3459
drh66560ad2006-01-06 14:32:19 +00003460#if OS_UNIX
3461 Tcl_SetVar2(interp, "sqlite_options", "crashtest", "1", TCL_GLOBAL_ONLY);
3462#else
3463 Tcl_SetVar2(interp, "sqlite_options", "crashtest", "0", TCL_GLOBAL_ONLY);
3464#endif
3465
drh13d70422004-11-13 15:59:14 +00003466#ifdef SQLITE_OMIT_DATETIME_FUNCS
3467 Tcl_SetVar2(interp, "sqlite_options", "datetime", "0", TCL_GLOBAL_ONLY);
3468#else
3469 Tcl_SetVar2(interp, "sqlite_options", "datetime", "1", TCL_GLOBAL_ONLY);
3470#endif
3471
drh2e66f0b2005-04-28 17:18:48 +00003472#ifdef SQLITE_OMIT_DISKIO
3473 Tcl_SetVar2(interp, "sqlite_options", "diskio", "0", TCL_GLOBAL_ONLY);
3474#else
3475 Tcl_SetVar2(interp, "sqlite_options", "diskio", "1", TCL_GLOBAL_ONLY);
3476#endif
3477
drh13d70422004-11-13 15:59:14 +00003478#ifdef SQLITE_OMIT_EXPLAIN
3479 Tcl_SetVar2(interp, "sqlite_options", "explain", "0", TCL_GLOBAL_ONLY);
3480#else
3481 Tcl_SetVar2(interp, "sqlite_options", "explain", "1", TCL_GLOBAL_ONLY);
3482#endif
3483
3484#ifdef SQLITE_OMIT_FLOATING_POINT
3485 Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "0", TCL_GLOBAL_ONLY);
3486#else
3487 Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "1", TCL_GLOBAL_ONLY);
3488#endif
3489
3490#ifdef SQLITE_OMIT_FOREIGN_KEY
3491 Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "0", TCL_GLOBAL_ONLY);
3492#else
3493 Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "1", TCL_GLOBAL_ONLY);
3494#endif
3495
danielk19776b456a22005-03-21 04:04:02 +00003496#ifdef SQLITE_OMIT_GLOBALRECOVER
3497 Tcl_SetVar2(interp, "sqlite_options", "globalrecover", "0", TCL_GLOBAL_ONLY);
3498#else
3499 Tcl_SetVar2(interp, "sqlite_options", "globalrecover", "1", TCL_GLOBAL_ONLY);
3500#endif
3501
drh13d70422004-11-13 15:59:14 +00003502#ifdef SQLITE_OMIT_INTEGRITY_CHECK
3503 Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
3504#else
3505 Tcl_SetVar2(interp, "sqlite_options", "integrityck", "1", TCL_GLOBAL_ONLY);
3506#endif
3507
drhff91c452006-06-27 12:51:12 +00003508#if defined(SQLITE_DEFAULT_FILE_FORMAT) && SQLITE_DEFAULT_FILE_FORMAT==1
3509 Tcl_SetVar2(interp, "sqlite_options", "legacyformat", "1", TCL_GLOBAL_ONLY);
3510#else
3511 Tcl_SetVar2(interp, "sqlite_options", "legacyformat", "0", TCL_GLOBAL_ONLY);
3512#endif
3513
drh55ef4d92005-08-14 01:20:37 +00003514#ifdef SQLITE_OMIT_LIKE_OPTIMIZATION
3515 Tcl_SetVar2(interp, "sqlite_options", "like_opt", "0", TCL_GLOBAL_ONLY);
3516#else
3517 Tcl_SetVar2(interp, "sqlite_options", "like_opt", "1", TCL_GLOBAL_ONLY);
3518#endif
3519
drh13d70422004-11-13 15:59:14 +00003520#ifdef SQLITE_OMIT_MEMORYDB
3521 Tcl_SetVar2(interp, "sqlite_options", "memorydb", "0", TCL_GLOBAL_ONLY);
3522#else
3523 Tcl_SetVar2(interp, "sqlite_options", "memorydb", "1", TCL_GLOBAL_ONLY);
3524#endif
3525
drh6f7adc82006-01-11 21:41:20 +00003526#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
drh6aafc292006-01-05 15:50:06 +00003527 Tcl_SetVar2(interp, "sqlite_options", "memorymanage", "1", TCL_GLOBAL_ONLY);
drh6f7adc82006-01-11 21:41:20 +00003528#else
3529 Tcl_SetVar2(interp, "sqlite_options", "memorymanage", "0", TCL_GLOBAL_ONLY);
drh6aafc292006-01-05 15:50:06 +00003530#endif
3531
drh55ef4d92005-08-14 01:20:37 +00003532#ifdef SQLITE_OMIT_OR_OPTIMIZATION
3533 Tcl_SetVar2(interp, "sqlite_options", "or_opt", "0", TCL_GLOBAL_ONLY);
3534#else
3535 Tcl_SetVar2(interp, "sqlite_options", "or_opt", "1", TCL_GLOBAL_ONLY);
3536#endif
3537
drh13d70422004-11-13 15:59:14 +00003538#ifdef SQLITE_OMIT_PAGER_PRAGMAS
3539 Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "0", TCL_GLOBAL_ONLY);
3540#else
3541 Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "1", TCL_GLOBAL_ONLY);
3542#endif
3543
drh2e66f0b2005-04-28 17:18:48 +00003544#ifdef SQLITE_OMIT_PARSER
3545 Tcl_SetVar2(interp, "sqlite_options", "parser", "0", TCL_GLOBAL_ONLY);
3546#else
3547 Tcl_SetVar2(interp, "sqlite_options", "parser", "1", TCL_GLOBAL_ONLY);
3548#endif
3549
drhbf216272005-02-26 18:10:44 +00003550#if defined(SQLITE_OMIT_PRAGMA) || defined(SQLITE_OMIT_FLAG_PRAGMAS)
drh13d70422004-11-13 15:59:14 +00003551 Tcl_SetVar2(interp, "sqlite_options", "pragma", "0", TCL_GLOBAL_ONLY);
3552 Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
3553#else
3554 Tcl_SetVar2(interp, "sqlite_options", "pragma", "1", TCL_GLOBAL_ONLY);
3555#endif
3556
3557#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
3558 Tcl_SetVar2(interp, "sqlite_options", "progress", "0", TCL_GLOBAL_ONLY);
3559#else
3560 Tcl_SetVar2(interp, "sqlite_options", "progress", "1", TCL_GLOBAL_ONLY);
3561#endif
3562
drh3f459022006-01-07 16:06:07 +00003563#ifdef SQLITE_ENABLE_REDEF_IO
3564 Tcl_SetVar2(interp, "sqlite_options", "redefio", "1", TCL_GLOBAL_ONLY);
3565#else
3566 Tcl_SetVar2(interp, "sqlite_options", "redefio", "0", TCL_GLOBAL_ONLY);
3567#endif
3568
drh13d70422004-11-13 15:59:14 +00003569#ifdef SQLITE_OMIT_REINDEX
3570 Tcl_SetVar2(interp, "sqlite_options", "reindex", "0", TCL_GLOBAL_ONLY);
3571#else
3572 Tcl_SetVar2(interp, "sqlite_options", "reindex", "1", TCL_GLOBAL_ONLY);
3573#endif
3574
3575#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
3576 Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "0", TCL_GLOBAL_ONLY);
3577#else
3578 Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "1", TCL_GLOBAL_ONLY);
3579#endif
3580
3581#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
3582 Tcl_SetVar2(interp, "sqlite_options", "schema_version", "0", TCL_GLOBAL_ONLY);
3583#else
3584 Tcl_SetVar2(interp, "sqlite_options", "schema_version", "1", TCL_GLOBAL_ONLY);
3585#endif
3586
danielk1977aef0bf62005-12-30 16:28:01 +00003587#ifdef SQLITE_OMIT_SHARED_CACHE
3588 Tcl_SetVar2(interp, "sqlite_options", "shared_cache", "0", TCL_GLOBAL_ONLY);
3589#else
3590 Tcl_SetVar2(interp, "sqlite_options", "shared_cache", "1", TCL_GLOBAL_ONLY);
3591#endif
3592
danielk19773e8c37e2005-01-21 03:12:14 +00003593#ifdef SQLITE_OMIT_SUBQUERY
3594 Tcl_SetVar2(interp, "sqlite_options", "subquery", "0", TCL_GLOBAL_ONLY);
3595#else
3596 Tcl_SetVar2(interp, "sqlite_options", "subquery", "1", TCL_GLOBAL_ONLY);
3597#endif
3598
drh13d70422004-11-13 15:59:14 +00003599#ifdef SQLITE_OMIT_TCL_VARIABLE
3600 Tcl_SetVar2(interp, "sqlite_options", "tclvar", "0", TCL_GLOBAL_ONLY);
3601#else
3602 Tcl_SetVar2(interp, "sqlite_options", "tclvar", "1", TCL_GLOBAL_ONLY);
3603#endif
3604
3605#if defined(THREADSAFE) && THREADSAFE
3606 Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "1", TCL_GLOBAL_ONLY);
3607#else
3608 Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "0", TCL_GLOBAL_ONLY);
3609#endif
3610
drh19e2d372005-08-29 23:00:03 +00003611#ifdef SQLITE_OMIT_TRACE
3612 Tcl_SetVar2(interp, "sqlite_options", "trace", "0", TCL_GLOBAL_ONLY);
3613#else
3614 Tcl_SetVar2(interp, "sqlite_options", "trace", "1", TCL_GLOBAL_ONLY);
3615#endif
3616
drh13d70422004-11-13 15:59:14 +00003617#ifdef SQLITE_OMIT_TRIGGER
3618 Tcl_SetVar2(interp, "sqlite_options", "trigger", "0", TCL_GLOBAL_ONLY);
3619#else
3620 Tcl_SetVar2(interp, "sqlite_options", "trigger", "1", TCL_GLOBAL_ONLY);
3621#endif
3622
danielk197753c0f742005-03-29 03:10:59 +00003623#ifdef SQLITE_OMIT_TEMPDB
3624 Tcl_SetVar2(interp, "sqlite_options", "tempdb", "0", TCL_GLOBAL_ONLY);
3625#else
3626 Tcl_SetVar2(interp, "sqlite_options", "tempdb", "1", TCL_GLOBAL_ONLY);
3627#endif
3628
drh13d70422004-11-13 15:59:14 +00003629#ifdef SQLITE_OMIT_UTF16
3630 Tcl_SetVar2(interp, "sqlite_options", "utf16", "0", TCL_GLOBAL_ONLY);
3631#else
3632 Tcl_SetVar2(interp, "sqlite_options", "utf16", "1", TCL_GLOBAL_ONLY);
3633#endif
3634
3635#ifdef SQLITE_OMIT_VACUUM
3636 Tcl_SetVar2(interp, "sqlite_options", "vacuum", "0", TCL_GLOBAL_ONLY);
3637#else
3638 Tcl_SetVar2(interp, "sqlite_options", "vacuum", "1", TCL_GLOBAL_ONLY);
3639#endif
3640
3641#ifdef SQLITE_OMIT_VIEW
3642 Tcl_SetVar2(interp, "sqlite_options", "view", "0", TCL_GLOBAL_ONLY);
3643#else
3644 Tcl_SetVar2(interp, "sqlite_options", "view", "1", TCL_GLOBAL_ONLY);
3645#endif
drhb9bb7c12006-06-11 23:41:55 +00003646
3647#ifdef SQLITE_OMIT_VIRTUALTABLE
3648 Tcl_SetVar2(interp, "sqlite_options", "vtab", "0", TCL_GLOBAL_ONLY);
3649#else
3650 Tcl_SetVar2(interp, "sqlite_options", "vtab", "1", TCL_GLOBAL_ONLY);
3651#endif
drh27d258a2004-10-30 20:23:09 +00003652}
3653
3654/*
drhd1bf3512001-04-07 15:24:33 +00003655** Register commands with the TCL interpreter.
3656*/
3657int Sqlitetest1_Init(Tcl_Interp *interp){
danielk19776f8a5032004-05-10 10:34:51 +00003658 extern int sqlite3_search_count;
3659 extern int sqlite3_interrupt_count;
3660 extern int sqlite3_open_file_count;
drh6bf89572004-11-03 16:27:01 +00003661 extern int sqlite3_sort_count;
danielk19776f8a5032004-05-10 10:34:51 +00003662 extern int sqlite3_current_time;
drhc2eef3b2002-08-31 18:53:06 +00003663 static struct {
3664 char *zName;
3665 Tcl_CmdProc *xProc;
3666 } aCmd[] = {
drhd3d39e92004-05-20 22:16:29 +00003667 { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int },
drhe9707672004-06-25 01:10:48 +00003668 { "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 },
drhd3d39e92004-05-20 22:16:29 +00003669 { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str },
drhe29b1a02004-07-17 21:56:09 +00003670 { "sqlite3_mprintf_stronly", (Tcl_CmdProc*)sqlite3_mprintf_stronly},
drhd3d39e92004-05-20 22:16:29 +00003671 { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double },
3672 { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled },
drh63782852005-08-30 19:30:59 +00003673 { "sqlite3_mprintf_hexdouble", (Tcl_CmdProc*)sqlite3_mprintf_hexdouble},
drhd3d39e92004-05-20 22:16:29 +00003674 { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z },
drh05a82982006-03-19 13:00:25 +00003675 { "sqlite3_mprintf_n_test", (Tcl_CmdProc*)test_mprintf_n },
drhd3d39e92004-05-20 22:16:29 +00003676 { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid },
3677 { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf },
3678 { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf },
3679 { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close },
3680 { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function },
3681 { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate },
3682 { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func },
3683 { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort },
danielk19772c336542005-01-13 02:14:23 +00003684#ifdef SQLITE_MEMDEBUG
drhd3d39e92004-05-20 22:16:29 +00003685 { "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail },
3686 { "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat },
drhc2eef3b2002-08-31 18:53:06 +00003687#endif
drh25d65432004-07-22 15:02:25 +00003688 { "sqlite_bind", (Tcl_CmdProc*)test_bind },
3689 { "breakpoint", (Tcl_CmdProc*)test_breakpoint },
3690 { "sqlite3_key", (Tcl_CmdProc*)test_key },
3691 { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey },
drhcacb2082005-01-11 15:28:33 +00003692 { "sqlite_set_magic", (Tcl_CmdProc*)sqlite_set_magic },
drhc5cdca62005-01-11 16:54:14 +00003693 { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt },
danielk1977600dd0b2005-01-20 01:14:23 +00003694#if 0
3695 { "sqlite3_sleep", (Tcl_CmdProc*)test_sleep },
3696#endif
drh3e1d8e62005-05-26 16:23:34 +00003697 { "sqlite_delete_function", (Tcl_CmdProc*)delete_function },
3698 { "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation },
3699 { "sqlite3_get_autocommit", (Tcl_CmdProc*)get_autocommit },
drh79158e12005-09-06 21:40:45 +00003700 { "sqlite3_stack_used", (Tcl_CmdProc*)test_stack_used },
drhc2eef3b2002-08-31 18:53:06 +00003701 };
danielk197751e3d8e2004-05-20 01:12:34 +00003702 static struct {
3703 char *zName;
3704 Tcl_ObjCmdProc *xProc;
danielk197704f2e682004-05-27 01:04:07 +00003705 void *clientData;
danielk197751e3d8e2004-05-20 01:12:34 +00003706 } aObjCmd[] = {
drhdddca282006-01-03 00:33:50 +00003707 { "sqlite3_connection_pointer", get_sqlite_pointer, 0 },
drh241db312004-06-22 12:46:53 +00003708 { "sqlite3_bind_int", test_bind_int, 0 },
3709 { "sqlite3_bind_int64", test_bind_int64, 0 },
3710 { "sqlite3_bind_double", test_bind_double, 0 },
danielk197704f2e682004-05-27 01:04:07 +00003711 { "sqlite3_bind_null", test_bind_null ,0 },
3712 { "sqlite3_bind_text", test_bind_text ,0 },
3713 { "sqlite3_bind_text16", test_bind_text16 ,0 },
3714 { "sqlite3_bind_blob", test_bind_blob ,0 },
drh75f6a032004-07-15 14:15:00 +00003715 { "sqlite3_bind_parameter_count", test_bind_parameter_count, 0},
drh895d7472004-08-20 16:02:39 +00003716 { "sqlite3_bind_parameter_name", test_bind_parameter_name, 0},
drhfa6bc002004-09-07 16:19:52 +00003717 { "sqlite3_bind_parameter_index", test_bind_parameter_index, 0},
danielk1977600dd0b2005-01-20 01:14:23 +00003718#if 0
3719 { "sqlite3_clear_bindings", test_clear_bindings, 0},
3720#endif
danielk197704f2e682004-05-27 01:04:07 +00003721 { "sqlite3_errcode", test_errcode ,0 },
3722 { "sqlite3_errmsg", test_errmsg ,0 },
3723 { "sqlite3_errmsg16", test_errmsg16 ,0 },
3724 { "sqlite3_open", test_open ,0 },
3725 { "sqlite3_open16", test_open16 ,0 },
danielk1977bc6ada42004-06-30 08:20:16 +00003726 { "sqlite3_complete16", test_complete16 ,0 },
danielk197704f2e682004-05-27 01:04:07 +00003727
3728 { "sqlite3_prepare", test_prepare ,0 },
3729 { "sqlite3_prepare16", test_prepare16 ,0 },
3730 { "sqlite3_finalize", test_finalize ,0 },
3731 { "sqlite3_reset", test_reset ,0 },
drhd89bd002005-01-22 03:03:54 +00003732 { "sqlite3_expired", test_expired ,0 },
drhf8db1bc2005-04-22 02:38:37 +00003733 { "sqlite3_transfer_bindings", test_transfer_bind ,0 },
danielk1977fbcd5852004-06-15 02:44:18 +00003734 { "sqlite3_changes", test_changes ,0 },
3735 { "sqlite3_step", test_step ,0 },
danielk197704f2e682004-05-27 01:04:07 +00003736
drhb4bc7052006-01-11 23:40:33 +00003737 { "sqlite3_release_memory", test_release_memory, 0},
3738 { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0},
3739 { "sqlite3_clear_tsd_memdebug", test_clear_tsd_memdebug, 0},
3740 { "sqlite3_tsd_release", test_tsd_release, 0},
3741 { "sqlite3_thread_cleanup", test_thread_cleanup, 0},
drh6aafc292006-01-05 15:50:06 +00003742
drhc2e87a32006-06-27 15:16:14 +00003743 { "sqlite3_load_extension", test_load_extension, 0},
3744 { "sqlite3_enable_load_extension", test_enable_load, 0},
3745
danielk197704f2e682004-05-27 01:04:07 +00003746 /* sqlite3_column_*() API */
3747 { "sqlite3_column_count", test_column_count ,0 },
3748 { "sqlite3_data_count", test_data_count ,0 },
3749 { "sqlite3_column_type", test_column_type ,0 },
danielk1977ea61b2c2004-05-27 01:49:51 +00003750 { "sqlite3_column_blob", test_column_blob ,0 },
danielk197704f2e682004-05-27 01:04:07 +00003751 { "sqlite3_column_double", test_column_double ,0 },
3752 { "sqlite3_column_int64", test_column_int64 ,0 },
drh241db312004-06-22 12:46:53 +00003753 { "sqlite3_column_text", test_stmt_utf8, sqlite3_column_text },
3754 { "sqlite3_column_decltype", test_stmt_utf8, sqlite3_column_decltype },
3755 { "sqlite3_column_name", test_stmt_utf8, sqlite3_column_name },
drh6c626082004-11-14 21:56:29 +00003756 { "sqlite3_column_int", test_stmt_int, sqlite3_column_int },
3757 { "sqlite3_column_bytes", test_stmt_int, sqlite3_column_bytes },
danielk19774b1ae992006-02-10 03:06:10 +00003758#ifdef SQLITE_ENABLE_COLUMN_METADATA
danielk1977955de522006-02-10 02:27:42 +00003759{ "sqlite3_column_database_name", test_stmt_utf8, sqlite3_column_database_name},
3760{ "sqlite3_column_table_name", test_stmt_utf8, sqlite3_column_table_name},
3761{ "sqlite3_column_origin_name", test_stmt_utf8, sqlite3_column_origin_name},
danielk19774b1ae992006-02-10 03:06:10 +00003762#endif
danielk1977955de522006-02-10 02:27:42 +00003763
drh6c626082004-11-14 21:56:29 +00003764#ifndef SQLITE_OMIT_UTF16
3765 { "sqlite3_column_bytes16", test_stmt_int, sqlite3_column_bytes16 },
drh241db312004-06-22 12:46:53 +00003766 { "sqlite3_column_text16", test_stmt_utf16, sqlite3_column_text16 },
3767 { "sqlite3_column_decltype16", test_stmt_utf16, sqlite3_column_decltype16},
3768 { "sqlite3_column_name16", test_stmt_utf16, sqlite3_column_name16 },
drh7d9bd4e2006-02-16 18:16:36 +00003769 { "add_alignment_test_collations", add_alignment_test_collations, 0 },
danielk19774b1ae992006-02-10 03:06:10 +00003770#ifdef SQLITE_ENABLE_COLUMN_METADATA
danielk1977955de522006-02-10 02:27:42 +00003771{"sqlite3_column_database_name16",
3772 test_stmt_utf16, sqlite3_column_database_name16},
3773{"sqlite3_column_table_name16", test_stmt_utf16, sqlite3_column_table_name16},
3774{"sqlite3_column_origin_name16", test_stmt_utf16, sqlite3_column_origin_name16},
drh6c626082004-11-14 21:56:29 +00003775#endif
danielk19774b1ae992006-02-10 03:06:10 +00003776#endif
danielk19776b456a22005-03-21 04:04:02 +00003777 { "sqlite3_global_recover", test_global_recover, 0 },
danielk197704f2e682004-05-27 01:04:07 +00003778
danielk19779a1d0ab2004-06-01 14:09:28 +00003779 /* Functions from os.h */
danielk197744ee5bf2005-05-27 09:41:12 +00003780#ifndef SQLITE_OMIT_DISKIO
danielk19779a1d0ab2004-06-01 14:09:28 +00003781 { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 },
3782 { "sqlite3OsClose", test_sqlite3OsClose, 0 },
3783 { "sqlite3OsLock", test_sqlite3OsLock, 0 },
drhab3f9fe2004-08-14 17:10:10 +00003784 { "sqlite3OsTempFileName", test_sqlite3OsTempFileName, 0 },
danielk1977312d6b32004-06-29 13:18:23 +00003785
3786 /* Custom test interfaces */
3787 { "sqlite3OsUnlock", test_sqlite3OsUnlock, 0 },
danielk197744ee5bf2005-05-27 09:41:12 +00003788#endif
drh5436dc22004-11-14 04:04:17 +00003789#ifndef SQLITE_OMIT_UTF16
danielk1977312d6b32004-06-29 13:18:23 +00003790 { "add_test_collate", test_collate, 0 },
3791 { "add_test_collate_needed", test_collate_needed, 0 },
3792 { "add_test_function", test_function, 0 },
drh5436dc22004-11-14 04:04:17 +00003793#endif
danielk19775591df52005-12-20 09:19:37 +00003794#ifdef SQLITE_MEMDEBUG
3795 { "sqlite_malloc_outstanding", sqlite_malloc_outstanding, 0},
3796#endif
danielk1977312d6b32004-06-29 13:18:23 +00003797 { "sqlite3_test_errstr", test_errstr, 0 },
drh92febd92004-08-20 18:34:20 +00003798 { "tcl_variable_type", tcl_variable_type, 0 },
danielk1977aef0bf62005-12-30 16:28:01 +00003799#ifndef SQLITE_OMIT_SHARED_CACHE
drh6f7adc82006-01-11 21:41:20 +00003800 { "sqlite3_enable_shared_cache", test_enable_shared, 0 },
danielk1977aef0bf62005-12-30 16:28:01 +00003801#endif
danielk1977161fb792006-01-24 10:58:21 +00003802 { "sqlite3_libversion_number", test_libversion_number, 0 },
danielk1977deb802c2006-02-09 13:43:28 +00003803#ifdef SQLITE_ENABLE_COLUMN_METADATA
3804 { "sqlite3_table_column_metadata", test_table_column_metadata, 0 },
3805#endif
danielk197751e3d8e2004-05-20 01:12:34 +00003806 };
drh1398ad32005-01-19 23:24:50 +00003807 static int bitmask_size = sizeof(Bitmask)*8;
drhc2eef3b2002-08-31 18:53:06 +00003808 int i;
drh2ac3ee92004-06-07 16:27:46 +00003809 extern int sqlite3_os_trace;
drh51147ba2005-07-23 22:59:55 +00003810 extern int sqlite3_where_trace;
drhb851b2c2005-03-10 14:11:12 +00003811 extern int sqlite3_sync_count, sqlite3_fullsync_count;
drhaf6df112005-06-07 02:12:30 +00003812 extern int sqlite3_opentemp_count;
drh01397202005-07-20 14:31:53 +00003813 extern int sqlite3_memUsed;
danielk19772e588c72005-12-09 14:25:08 +00003814 extern int sqlite3_malloc_id;
drh01397202005-07-20 14:31:53 +00003815 extern int sqlite3_memMax;
drh55ef4d92005-08-14 01:20:37 +00003816 extern int sqlite3_like_count;
drhb4bc7052006-01-11 23:40:33 +00003817 extern int sqlite3_tsd_count;
drh029b44b2006-01-15 00:13:15 +00003818#if OS_UNIX && defined(SQLITE_TEST) && defined(THREADSAFE) && THREADSAFE
3819 extern int threadsOverrideEachOthersLocks;
3820#endif
drhc0929982005-09-05 19:08:29 +00003821#if OS_WIN
3822 extern int sqlite3_os_type;
3823#endif
drh8b3d9902005-08-19 00:14:42 +00003824#ifdef SQLITE_DEBUG
3825 extern int sqlite3_vdbe_addop_trace;
drh549c8b62005-09-19 13:15:23 +00003826#endif
3827#ifdef SQLITE_TEST
3828 extern char sqlite3_query_plan[];
drh9042f392005-07-15 23:24:23 +00003829 static char *query_plan = sqlite3_query_plan;
drh48083ce2005-09-19 12:37:27 +00003830#endif
drhc2eef3b2002-08-31 18:53:06 +00003831
3832 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
3833 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
3834 }
danielk197751e3d8e2004-05-20 01:12:34 +00003835 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
danielk1977c572ef72004-05-27 09:28:41 +00003836 Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
3837 aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
danielk197751e3d8e2004-05-20 01:12:34 +00003838 }
danielk19776490beb2004-05-11 06:17:21 +00003839 Tcl_LinkVar(interp, "sqlite_search_count",
danielk19776f8a5032004-05-10 10:34:51 +00003840 (char*)&sqlite3_search_count, TCL_LINK_INT);
drh6bf89572004-11-03 16:27:01 +00003841 Tcl_LinkVar(interp, "sqlite_sort_count",
3842 (char*)&sqlite3_sort_count, TCL_LINK_INT);
drh55ef4d92005-08-14 01:20:37 +00003843 Tcl_LinkVar(interp, "sqlite_like_count",
3844 (char*)&sqlite3_like_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00003845 Tcl_LinkVar(interp, "sqlite_interrupt_count",
danielk19776f8a5032004-05-10 10:34:51 +00003846 (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00003847 Tcl_LinkVar(interp, "sqlite_open_file_count",
danielk19776f8a5032004-05-10 10:34:51 +00003848 (char*)&sqlite3_open_file_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00003849 Tcl_LinkVar(interp, "sqlite_current_time",
danielk19776f8a5032004-05-10 10:34:51 +00003850 (char*)&sqlite3_current_time, TCL_LINK_INT);
drh2ac3ee92004-06-07 16:27:46 +00003851 Tcl_LinkVar(interp, "sqlite_os_trace",
3852 (char*)&sqlite3_os_trace, TCL_LINK_INT);
drhb4bc7052006-01-11 23:40:33 +00003853 Tcl_LinkVar(interp, "sqlite3_tsd_count",
3854 (char*)&sqlite3_tsd_count, TCL_LINK_INT);
danielk19774b2688a2006-06-20 11:01:07 +00003855#ifndef SQLITE_OMIT_UTF16
drh7d9bd4e2006-02-16 18:16:36 +00003856 Tcl_LinkVar(interp, "unaligned_string_counter",
3857 (char*)&unaligned_string_counter, TCL_LINK_INT);
danielk19774b2688a2006-06-20 11:01:07 +00003858#endif
drh029b44b2006-01-15 00:13:15 +00003859#if OS_UNIX && defined(SQLITE_TEST) && defined(THREADSAFE) && THREADSAFE
3860 Tcl_LinkVar(interp, "threadsOverrideEachOthersLocks",
3861 (char*)&threadsOverrideEachOthersLocks, TCL_LINK_INT);
3862#endif
drh268803a2005-12-14 20:11:30 +00003863#ifndef SQLITE_OMIT_UTF16
3864 Tcl_LinkVar(interp, "sqlite_last_needed_collation",
3865 (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
3866#endif
danielk197797cb2e92005-12-09 14:39:04 +00003867#ifdef SQLITE_MEMDEBUG
danielk19772e588c72005-12-09 14:25:08 +00003868 Tcl_LinkVar(interp, "sqlite_malloc_id",
3869 (char*)&sqlite3_malloc_id, TCL_LINK_STRING);
danielk197797cb2e92005-12-09 14:39:04 +00003870#endif
drhc0929982005-09-05 19:08:29 +00003871#if OS_WIN
3872 Tcl_LinkVar(interp, "sqlite_os_type",
3873 (char*)&sqlite3_os_type, TCL_LINK_INT);
3874#endif
drh549c8b62005-09-19 13:15:23 +00003875#ifdef SQLITE_TEST
3876 Tcl_LinkVar(interp, "sqlite_query_plan",
3877 (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
3878#endif
drh8b3d9902005-08-19 00:14:42 +00003879#ifdef SQLITE_DEBUG
3880 Tcl_LinkVar(interp, "sqlite_addop_trace",
3881 (char*)&sqlite3_vdbe_addop_trace, TCL_LINK_INT);
drh48083ce2005-09-19 12:37:27 +00003882 Tcl_LinkVar(interp, "sqlite_where_trace",
3883 (char*)&sqlite3_where_trace, TCL_LINK_INT);
drh8b3d9902005-08-19 00:14:42 +00003884#endif
drh70180302005-08-02 21:42:16 +00003885#ifdef SQLITE_MEMDEBUG
drh01397202005-07-20 14:31:53 +00003886 Tcl_LinkVar(interp, "sqlite_memused",
3887 (char*)&sqlite3_memUsed, TCL_LINK_INT | TCL_LINK_READ_ONLY);
3888 Tcl_LinkVar(interp, "sqlite_memmax",
3889 (char*)&sqlite3_memMax, TCL_LINK_INT | TCL_LINK_READ_ONLY);
drh70180302005-08-02 21:42:16 +00003890#endif
danielk1977cbe21be2005-06-07 07:58:48 +00003891#ifndef SQLITE_OMIT_DISKIO
drhaf6df112005-06-07 02:12:30 +00003892 Tcl_LinkVar(interp, "sqlite_opentemp_count",
3893 (char*)&sqlite3_opentemp_count, TCL_LINK_INT);
danielk1977cbe21be2005-06-07 07:58:48 +00003894#endif
drh7c972de2003-09-06 22:18:07 +00003895 Tcl_LinkVar(interp, "sqlite_static_bind_value",
3896 (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
drhab3f9fe2004-08-14 17:10:10 +00003897 Tcl_LinkVar(interp, "sqlite_temp_directory",
drheffd02b2004-08-29 23:42:13 +00003898 (char*)&sqlite3_temp_directory, TCL_LINK_STRING);
drh1398ad32005-01-19 23:24:50 +00003899 Tcl_LinkVar(interp, "bitmask_size",
3900 (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
drh748f7632005-03-11 04:41:39 +00003901#if OS_UNIX
drhb851b2c2005-03-10 14:11:12 +00003902 Tcl_LinkVar(interp, "sqlite_sync_count",
3903 (char*)&sqlite3_sync_count, TCL_LINK_INT);
3904 Tcl_LinkVar(interp, "sqlite_fullsync_count",
3905 (char*)&sqlite3_fullsync_count, TCL_LINK_INT);
drh748f7632005-03-11 04:41:39 +00003906#endif /* OS_UNIX */
drh27d258a2004-10-30 20:23:09 +00003907 set_options(interp);
danielk1977b82e7ed2006-01-11 14:09:31 +00003908
drhb4bc7052006-01-11 23:40:33 +00003909 {
danielk197707cb5602006-01-20 10:55:05 +00003910#ifdef SQLITE_DEBUG
drhb4bc7052006-01-11 23:40:33 +00003911 extern int sqlite3_shared_cache_report(void *, Tcl_Interp *,
3912 int, Tcl_Obj *CONST[]);
3913 Tcl_CreateObjCommand(interp, "sqlite_shared_cache_report",
3914 sqlite3_shared_cache_report, 0, 0);
danielk197707cb5602006-01-20 10:55:05 +00003915#endif
drhb4bc7052006-01-11 23:40:33 +00003916 }
drhd1bf3512001-04-07 15:24:33 +00003917 return TCL_OK;
3918}