blob: 3684b6a1aea3578c4023873bd44c2a4d0875c815 [file] [log] [blame]
drhd1bf3512001-04-07 15:24:33 +00001/*
drhb19a2bc2001-09-16 00:13:26 +00002** 2001 September 15
drhd1bf3512001-04-07 15:24:33 +00003**
drhb19a2bc2001-09-16 00:13:26 +00004** The author disclaims copyright to this source code. In place of
5** a legal notice, here is a blessing:
drhd1bf3512001-04-07 15:24:33 +00006**
drhb19a2bc2001-09-16 00:13:26 +00007** May you do good and not evil.
8** May you find forgiveness for yourself and forgive others.
9** May you share freely, never taking more than you give.
drhd1bf3512001-04-07 15:24:33 +000010**
11*************************************************************************
12** Code for testing the printf() interface to SQLite. This code
13** is not included in the SQLite library. It is used for automated
14** testing of the SQLite library.
15**
danielk19772c336542005-01-13 02:14:23 +000016** $Id: test1.c,v 1.122 2005/01/13 02:14:25 danielk1977 Exp $
drhd1bf3512001-04-07 15:24:33 +000017*/
18#include "sqliteInt.h"
19#include "tcl.h"
drh94e92032003-02-16 22:21:32 +000020#include "os.h"
drhd1bf3512001-04-07 15:24:33 +000021#include <stdlib.h>
22#include <string.h>
23
danielk19776622cce2004-05-20 11:00:52 +000024static const char * errorName(int rc){
25 const char *zName = 0;
26 switch( rc ){
27 case SQLITE_OK: zName = "SQLITE_OK"; break;
28 case SQLITE_ERROR: zName = "SQLITE_ERROR"; break;
29 case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break;
30 case SQLITE_PERM: zName = "SQLITE_PERM"; break;
31 case SQLITE_ABORT: zName = "SQLITE_ABORT"; break;
32 case SQLITE_BUSY: zName = "SQLITE_BUSY"; break;
33 case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break;
34 case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break;
35 case SQLITE_READONLY: zName = "SQLITE_READONLY"; break;
36 case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break;
37 case SQLITE_IOERR: zName = "SQLITE_IOERR"; break;
38 case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break;
39 case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break;
40 case SQLITE_FULL: zName = "SQLITE_FULL"; break;
41 case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break;
42 case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
43 case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break;
44 case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break;
45 case SQLITE_TOOBIG: zName = "SQLITE_TOOBIG"; break;
46 case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break;
47 case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break;
48 case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break;
49 case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break;
50 case SQLITE_AUTH: zName = "SQLITE_AUTH"; break;
51 case SQLITE_FORMAT: zName = "SQLITE_FORMAT"; break;
52 case SQLITE_RANGE: zName = "SQLITE_RANGE"; break;
53 case SQLITE_ROW: zName = "SQLITE_ROW"; break;
54 case SQLITE_DONE: zName = "SQLITE_DONE"; break;
drhc60d0442004-09-30 13:43:13 +000055 case SQLITE_NOTADB: zName = "SQLITE_NOTADB"; break;
danielk19776622cce2004-05-20 11:00:52 +000056 default: zName = "SQLITE_Unknown"; break;
57 }
58 return zName;
59}
60
drhd1bf3512001-04-07 15:24:33 +000061/*
drhc60d0442004-09-30 13:43:13 +000062** Convert an sqlite3_stmt* into an sqlite3*. This depends on the
63** fact that the sqlite3* is the first field in the Vdbe structure.
64*/
65#define StmtToDb(X) (*(sqlite3**)(X))
66
67/*
68** Check a return value to make sure it agrees with the results
69** from sqlite3_errcode.
70*/
71int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){
72 if( rc!=SQLITE_MISUSE && rc!=SQLITE_OK && sqlite3_errcode(db)!=rc ){
73 char zBuf[200];
74 int r2 = sqlite3_errcode(db);
75 sprintf(zBuf, "error code %s (%d) does not match sqlite3_errcode %s (%d)",
76 errorName(rc), rc, errorName(r2), r2);
77 Tcl_ResetResult(interp);
78 Tcl_AppendResult(interp, zBuf, 0);
79 return 1;
80 }
81 return 0;
82}
83
84/*
drh9bb575f2004-09-06 17:24:11 +000085** Decode a pointer to an sqlite3 object.
drhb86ccfb2003-01-28 23:13:10 +000086*/
drh9bb575f2004-09-06 17:24:11 +000087static int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
drhfe63d1c2004-09-08 20:13:04 +000088 *ppDb = (sqlite3*)sqlite3TextToPtr(zA);
drhb86ccfb2003-01-28 23:13:10 +000089 return TCL_OK;
90}
91
92/*
danielk197751e3d8e2004-05-20 01:12:34 +000093** Decode a pointer to an sqlite3_stmt object.
94*/
95static int getStmtPointer(
96 Tcl_Interp *interp,
97 const char *zArg,
98 sqlite3_stmt **ppStmt
99){
drhfe63d1c2004-09-08 20:13:04 +0000100 *ppStmt = (sqlite3_stmt*)sqlite3TextToPtr(zArg);
danielk197751e3d8e2004-05-20 01:12:34 +0000101 return TCL_OK;
102}
103
104/*
danielk19779a1d0ab2004-06-01 14:09:28 +0000105** Decode a pointer to an sqlite3_stmt object.
106*/
107static int getFilePointer(
108 Tcl_Interp *interp,
109 const char *zArg,
110 OsFile **ppFile
111){
drhfe63d1c2004-09-08 20:13:04 +0000112 *ppFile = (OsFile*)sqlite3TextToPtr(zArg);
danielk19779a1d0ab2004-06-01 14:09:28 +0000113 return TCL_OK;
114}
115
116/*
drh7d8085a2003-04-26 13:19:38 +0000117** Generate a text representation of a pointer that can be understood
118** by the getDbPointer and getVmPointer routines above.
119**
120** The problem is, on some machines (Solaris) if you do a printf with
121** "%p" you cannot turn around and do a scanf with the same "%p" and
122** get your pointer back. You have to prepend a "0x" before it will
123** work. Or at least that is what is reported to me (drh). But this
124** behavior varies from machine to machine. The solution used her is
125** to test the string right after it is generated to see if it can be
126** understood by scanf, and if not, try prepending an "0x" to see if
127** that helps. If nothing works, a fatal error is generated.
128*/
129static int makePointerStr(Tcl_Interp *interp, char *zPtr, void *p){
drhfe63d1c2004-09-08 20:13:04 +0000130 sqlite3_snprintf(100, zPtr, "%p", p);
drh7d8085a2003-04-26 13:19:38 +0000131 return TCL_OK;
132}
133
134/*
danielk19776f8a5032004-05-10 10:34:51 +0000135** The callback routine for sqlite3_exec_printf().
drhd1bf3512001-04-07 15:24:33 +0000136*/
137static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){
138 Tcl_DString *str = (Tcl_DString*)pArg;
139 int i;
140
141 if( Tcl_DStringLength(str)==0 ){
142 for(i=0; i<argc; i++){
143 Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL");
144 }
145 }
146 for(i=0; i<argc; i++){
147 Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL");
148 }
149 return 0;
150}
151
152/*
danielk19776f8a5032004-05-10 10:34:51 +0000153** Usage: sqlite3_exec_printf DB FORMAT STRING
drhd1bf3512001-04-07 15:24:33 +0000154**
danielk19776f8a5032004-05-10 10:34:51 +0000155** Invoke the sqlite3_exec_printf() interface using the open database
drhd1bf3512001-04-07 15:24:33 +0000156** DB. The SQL is the string FORMAT. The format string should contain
157** one %s or %q. STRING is the value inserted into %s or %q.
158*/
159static int test_exec_printf(
160 void *NotUsed,
161 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
162 int argc, /* Number of arguments */
163 char **argv /* Text of each argument */
164){
drh9bb575f2004-09-06 17:24:11 +0000165 sqlite3 *db;
drhd1bf3512001-04-07 15:24:33 +0000166 Tcl_DString str;
167 int rc;
168 char *zErr = 0;
drh1211de32004-07-26 12:24:22 +0000169 char *zSql;
drhd1bf3512001-04-07 15:24:33 +0000170 char zBuf[30];
171 if( argc!=4 ){
172 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
173 " DB FORMAT STRING", 0);
174 return TCL_ERROR;
175 }
drhb86ccfb2003-01-28 23:13:10 +0000176 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000177 Tcl_DStringInit(&str);
drh1211de32004-07-26 12:24:22 +0000178 zSql = sqlite3_mprintf(argv[2], argv[3]);
179 rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
180 sqlite3_free(zSql);
drhd1bf3512001-04-07 15:24:33 +0000181 sprintf(zBuf, "%d", rc);
182 Tcl_AppendElement(interp, zBuf);
183 Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
184 Tcl_DStringFree(&str);
185 if( zErr ) free(zErr);
drhc60d0442004-09-30 13:43:13 +0000186 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000187 return TCL_OK;
188}
189
190/*
danielk19776f8a5032004-05-10 10:34:51 +0000191** Usage: sqlite3_mprintf_z_test SEPARATOR ARG0 ARG1 ...
drhd93d8a82003-06-16 03:08:18 +0000192**
193** Test the %z format of mprintf(). Use multiple mprintf() calls to
194** concatenate arg0 through argn using separator as the separator.
195** Return the result.
196*/
197static int test_mprintf_z(
198 void *NotUsed,
199 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
200 int argc, /* Number of arguments */
201 char **argv /* Text of each argument */
202){
203 char *zResult = 0;
204 int i;
205
206 for(i=2; i<argc; i++){
danielk19774adee202004-05-08 08:23:19 +0000207 zResult = sqlite3MPrintf("%z%s%s", zResult, argv[1], argv[i]);
drhd93d8a82003-06-16 03:08:18 +0000208 }
209 Tcl_AppendResult(interp, zResult, 0);
drh5f968432004-02-21 19:02:30 +0000210 sqliteFree(zResult);
drhd93d8a82003-06-16 03:08:18 +0000211 return TCL_OK;
212}
213
214/*
danielk19776f8a5032004-05-10 10:34:51 +0000215** Usage: sqlite3_get_table_printf DB FORMAT STRING
drhd1bf3512001-04-07 15:24:33 +0000216**
danielk19776f8a5032004-05-10 10:34:51 +0000217** Invoke the sqlite3_get_table_printf() interface using the open database
drhd1bf3512001-04-07 15:24:33 +0000218** DB. The SQL is the string FORMAT. The format string should contain
219** one %s or %q. STRING is the value inserted into %s or %q.
220*/
221static int test_get_table_printf(
222 void *NotUsed,
223 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
224 int argc, /* Number of arguments */
225 char **argv /* Text of each argument */
226){
drh9bb575f2004-09-06 17:24:11 +0000227 sqlite3 *db;
drhd1bf3512001-04-07 15:24:33 +0000228 Tcl_DString str;
229 int rc;
230 char *zErr = 0;
231 int nRow, nCol;
232 char **aResult;
233 int i;
234 char zBuf[30];
drh1211de32004-07-26 12:24:22 +0000235 char *zSql;
drhd1bf3512001-04-07 15:24:33 +0000236 if( argc!=4 ){
237 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
238 " DB FORMAT STRING", 0);
239 return TCL_ERROR;
240 }
drhb86ccfb2003-01-28 23:13:10 +0000241 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000242 Tcl_DStringInit(&str);
drh1211de32004-07-26 12:24:22 +0000243 zSql = sqlite3_mprintf(argv[2],argv[3]);
244 rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr);
245 sqlite3_free(zSql);
drhd1bf3512001-04-07 15:24:33 +0000246 sprintf(zBuf, "%d", rc);
247 Tcl_AppendElement(interp, zBuf);
248 if( rc==SQLITE_OK ){
249 sprintf(zBuf, "%d", nRow);
250 Tcl_AppendElement(interp, zBuf);
251 sprintf(zBuf, "%d", nCol);
252 Tcl_AppendElement(interp, zBuf);
253 for(i=0; i<(nRow+1)*nCol; i++){
254 Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL");
255 }
256 }else{
257 Tcl_AppendElement(interp, zErr);
258 }
danielk19776f8a5032004-05-10 10:34:51 +0000259 sqlite3_free_table(aResult);
drhd1bf3512001-04-07 15:24:33 +0000260 if( zErr ) free(zErr);
drhc60d0442004-09-30 13:43:13 +0000261 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000262 return TCL_OK;
263}
264
drhaf9ff332002-01-16 21:00:27 +0000265
266/*
danielk19776f8a5032004-05-10 10:34:51 +0000267** Usage: sqlite3_last_insert_rowid DB
drhaf9ff332002-01-16 21:00:27 +0000268**
269** Returns the integer ROWID of the most recent insert.
270*/
271static int test_last_rowid(
272 void *NotUsed,
273 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
274 int argc, /* Number of arguments */
275 char **argv /* Text of each argument */
276){
drh9bb575f2004-09-06 17:24:11 +0000277 sqlite3 *db;
drhaf9ff332002-01-16 21:00:27 +0000278 char zBuf[30];
279
280 if( argc!=2 ){
281 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0);
282 return TCL_ERROR;
283 }
drhb86ccfb2003-01-28 23:13:10 +0000284 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk1977c572ef72004-05-27 09:28:41 +0000285 sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db));
drhaf9ff332002-01-16 21:00:27 +0000286 Tcl_AppendResult(interp, zBuf, 0);
287 return SQLITE_OK;
288}
289
drhd1bf3512001-04-07 15:24:33 +0000290/*
drh25d65432004-07-22 15:02:25 +0000291** Usage: sqlite3_key DB KEY
292**
293** Set the codec key.
294*/
295static int test_key(
296 void *NotUsed,
297 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
298 int argc, /* Number of arguments */
299 char **argv /* Text of each argument */
300){
drh9bb575f2004-09-06 17:24:11 +0000301 sqlite3 *db;
drh25d65432004-07-22 15:02:25 +0000302 const char *zKey;
303 int nKey;
304 if( argc!=3 ){
305 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
306 " FILENAME\"", 0);
307 return TCL_ERROR;
308 }
309 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
310 zKey = argv[2];
311 nKey = strlen(zKey);
312#ifdef SQLITE_HAS_CODEC
313 sqlite3_key(db, zKey, nKey);
314#endif
315 return TCL_OK;
316}
317
318/*
319** Usage: sqlite3_rekey DB KEY
320**
321** Change the codec key.
322*/
323static int test_rekey(
324 void *NotUsed,
325 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
326 int argc, /* Number of arguments */
327 char **argv /* Text of each argument */
328){
drh9bb575f2004-09-06 17:24:11 +0000329 sqlite3 *db;
drh25d65432004-07-22 15:02:25 +0000330 const char *zKey;
331 int nKey;
332 if( argc!=3 ){
333 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
334 " FILENAME\"", 0);
335 return TCL_ERROR;
336 }
337 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
338 zKey = argv[2];
339 nKey = strlen(zKey);
340#ifdef SQLITE_HAS_CODEC
341 sqlite3_rekey(db, zKey, nKey);
342#endif
343 return TCL_OK;
344}
345
346/*
danielk19776f8a5032004-05-10 10:34:51 +0000347** Usage: sqlite3_close DB
drhd1bf3512001-04-07 15:24:33 +0000348**
danielk19776f8a5032004-05-10 10:34:51 +0000349** Closes the database opened by sqlite3_open.
drhd1bf3512001-04-07 15:24:33 +0000350*/
351static int sqlite_test_close(
352 void *NotUsed,
353 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
354 int argc, /* Number of arguments */
355 char **argv /* Text of each argument */
356){
drh9bb575f2004-09-06 17:24:11 +0000357 sqlite3 *db;
danielk197796d81f92004-06-19 03:33:57 +0000358 int rc;
drhd1bf3512001-04-07 15:24:33 +0000359 if( argc!=2 ){
360 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
361 " FILENAME\"", 0);
362 return TCL_ERROR;
363 }
drhb86ccfb2003-01-28 23:13:10 +0000364 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk197796d81f92004-06-19 03:33:57 +0000365 rc = sqlite3_close(db);
danielk1977f9d64d22004-06-19 08:18:07 +0000366 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
drhd1bf3512001-04-07 15:24:33 +0000367 return TCL_OK;
368}
369
370/*
drhc22bd472002-05-10 13:14:07 +0000371** Implementation of the x_coalesce() function.
372** Return the first argument non-NULL argument.
373*/
danielk19770ae8b832004-05-25 12:05:56 +0000374static void ifnullFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
drhc22bd472002-05-10 13:14:07 +0000375 int i;
376 for(i=0; i<argc; i++){
drh9c054832004-05-31 18:51:57 +0000377 if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
danielk1977d8123362004-06-12 09:25:12 +0000378 sqlite3_result_text(context, sqlite3_value_text(argv[i]), -1,
379 SQLITE_TRANSIENT);
drhc22bd472002-05-10 13:14:07 +0000380 break;
381 }
382 }
383}
384
385/*
drhd1d9fc32004-01-07 19:24:48 +0000386** A structure into which to accumulate text.
387*/
388struct dstr {
389 int nAlloc; /* Space allocated */
390 int nUsed; /* Space used */
391 char *z; /* The space */
392};
393
394/*
395** Append text to a dstr
396*/
397static void dstrAppend(struct dstr *p, const char *z, int divider){
398 int n = strlen(z);
399 if( p->nUsed + n + 2 > p->nAlloc ){
400 char *zNew;
401 p->nAlloc = p->nAlloc*2 + n + 200;
402 zNew = sqliteRealloc(p->z, p->nAlloc);
403 if( zNew==0 ){
404 sqliteFree(p->z);
405 memset(p, 0, sizeof(*p));
406 return;
407 }
408 p->z = zNew;
409 }
410 if( divider && p->nUsed>0 ){
411 p->z[p->nUsed++] = divider;
412 }
413 memcpy(&p->z[p->nUsed], z, n+1);
414 p->nUsed += n;
415}
416
417/*
danielk19774adee202004-05-08 08:23:19 +0000418** Invoked for each callback from sqlite3ExecFunc
drhd1d9fc32004-01-07 19:24:48 +0000419*/
420static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){
421 struct dstr *p = (struct dstr*)pData;
422 int i;
423 for(i=0; i<argc; i++){
424 if( argv[i]==0 ){
425 dstrAppend(p, "NULL", ' ');
426 }else{
427 dstrAppend(p, argv[i], ' ');
428 }
429 }
430 return 0;
431}
432
433/*
danielk1977e35ee192004-06-26 09:50:11 +0000434** Implementation of the x_sqlite_exec() function. This function takes
drhc22bd472002-05-10 13:14:07 +0000435** a single argument and attempts to execute that argument as SQL code.
drh6cbe1f12002-07-01 00:31:36 +0000436** This is illegal and should set the SQLITE_MISUSE flag on the database.
drhd1d9fc32004-01-07 19:24:48 +0000437**
danielk19776f8a5032004-05-10 10:34:51 +0000438** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec()
drhd1d9fc32004-01-07 19:24:48 +0000439** from within a function call.
drhc22bd472002-05-10 13:14:07 +0000440**
441** This routine simulates the effect of having two threads attempt to
442** use the same database at the same time.
443*/
danielk197751ad0ec2004-05-24 12:39:02 +0000444static void sqlite3ExecFunc(
danielk19770ae8b832004-05-25 12:05:56 +0000445 sqlite3_context *context,
danielk197751ad0ec2004-05-24 12:39:02 +0000446 int argc,
447 sqlite3_value **argv
448){
drhd1d9fc32004-01-07 19:24:48 +0000449 struct dstr x;
450 memset(&x, 0, sizeof(x));
drh9bb575f2004-09-06 17:24:11 +0000451 sqlite3_exec((sqlite3*)sqlite3_user_data(context),
drh4f26d6c2004-05-26 23:25:30 +0000452 sqlite3_value_text(argv[0]),
drhd1d9fc32004-01-07 19:24:48 +0000453 execFuncCallback, &x, 0);
danielk1977d8123362004-06-12 09:25:12 +0000454 sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT);
drhd1d9fc32004-01-07 19:24:48 +0000455 sqliteFree(x.z);
drhc22bd472002-05-10 13:14:07 +0000456}
457
458/*
459** Usage: sqlite_test_create_function DB
460**
danielk19776f8a5032004-05-10 10:34:51 +0000461** Call the sqlite3_create_function API on the given database in order
drhc22bd472002-05-10 13:14:07 +0000462** to create a function named "x_coalesce". This function does the same thing
463** as the "coalesce" function. This function also registers an SQL function
danielk1977e35ee192004-06-26 09:50:11 +0000464** named "x_sqlite_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec()
drhc22bd472002-05-10 13:14:07 +0000465** in this way is illegal recursion and should raise an SQLITE_MISUSE error.
466** The effect is similar to trying to use the same database connection from
467** two threads at the same time.
468**
469** The original motivation for this routine was to be able to call the
danielk19776f8a5032004-05-10 10:34:51 +0000470** sqlite3_create_function function while a query is in progress in order
drhc22bd472002-05-10 13:14:07 +0000471** to test the SQLITE_MISUSE detection logic.
472*/
drhc2eef3b2002-08-31 18:53:06 +0000473static int test_create_function(
drhc22bd472002-05-10 13:14:07 +0000474 void *NotUsed,
475 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
476 int argc, /* Number of arguments */
477 char **argv /* Text of each argument */
478){
drhc60d0442004-09-30 13:43:13 +0000479 int rc;
drh9bb575f2004-09-06 17:24:11 +0000480 sqlite3 *db;
danielk1977312d6b32004-06-29 13:18:23 +0000481 sqlite3_value *pVal;
drh9bb575f2004-09-06 17:24:11 +0000482 extern void Md5_Register(sqlite3*);
danielk1977312d6b32004-06-29 13:18:23 +0000483
drhc22bd472002-05-10 13:14:07 +0000484 if( argc!=2 ){
485 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
danielk19774397de52005-01-12 12:44:03 +0000486 " DB\"", 0);
drhc22bd472002-05-10 13:14:07 +0000487 return TCL_ERROR;
488 }
drhb86ccfb2003-01-28 23:13:10 +0000489 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +0000490 rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0,
491 ifnullFunc, 0, 0);
danielk1977312d6b32004-06-29 13:18:23 +0000492
drh5436dc22004-11-14 04:04:17 +0000493#ifndef SQLITE_OMIT_UTF16
danielk1977312d6b32004-06-29 13:18:23 +0000494 /* Use the sqlite3_create_function16() API here. Mainly for fun, but also
495 ** because it is not tested anywhere else. */
drhc60d0442004-09-30 13:43:13 +0000496 if( rc==SQLITE_OK ){
497 pVal = sqlite3ValueNew();
498 sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC);
499 rc = sqlite3_create_function16(db,
500 sqlite3ValueText(pVal, SQLITE_UTF16NATIVE),
501 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
502 sqlite3ValueFree(pVal);
503 }
drh5436dc22004-11-14 04:04:17 +0000504#endif
505
drhc60d0442004-09-30 13:43:13 +0000506 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk19774397de52005-01-12 12:44:03 +0000507 Tcl_SetResult(interp, (char *)errorName(rc), 0);
drhc22bd472002-05-10 13:14:07 +0000508 return TCL_OK;
509}
510
511/*
512** Routines to implement the x_count() aggregate function.
513*/
514typedef struct CountCtx CountCtx;
515struct CountCtx {
516 int n;
517};
danielk19770ae8b832004-05-25 12:05:56 +0000518static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
drhc22bd472002-05-10 13:14:07 +0000519 CountCtx *p;
drh4f26d6c2004-05-26 23:25:30 +0000520 p = sqlite3_aggregate_context(context, sizeof(*p));
drh9c054832004-05-31 18:51:57 +0000521 if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){
drhc22bd472002-05-10 13:14:07 +0000522 p->n++;
523 }
524}
danielk19770ae8b832004-05-25 12:05:56 +0000525static void countFinalize(sqlite3_context *context){
drhc22bd472002-05-10 13:14:07 +0000526 CountCtx *p;
drh4f26d6c2004-05-26 23:25:30 +0000527 p = sqlite3_aggregate_context(context, sizeof(*p));
danielk1977c572ef72004-05-27 09:28:41 +0000528 sqlite3_result_int(context, p ? p->n : 0);
drhc22bd472002-05-10 13:14:07 +0000529}
530
531/*
532** Usage: sqlite_test_create_aggregate DB
533**
danielk19776f8a5032004-05-10 10:34:51 +0000534** Call the sqlite3_create_function API on the given database in order
drhc22bd472002-05-10 13:14:07 +0000535** to create a function named "x_count". This function does the same thing
536** as the "md5sum" function.
537**
538** The original motivation for this routine was to be able to call the
danielk19776f8a5032004-05-10 10:34:51 +0000539** sqlite3_create_aggregate function while a query is in progress in order
drhc22bd472002-05-10 13:14:07 +0000540** to test the SQLITE_MISUSE detection logic.
541*/
drhc2eef3b2002-08-31 18:53:06 +0000542static int test_create_aggregate(
drhc22bd472002-05-10 13:14:07 +0000543 void *NotUsed,
544 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
545 int argc, /* Number of arguments */
546 char **argv /* Text of each argument */
547){
drh9bb575f2004-09-06 17:24:11 +0000548 sqlite3 *db;
drhc60d0442004-09-30 13:43:13 +0000549 int rc;
drhc22bd472002-05-10 13:14:07 +0000550 if( argc!=2 ){
551 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
552 " FILENAME\"", 0);
553 return TCL_ERROR;
554 }
drhb86ccfb2003-01-28 23:13:10 +0000555 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +0000556 rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0,
danielk1977d8123362004-06-12 09:25:12 +0000557 countStep,countFinalize);
drhc60d0442004-09-30 13:43:13 +0000558 if( rc==SQLITE_OK ){
559 sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0,
560 countStep,countFinalize);
561 }
562 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drhc22bd472002-05-10 13:14:07 +0000563 return TCL_OK;
564}
565
566
567
568/*
danielk19776f8a5032004-05-10 10:34:51 +0000569** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER
drhd1bf3512001-04-07 15:24:33 +0000570**
571** Call mprintf with three integer arguments
572*/
danielk19776f8a5032004-05-10 10:34:51 +0000573static int sqlite3_mprintf_int(
drhd1bf3512001-04-07 15:24:33 +0000574 void *NotUsed,
575 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
576 int argc, /* Number of arguments */
577 char **argv /* Text of each argument */
578){
579 int a[3], i;
580 char *z;
581 if( argc!=5 ){
582 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
583 " FORMAT INT INT INT\"", 0);
584 return TCL_ERROR;
585 }
586 for(i=2; i<5; i++){
587 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
588 }
danielk19776f8a5032004-05-10 10:34:51 +0000589 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
drhd1bf3512001-04-07 15:24:33 +0000590 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000591 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +0000592 return TCL_OK;
593}
594
595/*
drh9d213ef2004-06-30 04:02:11 +0000596** If zNum represents an integer that will fit in 64-bits, then set
597** *pValue to that integer and return true. Otherwise return false.
598*/
599static int sqlite3GetInt64(const char *zNum, i64 *pValue){
600 if( sqlite3FitsIn64Bits(zNum) ){
601 sqlite3atoi64(zNum, pValue);
602 return 1;
603 }
604 return 0;
605}
606
607/*
drhe9707672004-06-25 01:10:48 +0000608** Usage: sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER
609**
610** Call mprintf with three 64-bit integer arguments
611*/
612static int sqlite3_mprintf_int64(
613 void *NotUsed,
614 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
615 int argc, /* Number of arguments */
616 char **argv /* Text of each argument */
617){
618 int i;
619 sqlite_int64 a[3];
620 char *z;
621 if( argc!=5 ){
622 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
623 " FORMAT INT INT INT\"", 0);
624 return TCL_ERROR;
625 }
626 for(i=2; i<5; i++){
627 if( !sqlite3GetInt64(argv[i], &a[i-2]) ){
628 Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0);
629 return TCL_ERROR;
630 }
631 }
632 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
633 Tcl_AppendResult(interp, z, 0);
634 sqlite3_free(z);
635 return TCL_OK;
636}
637
638/*
danielk19776f8a5032004-05-10 10:34:51 +0000639** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING
drhd1bf3512001-04-07 15:24:33 +0000640**
641** Call mprintf with two integer arguments and one string argument
642*/
danielk19776f8a5032004-05-10 10:34:51 +0000643static int sqlite3_mprintf_str(
drhd1bf3512001-04-07 15:24:33 +0000644 void *NotUsed,
645 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
646 int argc, /* Number of arguments */
647 char **argv /* Text of each argument */
648){
649 int a[3], i;
650 char *z;
chwf220b242002-06-16 04:54:28 +0000651 if( argc<4 || argc>5 ){
drhd1bf3512001-04-07 15:24:33 +0000652 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
chwf220b242002-06-16 04:54:28 +0000653 " FORMAT INT INT ?STRING?\"", 0);
drhd1bf3512001-04-07 15:24:33 +0000654 return TCL_ERROR;
655 }
656 for(i=2; i<4; i++){
657 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
658 }
danielk19776f8a5032004-05-10 10:34:51 +0000659 z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL);
drhd1bf3512001-04-07 15:24:33 +0000660 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000661 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +0000662 return TCL_OK;
663}
664
665/*
danielk19776f8a5032004-05-10 10:34:51 +0000666** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER DOUBLE
drhd1bf3512001-04-07 15:24:33 +0000667**
668** Call mprintf with two integer arguments and one double argument
669*/
danielk19776f8a5032004-05-10 10:34:51 +0000670static int sqlite3_mprintf_double(
drhd1bf3512001-04-07 15:24:33 +0000671 void *NotUsed,
672 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
673 int argc, /* Number of arguments */
674 char **argv /* Text of each argument */
675){
676 int a[3], i;
677 double r;
678 char *z;
679 if( argc!=5 ){
680 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
681 " FORMAT INT INT STRING\"", 0);
682 return TCL_ERROR;
683 }
684 for(i=2; i<4; i++){
685 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
686 }
687 if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
danielk19776f8a5032004-05-10 10:34:51 +0000688 z = sqlite3_mprintf(argv[1], a[0], a[1], r);
drhd1bf3512001-04-07 15:24:33 +0000689 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000690 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +0000691 return TCL_OK;
692}
693
694/*
danielk19776f8a5032004-05-10 10:34:51 +0000695** Usage: sqlite3_mprintf_str FORMAT DOUBLE DOUBLE
drhb621c232004-02-21 19:41:04 +0000696**
697** Call mprintf with a single double argument which is the product of the
698** two arguments given above. This is used to generate overflow and underflow
699** doubles to test that they are converted properly.
700*/
danielk19776f8a5032004-05-10 10:34:51 +0000701static int sqlite3_mprintf_scaled(
drhb621c232004-02-21 19:41:04 +0000702 void *NotUsed,
703 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
704 int argc, /* Number of arguments */
705 char **argv /* Text of each argument */
706){
707 int i;
708 double r[2];
709 char *z;
710 if( argc!=4 ){
711 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
712 " FORMAT DOUBLE DOUBLE\"", 0);
713 return TCL_ERROR;
714 }
715 for(i=2; i<4; i++){
716 if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR;
717 }
danielk19776f8a5032004-05-10 10:34:51 +0000718 z = sqlite3_mprintf(argv[1], r[0]*r[1]);
drhb621c232004-02-21 19:41:04 +0000719 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000720 sqlite3_free(z);
drhb621c232004-02-21 19:41:04 +0000721 return TCL_OK;
722}
723
724/*
drhe29b1a02004-07-17 21:56:09 +0000725** Usage: sqlite3_mprintf_stronly FORMAT STRING
726**
727** Call mprintf with a single double argument which is the product of the
728** two arguments given above. This is used to generate overflow and underflow
729** doubles to test that they are converted properly.
730*/
731static int sqlite3_mprintf_stronly(
732 void *NotUsed,
733 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
734 int argc, /* Number of arguments */
735 char **argv /* Text of each argument */
736){
737 char *z;
738 if( argc!=3 ){
739 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
740 " FORMAT STRING\"", 0);
741 return TCL_ERROR;
742 }
743 z = sqlite3_mprintf(argv[1], argv[2]);
744 Tcl_AppendResult(interp, z, 0);
745 sqlite3_free(z);
746 return TCL_OK;
747}
748
749/*
drh46934232004-11-20 19:18:00 +0000750** Usage: sqlite_malloc_fail N ?REPEAT-INTERVAL?
drhdaffd0e2001-04-11 14:28:42 +0000751**
drh46934232004-11-20 19:18:00 +0000752** Rig sqliteMalloc() to fail on the N-th call and every REPEAT-INTERVAL call
753** after that. If REPEAT-INTERVAL is 0 or is omitted, then only a single
754** malloc will fail. If REPEAT-INTERVAL is 1 then all mallocs after the
755** first failure will continue to fail on every call. If REPEAT-INTERVAL is
756** 2 then every other malloc will fail. And so forth.
757**
758** Turn off this mechanism and reset the sqlite3_malloc_failed variable is N==0.
drhdaffd0e2001-04-11 14:28:42 +0000759*/
danielk19772c336542005-01-13 02:14:23 +0000760#ifdef SQLITE_MEMDEBUG
drhdaffd0e2001-04-11 14:28:42 +0000761static int sqlite_malloc_fail(
762 void *NotUsed,
763 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
764 int argc, /* Number of arguments */
765 char **argv /* Text of each argument */
766){
767 int n;
drh46934232004-11-20 19:18:00 +0000768 int rep;
769 if( argc!=2 && argc!=3 ){
drhdaffd0e2001-04-11 14:28:42 +0000770 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0);
771 return TCL_ERROR;
772 }
773 if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
drh46934232004-11-20 19:18:00 +0000774 if( argc==3 ){
775 if( Tcl_GetInt(interp, argv[2], &rep) ) return TCL_ERROR;
776 }else{
777 rep = 0;
778 }
danielk19776f8a5032004-05-10 10:34:51 +0000779 sqlite3_iMallocFail = n;
drh46934232004-11-20 19:18:00 +0000780 sqlite3_iMallocReset = rep;
danielk19776f8a5032004-05-10 10:34:51 +0000781 sqlite3_malloc_failed = 0;
drhdaffd0e2001-04-11 14:28:42 +0000782 return TCL_OK;
783}
784#endif
785
786/*
787** Usage: sqlite_malloc_stat
788**
789** Return the number of prior calls to sqliteMalloc() and sqliteFree().
790*/
danielk19772c336542005-01-13 02:14:23 +0000791#ifdef SQLITE_MEMDEBUG
drhdaffd0e2001-04-11 14:28:42 +0000792static int sqlite_malloc_stat(
793 void *NotUsed,
794 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
795 int argc, /* Number of arguments */
796 char **argv /* Text of each argument */
797){
798 char zBuf[200];
danielk19776f8a5032004-05-10 10:34:51 +0000799 sprintf(zBuf, "%d %d %d", sqlite3_nMalloc, sqlite3_nFree, sqlite3_iMallocFail);
drhdaffd0e2001-04-11 14:28:42 +0000800 Tcl_AppendResult(interp, zBuf, 0);
801 return TCL_OK;
802}
803#endif
804
805/*
drh28b4e482002-03-11 02:06:13 +0000806** Usage: sqlite_abort
807**
808** Shutdown the process immediately. This is not a clean shutdown.
809** This command is used to test the recoverability of a database in
810** the event of a program crash.
811*/
812static int sqlite_abort(
813 void *NotUsed,
814 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
815 int argc, /* Number of arguments */
816 char **argv /* Text of each argument */
817){
818 assert( interp==0 ); /* This will always fail */
819 return TCL_OK;
820}
821
822/*
drh6cbe1f12002-07-01 00:31:36 +0000823** The following routine is a user-defined SQL function whose purpose
824** is to test the sqlite_set_result() API.
825*/
danielk19770ae8b832004-05-25 12:05:56 +0000826static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
drh6cbe1f12002-07-01 00:31:36 +0000827 while( argc>=2 ){
drh4f26d6c2004-05-26 23:25:30 +0000828 const char *zArg0 = sqlite3_value_text(argv[0]);
danielk19776d88bad2004-05-27 14:23:36 +0000829 if( zArg0 ){
830 if( 0==sqlite3StrICmp(zArg0, "int") ){
831 sqlite3_result_int(context, sqlite3_value_int(argv[1]));
832 }else if( sqlite3StrICmp(zArg0,"int64")==0 ){
833 sqlite3_result_int64(context, sqlite3_value_int64(argv[1]));
834 }else if( sqlite3StrICmp(zArg0,"string")==0 ){
danielk1977d8123362004-06-12 09:25:12 +0000835 sqlite3_result_text(context, sqlite3_value_text(argv[1]), -1,
836 SQLITE_TRANSIENT);
danielk19776d88bad2004-05-27 14:23:36 +0000837 }else if( sqlite3StrICmp(zArg0,"double")==0 ){
838 sqlite3_result_double(context, sqlite3_value_double(argv[1]));
839 }else if( sqlite3StrICmp(zArg0,"null")==0 ){
840 sqlite3_result_null(context);
841 }else if( sqlite3StrICmp(zArg0,"value")==0 ){
842 sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]);
843 }else{
844 goto error_out;
845 }
drh6cbe1f12002-07-01 00:31:36 +0000846 }else{
danielk19776d88bad2004-05-27 14:23:36 +0000847 goto error_out;
drh6cbe1f12002-07-01 00:31:36 +0000848 }
849 argc -= 2;
850 argv += 2;
851 }
danielk19776d88bad2004-05-27 14:23:36 +0000852 return;
853
854error_out:
855 sqlite3_result_error(context,"first argument should be one of: "
856 "int int64 string double null value", -1);
drh6cbe1f12002-07-01 00:31:36 +0000857}
858
859/*
860** Usage: sqlite_register_test_function DB NAME
861**
862** Register the test SQL function on the database DB under the name NAME.
863*/
drhc2eef3b2002-08-31 18:53:06 +0000864static int test_register_func(
drh6cbe1f12002-07-01 00:31:36 +0000865 void *NotUsed,
866 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
867 int argc, /* Number of arguments */
868 char **argv /* Text of each argument */
869){
drh9bb575f2004-09-06 17:24:11 +0000870 sqlite3 *db;
drh6cbe1f12002-07-01 00:31:36 +0000871 int rc;
872 if( argc!=3 ){
873 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
874 " DB FUNCTION-NAME", 0);
875 return TCL_ERROR;
876 }
drhb86ccfb2003-01-28 23:13:10 +0000877 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk1977f9d64d22004-06-19 08:18:07 +0000878 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0,
danielk1977d8123362004-06-12 09:25:12 +0000879 testFunc, 0, 0);
drh6cbe1f12002-07-01 00:31:36 +0000880 if( rc!=0 ){
danielk1977f20b21c2004-05-31 23:56:42 +0000881 Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);
drh6cbe1f12002-07-01 00:31:36 +0000882 return TCL_ERROR;
883 }
drhc60d0442004-09-30 13:43:13 +0000884 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
drh6cbe1f12002-07-01 00:31:36 +0000885 return TCL_OK;
886}
887
888/*
danielk1977106bb232004-05-21 10:08:53 +0000889** Usage: sqlite3_finalize STMT
drhb86ccfb2003-01-28 23:13:10 +0000890**
danielk1977106bb232004-05-21 10:08:53 +0000891** Finalize a statement handle.
drhb86ccfb2003-01-28 23:13:10 +0000892*/
893static int test_finalize(
danielk1977106bb232004-05-21 10:08:53 +0000894 void * clientData,
895 Tcl_Interp *interp,
896 int objc,
897 Tcl_Obj *CONST objv[]
drhb86ccfb2003-01-28 23:13:10 +0000898){
danielk1977106bb232004-05-21 10:08:53 +0000899 sqlite3_stmt *pStmt;
drhb86ccfb2003-01-28 23:13:10 +0000900 int rc;
drhc60d0442004-09-30 13:43:13 +0000901 sqlite3 *db;
danielk1977106bb232004-05-21 10:08:53 +0000902
903 if( objc!=2 ){
904 Tcl_AppendResult(interp, "wrong # args: should be \"",
905 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
drhb86ccfb2003-01-28 23:13:10 +0000906 return TCL_ERROR;
907 }
danielk1977106bb232004-05-21 10:08:53 +0000908
909 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
910
danielk19774397de52005-01-12 12:44:03 +0000911 if( pStmt ){
912 db = StmtToDb(pStmt);
913 }
danielk1977fc57d7b2004-05-26 02:04:57 +0000914 rc = sqlite3_finalize(pStmt);
danielk1977b77f5da2004-05-26 13:27:00 +0000915 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
danielk19774397de52005-01-12 12:44:03 +0000916 if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk1977106bb232004-05-21 10:08:53 +0000917 return TCL_OK;
918}
919
920/*
921** Usage: sqlite3_reset STMT
922**
923** Finalize a statement handle.
924*/
925static int test_reset(
926 void * clientData,
927 Tcl_Interp *interp,
928 int objc,
929 Tcl_Obj *CONST objv[]
930){
931 sqlite3_stmt *pStmt;
932 int rc;
933
934 if( objc!=2 ){
935 Tcl_AppendResult(interp, "wrong # args: should be \"",
936 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
937 return TCL_ERROR;
938 }
939
940 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
941
danielk1977fc57d7b2004-05-26 02:04:57 +0000942 rc = sqlite3_reset(pStmt);
danielk19774397de52005-01-12 12:44:03 +0000943 if( pStmt &&
944 sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
945 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
danielk1977106bb232004-05-21 10:08:53 +0000946 if( rc ){
drhb86ccfb2003-01-28 23:13:10 +0000947 return TCL_ERROR;
948 }
949 return TCL_OK;
950}
951
drh5a387052003-01-11 14:19:51 +0000952/*
danielk1977fbcd5852004-06-15 02:44:18 +0000953** Usage: sqlite3_changes DB
drh50457892003-09-06 01:10:47 +0000954**
danielk1977fbcd5852004-06-15 02:44:18 +0000955** Return the number of changes made to the database by the last SQL
956** execution.
drh50457892003-09-06 01:10:47 +0000957*/
danielk1977fbcd5852004-06-15 02:44:18 +0000958static int test_changes(
959 void * clientData,
960 Tcl_Interp *interp,
961 int objc,
962 Tcl_Obj *CONST objv[]
963){
964 sqlite3 *db;
965 if( objc!=2 ){
966 Tcl_AppendResult(interp, "wrong # args: should be \"",
967 Tcl_GetString(objv[0]), " DB", 0);
968 return TCL_ERROR;
969 }
970 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
971 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db)));
972 return TCL_OK;
973}
drh50457892003-09-06 01:10:47 +0000974
975/*
drh7c972de2003-09-06 22:18:07 +0000976** This is the "static_bind_value" that variables are bound to when
danielk19776f8a5032004-05-10 10:34:51 +0000977** the FLAG option of sqlite3_bind is "static"
drh50457892003-09-06 01:10:47 +0000978*/
drh7c972de2003-09-06 22:18:07 +0000979static char *sqlite_static_bind_value = 0;
980
981/*
danielk19776f8a5032004-05-10 10:34:51 +0000982** Usage: sqlite3_bind VM IDX VALUE FLAGS
drh7c972de2003-09-06 22:18:07 +0000983**
984** Sets the value of the IDX-th occurance of "?" in the original SQL
985** string. VALUE is the new value. If FLAGS=="null" then VALUE is
986** ignored and the value is set to NULL. If FLAGS=="static" then
987** the value is set to the value of a static variable named
988** "sqlite_static_bind_value". If FLAGS=="normal" then a copy
989** of the VALUE is made.
990*/
991static int test_bind(
drh50457892003-09-06 01:10:47 +0000992 void *NotUsed,
993 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
994 int argc, /* Number of arguments */
995 char **argv /* Text of each argument */
996){
danielk1977fc57d7b2004-05-26 02:04:57 +0000997 sqlite3_stmt *pStmt;
drh50457892003-09-06 01:10:47 +0000998 int rc;
drh7c972de2003-09-06 22:18:07 +0000999 int idx;
1000 if( argc!=5 ){
drh50457892003-09-06 01:10:47 +00001001 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
drh7c972de2003-09-06 22:18:07 +00001002 " VM IDX VALUE (null|static|normal)\"", 0);
drh50457892003-09-06 01:10:47 +00001003 return TCL_ERROR;
1004 }
danielk1977fc57d7b2004-05-26 02:04:57 +00001005 if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR;
drh7c972de2003-09-06 22:18:07 +00001006 if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR;
1007 if( strcmp(argv[4],"null")==0 ){
danielk1977fc57d7b2004-05-26 02:04:57 +00001008 rc = sqlite3_bind_null(pStmt, idx);
drh7c972de2003-09-06 22:18:07 +00001009 }else if( strcmp(argv[4],"static")==0 ){
danielk1977fc57d7b2004-05-26 02:04:57 +00001010 rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0);
drh7c972de2003-09-06 22:18:07 +00001011 }else if( strcmp(argv[4],"normal")==0 ){
danielk1977d8123362004-06-12 09:25:12 +00001012 rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT);
drh7c972de2003-09-06 22:18:07 +00001013 }else{
1014 Tcl_AppendResult(interp, "4th argument should be "
1015 "\"null\" or \"static\" or \"normal\"", 0);
1016 return TCL_ERROR;
1017 }
drhc60d0442004-09-30 13:43:13 +00001018 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
drh50457892003-09-06 01:10:47 +00001019 if( rc ){
1020 char zBuf[50];
1021 sprintf(zBuf, "(%d) ", rc);
danielk1977f20b21c2004-05-31 23:56:42 +00001022 Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0);
drh50457892003-09-06 01:10:47 +00001023 return TCL_ERROR;
1024 }
1025 return TCL_OK;
1026}
1027
drh5436dc22004-11-14 04:04:17 +00001028#ifndef SQLITE_OMIT_UTF16
danielk19774e6af132004-06-10 14:01:08 +00001029/*
1030** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be>
1031**
1032** This function is used to test that SQLite selects the correct collation
1033** sequence callback when multiple versions (for different text encodings)
1034** are available.
1035**
1036** Calling this routine registers the collation sequence "test_collate"
1037** with database handle <db>. The second argument must be a list of three
1038** boolean values. If the first is true, then a version of test_collate is
1039** registered for UTF-8, if the second is true, a version is registered for
1040** UTF-16le, if the third is true, a UTF-16be version is available.
1041** Previous versions of test_collate are deleted.
1042**
1043** The collation sequence test_collate is implemented by calling the
1044** following TCL script:
1045**
1046** "test_collate <enc> <lhs> <rhs>"
1047**
1048** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8.
1049** The <enc> parameter is the encoding of the collation function that
1050** SQLite selected to call. The TCL test script implements the
1051** "test_collate" proc.
1052**
1053** Note that this will only work with one intepreter at a time, as the
1054** interp pointer to use when evaluating the TCL script is stored in
1055** pTestCollateInterp.
1056*/
1057static Tcl_Interp* pTestCollateInterp;
1058static int test_collate_func(
1059 void *pCtx,
1060 int nA, const void *zA,
1061 int nB, const void *zB
1062){
1063 Tcl_Interp *i = pTestCollateInterp;
1064 int encin = (int)pCtx;
1065 int res;
1066
1067 sqlite3_value *pVal;
1068 Tcl_Obj *pX;
1069
1070 pX = Tcl_NewStringObj("test_collate", -1);
1071 Tcl_IncrRefCount(pX);
1072
1073 switch( encin ){
1074 case SQLITE_UTF8:
1075 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1));
1076 break;
1077 case SQLITE_UTF16LE:
1078 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1));
1079 break;
1080 case SQLITE_UTF16BE:
1081 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1));
1082 break;
1083 default:
1084 assert(0);
1085 }
1086
1087 pVal = sqlite3ValueNew();
danielk1977bfd6cce2004-06-18 04:24:54 +00001088 sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC);
danielk19774e6af132004-06-10 14:01:08 +00001089 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),-1));
danielk1977bfd6cce2004-06-18 04:24:54 +00001090 sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC);
danielk19774e6af132004-06-10 14:01:08 +00001091 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),-1));
1092 sqlite3ValueFree(pVal);
1093
1094 Tcl_EvalObjEx(i, pX, 0);
1095 Tcl_DecrRefCount(pX);
1096 Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res);
1097 return res;
1098}
1099static int test_collate(
1100 void * clientData,
1101 Tcl_Interp *interp,
1102 int objc,
1103 Tcl_Obj *CONST objv[]
1104){
1105 sqlite3 *db;
1106 int val;
danielk1977312d6b32004-06-29 13:18:23 +00001107 sqlite3_value *pVal;
drhc60d0442004-09-30 13:43:13 +00001108 int rc;
danielk19774e6af132004-06-10 14:01:08 +00001109
1110 if( objc!=5 ) goto bad_args;
1111 pTestCollateInterp = interp;
1112 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1113
1114 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +00001115 rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8,
1116 (void *)SQLITE_UTF8, val?test_collate_func:0);
1117 if( rc==SQLITE_OK ){
1118 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
1119 rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE,
1120 (void *)SQLITE_UTF16LE, val?test_collate_func:0);
1121 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
danielk1977312d6b32004-06-29 13:18:23 +00001122
drhc60d0442004-09-30 13:43:13 +00001123 pVal = sqlite3ValueNew();
1124 sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC);
1125 sqlite3_create_collation16(db, sqlite3ValueText(pVal, SQLITE_UTF16NATIVE),
1126 SQLITE_UTF16BE, (void *)SQLITE_UTF16BE, val?test_collate_func:0);
1127 sqlite3ValueFree(pVal);
1128 }
1129 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk19774e6af132004-06-10 14:01:08 +00001130 return TCL_OK;
1131
1132bad_args:
1133 Tcl_AppendResult(interp, "wrong # args: should be \"",
1134 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
1135 return TCL_ERROR;
1136}
1137
danielk1977312d6b32004-06-29 13:18:23 +00001138static void test_collate_needed_cb(
1139 void *pCtx,
1140 sqlite3 *db,
1141 int eTextRep,
1142 const void *notUsed
1143){
1144 int enc = db->enc;
1145 sqlite3_create_collation(
1146 db, "test_collate", db->enc, (void *)enc, test_collate_func);
1147}
1148
1149/*
1150** Usage: add_test_collate_needed DB
1151*/
1152static int test_collate_needed(
1153 void * clientData,
1154 Tcl_Interp *interp,
1155 int objc,
1156 Tcl_Obj *CONST objv[]
1157){
1158 sqlite3 *db;
drhc60d0442004-09-30 13:43:13 +00001159 int rc;
danielk1977312d6b32004-06-29 13:18:23 +00001160
1161 if( objc!=2 ) goto bad_args;
1162 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
drhc60d0442004-09-30 13:43:13 +00001163 rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb);
1164 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk1977312d6b32004-06-29 13:18:23 +00001165 return TCL_OK;
1166
1167bad_args:
1168 Tcl_WrongNumArgs(interp, 1, objv, "DB");
1169 return TCL_ERROR;
1170}
drh5436dc22004-11-14 04:04:17 +00001171#endif /* SQLITE_OMIT_UTF16 */
danielk1977312d6b32004-06-29 13:18:23 +00001172
danielk1977c8e9a2d2004-06-25 12:08:46 +00001173/*
1174** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
1175**
1176** This function is used to test that SQLite selects the correct user
1177** function callback when multiple versions (for different text encodings)
1178** are available.
1179**
1180** Calling this routine registers up to three versions of the user function
1181** "test_function" with database handle <db>. If the second argument is
1182** true, then a version of test_function is registered for UTF-8, if the
1183** third is true, a version is registered for UTF-16le, if the fourth is
1184** true, a UTF-16be version is available. Previous versions of
1185** test_function are deleted.
1186**
1187** The user function is implemented by calling the following TCL script:
1188**
1189** "test_function <enc> <arg>"
1190**
1191** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the
1192** single argument passed to the SQL function. The value returned by
1193** the TCL script is used as the return value of the SQL function. It
1194** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8
1195** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
1196** prefers UTF-16BE.
1197*/
drh5436dc22004-11-14 04:04:17 +00001198#ifndef SQLITE_OMIT_UTF16
danielk1977c8e9a2d2004-06-25 12:08:46 +00001199static void test_function_utf8(
1200 sqlite3_context *pCtx,
1201 int nArg,
1202 sqlite3_value **argv
1203){
1204 Tcl_Interp *interp;
1205 Tcl_Obj *pX;
1206 sqlite3_value *pVal;
1207 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1208 pX = Tcl_NewStringObj("test_function", -1);
1209 Tcl_IncrRefCount(pX);
1210 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1));
1211 Tcl_ListObjAppendElement(interp, pX,
1212 Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1));
1213 Tcl_EvalObjEx(interp, pX, 0);
1214 Tcl_DecrRefCount(pX);
1215 sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT);
1216 pVal = sqlite3ValueNew();
1217 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1218 SQLITE_UTF8, SQLITE_STATIC);
1219 sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal),
1220 -1, SQLITE_TRANSIENT);
1221 sqlite3ValueFree(pVal);
1222}
1223static void test_function_utf16le(
1224 sqlite3_context *pCtx,
1225 int nArg,
1226 sqlite3_value **argv
1227){
1228 Tcl_Interp *interp;
1229 Tcl_Obj *pX;
1230 sqlite3_value *pVal;
1231 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1232 pX = Tcl_NewStringObj("test_function", -1);
1233 Tcl_IncrRefCount(pX);
1234 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1));
1235 Tcl_ListObjAppendElement(interp, pX,
1236 Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1));
1237 Tcl_EvalObjEx(interp, pX, 0);
1238 Tcl_DecrRefCount(pX);
1239 pVal = sqlite3ValueNew();
1240 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1241 SQLITE_UTF8, SQLITE_STATIC);
1242 sqlite3_result_text(pCtx,sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT);
1243 sqlite3ValueFree(pVal);
1244}
1245static void test_function_utf16be(
1246 sqlite3_context *pCtx,
1247 int nArg,
1248 sqlite3_value **argv
1249){
1250 Tcl_Interp *interp;
1251 Tcl_Obj *pX;
1252 sqlite3_value *pVal;
1253 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1254 pX = Tcl_NewStringObj("test_function", -1);
1255 Tcl_IncrRefCount(pX);
1256 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1));
1257 Tcl_ListObjAppendElement(interp, pX,
1258 Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1));
1259 Tcl_EvalObjEx(interp, pX, 0);
1260 Tcl_DecrRefCount(pX);
1261 pVal = sqlite3ValueNew();
1262 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1263 SQLITE_UTF8, SQLITE_STATIC);
1264 sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal),
1265 -1, SQLITE_TRANSIENT);
1266 sqlite3ValueFree(pVal);
1267}
drh5436dc22004-11-14 04:04:17 +00001268#endif /* SQLITE_OMIT_UTF16 */
danielk1977c8e9a2d2004-06-25 12:08:46 +00001269static int test_function(
1270 void * clientData,
1271 Tcl_Interp *interp,
1272 int objc,
1273 Tcl_Obj *CONST objv[]
1274){
drh5436dc22004-11-14 04:04:17 +00001275#ifndef SQLITE_OMIT_UTF16
danielk1977c8e9a2d2004-06-25 12:08:46 +00001276 sqlite3 *db;
1277 int val;
1278
1279 if( objc!=5 ) goto bad_args;
1280 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1281
1282 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
1283 if( val ){
1284 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8,
1285 interp, test_function_utf8, 0, 0);
1286 }
1287 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
1288 if( val ){
1289 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE,
1290 interp, test_function_utf16le, 0, 0);
1291 }
1292 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
1293 if( val ){
1294 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE,
1295 interp, test_function_utf16be, 0, 0);
1296 }
1297
1298 return TCL_OK;
1299bad_args:
1300 Tcl_AppendResult(interp, "wrong # args: should be \"",
1301 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
drh5436dc22004-11-14 04:04:17 +00001302#endif /* SQLITE_OMIT_UTF16 */
danielk1977c8e9a2d2004-06-25 12:08:46 +00001303 return TCL_ERROR;
1304}
1305
danielk1977312d6b32004-06-29 13:18:23 +00001306/*
1307** Usage: test_errstr <err code>
1308**
1309** Test that the english language string equivalents for sqlite error codes
1310** are sane. The parameter is an integer representing an sqlite error code.
1311** The result is a list of two elements, the string representation of the
1312** error code and the english language explanation.
1313*/
1314static int test_errstr(
1315 void * clientData,
1316 Tcl_Interp *interp,
1317 int objc,
1318 Tcl_Obj *CONST objv[]
1319){
1320 char *zCode;
1321 int i;
1322 if( objc!=1 ){
1323 Tcl_WrongNumArgs(interp, 1, objv, "<error code>");
1324 }
1325
1326 zCode = Tcl_GetString(objv[1]);
1327 for(i=0; i<200; i++){
1328 if( 0==strcmp(errorName(i), zCode) ) break;
1329 }
1330 Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0);
1331 return TCL_OK;
1332}
1333
danielk1977c8e9a2d2004-06-25 12:08:46 +00001334static int sqlite3_crashparams(
danielk19778a6c5502004-06-22 12:18:32 +00001335 void * clientData,
1336 Tcl_Interp *interp,
1337 int objc,
1338 Tcl_Obj *CONST objv[]
1339){
1340#ifdef OS_TEST
danielk1977c8e9a2d2004-06-25 12:08:46 +00001341 int delay;
1342 if( objc!=3 ) goto bad_args;
1343 if( Tcl_GetIntFromObj(interp, objv[1], &delay) ) return TCL_ERROR;
1344 sqlite3SetCrashParams(delay, Tcl_GetString(objv[2]));
danielk19778a6c5502004-06-22 12:18:32 +00001345#endif
1346 return TCL_OK;
1347
drh241db312004-06-22 12:46:53 +00001348#ifdef OS_TEST
danielk19778a6c5502004-06-22 12:18:32 +00001349bad_args:
1350 Tcl_AppendResult(interp, "wrong # args: should be \"",
danielk1977c8e9a2d2004-06-25 12:08:46 +00001351 Tcl_GetStringFromObj(objv[0], 0), "<delay> <filename>", 0);
danielk19778a6c5502004-06-22 12:18:32 +00001352 return TCL_ERROR;
drh241db312004-06-22 12:46:53 +00001353#endif
danielk19778a6c5502004-06-22 12:18:32 +00001354}
1355
1356
drh50457892003-09-06 01:10:47 +00001357/*
drh99ee3602003-02-16 19:13:36 +00001358** Usage: breakpoint
1359**
1360** This routine exists for one purpose - to provide a place to put a
1361** breakpoint with GDB that can be triggered using TCL code. The use
1362** for this is when a particular test fails on (say) the 1485th iteration.
1363** In the TCL test script, we can add code like this:
1364**
1365** if {$i==1485} breakpoint
1366**
1367** Then run testfixture in the debugger and wait for the breakpoint to
1368** fire. Then additional breakpoints can be set to trace down the bug.
1369*/
1370static int test_breakpoint(
1371 void *NotUsed,
1372 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1373 int argc, /* Number of arguments */
1374 char **argv /* Text of each argument */
1375){
1376 return TCL_OK; /* Do nothing */
1377}
1378
drh241db312004-06-22 12:46:53 +00001379/*
1380** Usage: sqlite3_bind_int STMT N VALUE
1381**
1382** Test the sqlite3_bind_int interface. STMT is a prepared statement.
1383** N is the index of a wildcard in the prepared statement. This command
1384** binds a 32-bit integer VALUE to that wildcard.
1385*/
1386static int test_bind_int(
danielk197751e3d8e2004-05-20 01:12:34 +00001387 void * clientData,
1388 Tcl_Interp *interp,
1389 int objc,
1390 Tcl_Obj *CONST objv[]
1391){
1392 sqlite3_stmt *pStmt;
1393 int idx;
1394 int value;
1395 int rc;
1396
1397 if( objc!=4 ){
1398 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001399 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001400 return TCL_ERROR;
1401 }
1402
1403 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1404 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1405 if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
1406
danielk1977c572ef72004-05-27 09:28:41 +00001407 rc = sqlite3_bind_int(pStmt, idx, value);
drhc60d0442004-09-30 13:43:13 +00001408 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001409 if( rc!=SQLITE_OK ){
1410 return TCL_ERROR;
1411 }
1412
1413 return TCL_OK;
1414}
1415
drh241db312004-06-22 12:46:53 +00001416
1417/*
1418** Usage: sqlite3_bind_int64 STMT N VALUE
1419**
1420** Test the sqlite3_bind_int64 interface. STMT is a prepared statement.
1421** N is the index of a wildcard in the prepared statement. This command
1422** binds a 64-bit integer VALUE to that wildcard.
1423*/
danielk197751e3d8e2004-05-20 01:12:34 +00001424static int test_bind_int64(
1425 void * clientData,
1426 Tcl_Interp *interp,
1427 int objc,
1428 Tcl_Obj *CONST objv[]
1429){
1430 sqlite3_stmt *pStmt;
1431 int idx;
1432 i64 value;
1433 int rc;
1434
1435 if( objc!=4 ){
1436 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001437 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001438 return TCL_ERROR;
1439 }
1440
1441 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1442 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1443 if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
1444
1445 rc = sqlite3_bind_int64(pStmt, idx, value);
drhc60d0442004-09-30 13:43:13 +00001446 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001447 if( rc!=SQLITE_OK ){
1448 return TCL_ERROR;
1449 }
1450
1451 return TCL_OK;
1452}
1453
drh241db312004-06-22 12:46:53 +00001454
1455/*
1456** Usage: sqlite3_bind_double STMT N VALUE
1457**
1458** Test the sqlite3_bind_double interface. STMT is a prepared statement.
1459** N is the index of a wildcard in the prepared statement. This command
1460** binds a 64-bit integer VALUE to that wildcard.
1461*/
danielk197751e3d8e2004-05-20 01:12:34 +00001462static int test_bind_double(
1463 void * clientData,
1464 Tcl_Interp *interp,
1465 int objc,
1466 Tcl_Obj *CONST objv[]
1467){
1468 sqlite3_stmt *pStmt;
1469 int idx;
1470 double value;
1471 int rc;
1472
1473 if( objc!=4 ){
1474 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001475 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001476 return TCL_ERROR;
1477 }
1478
1479 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1480 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1481 if( Tcl_GetDoubleFromObj(interp, objv[3], &value) ) return TCL_ERROR;
1482
1483 rc = sqlite3_bind_double(pStmt, idx, value);
drhc60d0442004-09-30 13:43:13 +00001484 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001485 if( rc!=SQLITE_OK ){
1486 return TCL_ERROR;
1487 }
1488
1489 return TCL_OK;
1490}
1491
drh241db312004-06-22 12:46:53 +00001492/*
1493** Usage: sqlite3_bind_null STMT N
1494**
1495** Test the sqlite3_bind_null interface. STMT is a prepared statement.
1496** N is the index of a wildcard in the prepared statement. This command
1497** binds a NULL to the wildcard.
1498*/
danielk197751e3d8e2004-05-20 01:12:34 +00001499static int test_bind_null(
1500 void * clientData,
1501 Tcl_Interp *interp,
1502 int objc,
1503 Tcl_Obj *CONST objv[]
1504){
1505 sqlite3_stmt *pStmt;
1506 int idx;
1507 int rc;
1508
1509 if( objc!=3 ){
1510 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001511 Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001512 return TCL_ERROR;
1513 }
1514
1515 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1516 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1517
1518 rc = sqlite3_bind_null(pStmt, idx);
drhc60d0442004-09-30 13:43:13 +00001519 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001520 if( rc!=SQLITE_OK ){
1521 return TCL_ERROR;
1522 }
1523
1524 return TCL_OK;
1525}
1526
drh241db312004-06-22 12:46:53 +00001527/*
1528** Usage: sqlite3_bind_text STMT N STRING BYTES
1529**
1530** Test the sqlite3_bind_text interface. STMT is a prepared statement.
1531** N is the index of a wildcard in the prepared statement. This command
1532** binds a UTF-8 string STRING to the wildcard. The string is BYTES bytes
1533** long.
1534*/
danielk197751e3d8e2004-05-20 01:12:34 +00001535static int test_bind_text(
1536 void * clientData,
1537 Tcl_Interp *interp,
1538 int objc,
1539 Tcl_Obj *CONST objv[]
1540){
1541 sqlite3_stmt *pStmt;
1542 int idx;
1543 int bytes;
1544 char *value;
1545 int rc;
1546
1547 if( objc!=5 ){
1548 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001549 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001550 return TCL_ERROR;
1551 }
1552
1553 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1554 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1555 value = Tcl_GetString(objv[3]);
1556 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
1557
danielk1977d8123362004-06-12 09:25:12 +00001558 rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
drhc60d0442004-09-30 13:43:13 +00001559 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001560 if( rc!=SQLITE_OK ){
1561 return TCL_ERROR;
1562 }
1563
1564 return TCL_OK;
1565}
1566
drh241db312004-06-22 12:46:53 +00001567/*
1568** Usage: sqlite3_bind_text16 STMT N STRING BYTES
1569**
1570** Test the sqlite3_bind_text16 interface. STMT is a prepared statement.
1571** N is the index of a wildcard in the prepared statement. This command
1572** binds a UTF-16 string STRING to the wildcard. The string is BYTES bytes
1573** long.
1574*/
danielk197751e3d8e2004-05-20 01:12:34 +00001575static int test_bind_text16(
1576 void * clientData,
1577 Tcl_Interp *interp,
1578 int objc,
1579 Tcl_Obj *CONST objv[]
1580){
drh5436dc22004-11-14 04:04:17 +00001581#ifndef SQLITE_OMIT_UTF16
danielk197751e3d8e2004-05-20 01:12:34 +00001582 sqlite3_stmt *pStmt;
1583 int idx;
1584 int bytes;
1585 char *value;
1586 int rc;
1587
1588 if( objc!=5 ){
1589 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001590 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001591 return TCL_ERROR;
1592 }
1593
1594 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1595 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1596 value = Tcl_GetByteArrayFromObj(objv[3], 0);
1597 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
1598
danielk1977d8123362004-06-12 09:25:12 +00001599 rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, SQLITE_TRANSIENT);
drhc60d0442004-09-30 13:43:13 +00001600 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001601 if( rc!=SQLITE_OK ){
1602 return TCL_ERROR;
1603 }
1604
drh5436dc22004-11-14 04:04:17 +00001605#endif /* SQLITE_OMIT_UTF16 */
danielk197751e3d8e2004-05-20 01:12:34 +00001606 return TCL_OK;
1607}
1608
drh241db312004-06-22 12:46:53 +00001609/*
1610** Usage: sqlite3_bind_blob STMT N DATA BYTES
1611**
1612** Test the sqlite3_bind_blob interface. STMT is a prepared statement.
1613** N is the index of a wildcard in the prepared statement. This command
1614** binds a BLOB to the wildcard. The BLOB is BYTES bytes in size.
1615*/
danielk197751e3d8e2004-05-20 01:12:34 +00001616static int test_bind_blob(
1617 void * clientData,
1618 Tcl_Interp *interp,
1619 int objc,
1620 Tcl_Obj *CONST objv[]
1621){
1622 sqlite3_stmt *pStmt;
1623 int idx;
1624 int bytes;
1625 char *value;
1626 int rc;
1627
1628 if( objc!=5 ){
1629 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001630 Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001631 return TCL_ERROR;
1632 }
1633
1634 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1635 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1636 value = Tcl_GetString(objv[3]);
danielk197749e46432004-05-27 13:55:27 +00001637 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001638
danielk1977d8123362004-06-12 09:25:12 +00001639 rc = sqlite3_bind_blob(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
drhc60d0442004-09-30 13:43:13 +00001640 if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001641 if( rc!=SQLITE_OK ){
1642 return TCL_ERROR;
1643 }
1644
1645 return TCL_OK;
1646}
1647
drh99ee3602003-02-16 19:13:36 +00001648/*
drh75f6a032004-07-15 14:15:00 +00001649** Usage: sqlite3_bind_parameter_count STMT
1650**
1651** Return the number of wildcards in the given statement.
1652*/
1653static int test_bind_parameter_count(
1654 void * clientData,
1655 Tcl_Interp *interp,
1656 int objc,
1657 Tcl_Obj *CONST objv[]
1658){
1659 sqlite3_stmt *pStmt;
1660
1661 if( objc!=2 ){
1662 Tcl_WrongNumArgs(interp, 1, objv, "STMT");
1663 return TCL_ERROR;
1664 }
1665 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1666 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt)));
1667 return TCL_OK;
1668}
1669
1670/*
drh895d7472004-08-20 16:02:39 +00001671** Usage: sqlite3_bind_parameter_name STMT N
1672**
1673** Return the name of the Nth wildcard. The first wildcard is 1.
1674** An empty string is returned if N is out of range or if the wildcard
1675** is nameless.
1676*/
1677static int test_bind_parameter_name(
1678 void * clientData,
1679 Tcl_Interp *interp,
1680 int objc,
1681 Tcl_Obj *CONST objv[]
1682){
1683 sqlite3_stmt *pStmt;
1684 int i;
1685
1686 if( objc!=3 ){
1687 Tcl_WrongNumArgs(interp, 1, objv, "STMT N");
1688 return TCL_ERROR;
1689 }
1690 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1691 if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR;
1692 Tcl_SetObjResult(interp,
1693 Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1)
1694 );
1695 return TCL_OK;
1696}
1697
1698/*
drhfa6bc002004-09-07 16:19:52 +00001699** Usage: sqlite3_bind_parameter_index STMT NAME
1700**
1701** Return the index of the wildcard called NAME. Return 0 if there is
1702** no such wildcard.
1703*/
1704static int test_bind_parameter_index(
1705 void * clientData,
1706 Tcl_Interp *interp,
1707 int objc,
1708 Tcl_Obj *CONST objv[]
1709){
1710 sqlite3_stmt *pStmt;
1711
1712 if( objc!=3 ){
1713 Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME");
1714 return TCL_ERROR;
1715 }
1716 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1717 Tcl_SetObjResult(interp,
1718 Tcl_NewIntObj(
1719 sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2]))
1720 )
1721 );
1722 return TCL_OK;
1723}
1724
1725/*
danielk19776622cce2004-05-20 11:00:52 +00001726** Usage: sqlite3_errcode DB
1727**
1728** Return the string representation of the most recent sqlite3_* API
1729** error code. e.g. "SQLITE_ERROR".
1730*/
1731static int test_errcode(
1732 void * clientData,
1733 Tcl_Interp *interp,
1734 int objc,
1735 Tcl_Obj *CONST objv[]
1736){
1737 sqlite3 *db;
1738
1739 if( objc!=2 ){
1740 Tcl_AppendResult(interp, "wrong # args: should be \"",
1741 Tcl_GetString(objv[0]), " DB", 0);
1742 return TCL_ERROR;
1743 }
1744 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1745 Tcl_SetResult(interp, (char *)errorName(sqlite3_errcode(db)), 0);
1746 return TCL_OK;
1747}
1748
1749/*
1750** Usage: test_errmsg DB
1751**
1752** Returns the UTF-8 representation of the error message string for the
1753** most recent sqlite3_* API call.
1754*/
1755static int test_errmsg(
1756 void * clientData,
1757 Tcl_Interp *interp,
1758 int objc,
1759 Tcl_Obj *CONST objv[]
1760){
drh9bb575f2004-09-06 17:24:11 +00001761 sqlite3 *db;
danielk19776622cce2004-05-20 11:00:52 +00001762 const char *zErr;
1763
1764 if( objc!=2 ){
1765 Tcl_AppendResult(interp, "wrong # args: should be \"",
1766 Tcl_GetString(objv[0]), " DB", 0);
1767 return TCL_ERROR;
1768 }
1769 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1770
1771 zErr = sqlite3_errmsg(db);
1772 Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
1773 return TCL_OK;
1774}
1775
1776/*
1777** Usage: test_errmsg16 DB
1778**
1779** Returns the UTF-16 representation of the error message string for the
1780** most recent sqlite3_* API call. This is a byte array object at the TCL
1781** level, and it includes the 0x00 0x00 terminator bytes at the end of the
1782** UTF-16 string.
1783*/
1784static int test_errmsg16(
1785 void * clientData,
1786 Tcl_Interp *interp,
1787 int objc,
1788 Tcl_Obj *CONST objv[]
1789){
drh5436dc22004-11-14 04:04:17 +00001790#ifndef SQLITE_OMIT_UTF16
drh9bb575f2004-09-06 17:24:11 +00001791 sqlite3 *db;
danielk19776622cce2004-05-20 11:00:52 +00001792 const void *zErr;
1793 int bytes;
1794
1795 if( objc!=2 ){
1796 Tcl_AppendResult(interp, "wrong # args: should be \"",
1797 Tcl_GetString(objv[0]), " DB", 0);
1798 return TCL_ERROR;
1799 }
1800 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1801
1802 zErr = sqlite3_errmsg16(db);
1803 bytes = sqlite3utf16ByteLen(zErr, -1);
1804 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes));
drh5436dc22004-11-14 04:04:17 +00001805#endif /* SQLITE_OMIT_UTF16 */
danielk19776622cce2004-05-20 11:00:52 +00001806 return TCL_OK;
1807}
1808
1809/*
1810** Usage: sqlite3_prepare DB sql bytes tailvar
1811**
1812** Compile up to <bytes> bytes of the supplied SQL string <sql> using
1813** database handle <DB>. The parameter <tailval> is the name of a global
1814** variable that is set to the unused portion of <sql> (if any). A
1815** STMT handle is returned.
1816*/
1817static int test_prepare(
1818 void * clientData,
1819 Tcl_Interp *interp,
1820 int objc,
1821 Tcl_Obj *CONST objv[]
1822){
1823 sqlite3 *db;
1824 const char *zSql;
1825 int bytes;
1826 const char *zTail = 0;
1827 sqlite3_stmt *pStmt = 0;
1828 char zBuf[50];
danielk19774ad17132004-05-21 01:47:26 +00001829 int rc;
danielk19776622cce2004-05-20 11:00:52 +00001830
1831 if( objc!=5 ){
1832 Tcl_AppendResult(interp, "wrong # args: should be \"",
1833 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
1834 return TCL_ERROR;
1835 }
1836 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1837 zSql = Tcl_GetString(objv[2]);
1838 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
1839
danielk19774ad17132004-05-21 01:47:26 +00001840 rc = sqlite3_prepare(db, zSql, bytes, &pStmt, &zTail);
drhc60d0442004-09-30 13:43:13 +00001841 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
danielk19776622cce2004-05-20 11:00:52 +00001842 if( zTail ){
1843 if( bytes>=0 ){
1844 bytes = bytes - (zTail-zSql);
1845 }
1846 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
1847 }
danielk19774ad17132004-05-21 01:47:26 +00001848 if( rc!=SQLITE_OK ){
1849 assert( pStmt==0 );
1850 sprintf(zBuf, "(%d) ", rc);
1851 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
1852 return TCL_ERROR;
1853 }
danielk19776622cce2004-05-20 11:00:52 +00001854
danielk19774ad17132004-05-21 01:47:26 +00001855 if( pStmt ){
1856 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
1857 Tcl_AppendResult(interp, zBuf, 0);
1858 }
danielk19776622cce2004-05-20 11:00:52 +00001859 return TCL_OK;
1860}
1861
1862/*
1863** Usage: sqlite3_prepare DB sql bytes tailvar
1864**
1865** Compile up to <bytes> bytes of the supplied SQL string <sql> using
1866** database handle <DB>. The parameter <tailval> is the name of a global
1867** variable that is set to the unused portion of <sql> (if any). A
1868** STMT handle is returned.
1869*/
1870static int test_prepare16(
1871 void * clientData,
1872 Tcl_Interp *interp,
1873 int objc,
1874 Tcl_Obj *CONST objv[]
1875){
drh5436dc22004-11-14 04:04:17 +00001876#ifndef SQLITE_OMIT_UTF16
danielk19776622cce2004-05-20 11:00:52 +00001877 sqlite3 *db;
1878 const void *zSql;
1879 const void *zTail = 0;
1880 Tcl_Obj *pTail = 0;
1881 sqlite3_stmt *pStmt = 0;
drhc60d0442004-09-30 13:43:13 +00001882 char zBuf[50];
1883 int rc;
danielk19776622cce2004-05-20 11:00:52 +00001884 int bytes; /* The integer specified as arg 3 */
1885 int objlen; /* The byte-array length of arg 2 */
1886
1887 if( objc!=5 ){
1888 Tcl_AppendResult(interp, "wrong # args: should be \"",
1889 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
1890 return TCL_ERROR;
1891 }
1892 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1893 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
1894 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
1895
drhc60d0442004-09-30 13:43:13 +00001896 rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, &zTail);
1897 if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
1898 if( rc ){
danielk19776622cce2004-05-20 11:00:52 +00001899 return TCL_ERROR;
1900 }
1901
1902 if( zTail ){
1903 objlen = objlen - ((u8 *)zTail-(u8 *)zSql);
1904 }else{
1905 objlen = 0;
1906 }
1907 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
1908 Tcl_IncrRefCount(pTail);
1909 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
danielk19774ad17132004-05-21 01:47:26 +00001910 Tcl_DecrRefCount(pTail);
danielk19776622cce2004-05-20 11:00:52 +00001911
danielk19774ad17132004-05-21 01:47:26 +00001912 if( pStmt ){
1913 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
1914 }
danielk19776622cce2004-05-20 11:00:52 +00001915 Tcl_AppendResult(interp, zBuf, 0);
drh5436dc22004-11-14 04:04:17 +00001916#endif /* SQLITE_OMIT_UTF16 */
danielk19776622cce2004-05-20 11:00:52 +00001917 return TCL_OK;
1918}
1919
danielk19774ad17132004-05-21 01:47:26 +00001920/*
1921** Usage: sqlite3_open filename ?options-list?
1922*/
1923static int test_open(
1924 void * clientData,
1925 Tcl_Interp *interp,
1926 int objc,
1927 Tcl_Obj *CONST objv[]
1928){
1929 const char *zFilename;
1930 sqlite3 *db;
1931 int rc;
1932 char zBuf[100];
1933
1934 if( objc!=3 && objc!=2 ){
1935 Tcl_AppendResult(interp, "wrong # args: should be \"",
1936 Tcl_GetString(objv[0]), " filename options-list", 0);
1937 return TCL_ERROR;
1938 }
1939
1940 zFilename = Tcl_GetString(objv[1]);
danielk19774f057f92004-06-08 00:02:33 +00001941 rc = sqlite3_open(zFilename, &db);
danielk19774ad17132004-05-21 01:47:26 +00001942
1943 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR;
1944 Tcl_AppendResult(interp, zBuf, 0);
1945 return TCL_OK;
1946}
1947
1948/*
1949** Usage: sqlite3_open16 filename options
1950*/
1951static int test_open16(
1952 void * clientData,
1953 Tcl_Interp *interp,
1954 int objc,
1955 Tcl_Obj *CONST objv[]
1956){
drh5436dc22004-11-14 04:04:17 +00001957#ifndef SQLITE_OMIT_UTF16
danielk19774ad17132004-05-21 01:47:26 +00001958 const void *zFilename;
1959 sqlite3 *db;
1960 int rc;
1961 char zBuf[100];
1962
1963 if( objc!=3 ){
1964 Tcl_AppendResult(interp, "wrong # args: should be \"",
1965 Tcl_GetString(objv[0]), " filename options-list", 0);
1966 return TCL_ERROR;
1967 }
1968
1969 zFilename = Tcl_GetByteArrayFromObj(objv[1], 0);
danielk19774f057f92004-06-08 00:02:33 +00001970 rc = sqlite3_open16(zFilename, &db);
danielk19774ad17132004-05-21 01:47:26 +00001971
1972 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR;
1973 Tcl_AppendResult(interp, zBuf, 0);
drh5436dc22004-11-14 04:04:17 +00001974#endif /* SQLITE_OMIT_UTF16 */
danielk19774ad17132004-05-21 01:47:26 +00001975 return TCL_OK;
1976}
drhd3d39e92004-05-20 22:16:29 +00001977
1978/*
danielk1977bc6ada42004-06-30 08:20:16 +00001979** Usage: sqlite3_complete16 <UTF-16 string>
1980**
1981** Return 1 if the supplied argument is a complete SQL statement, or zero
1982** otherwise.
1983*/
1984static int test_complete16(
1985 void * clientData,
1986 Tcl_Interp *interp,
1987 int objc,
1988 Tcl_Obj *CONST objv[]
1989){
drh5436dc22004-11-14 04:04:17 +00001990#ifndef SQLITE_OMIT_UTF16
danielk1977bc6ada42004-06-30 08:20:16 +00001991 char *zBuf;
1992
1993 if( objc!=2 ){
1994 Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>");
1995 return TCL_ERROR;
1996 }
1997
1998 zBuf = Tcl_GetByteArrayFromObj(objv[1], 0);
1999 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf)));
drh5436dc22004-11-14 04:04:17 +00002000#endif /* SQLITE_OMIT_UTF16 */
danielk1977bc6ada42004-06-30 08:20:16 +00002001 return TCL_OK;
2002}
2003
2004/*
danielk1977106bb232004-05-21 10:08:53 +00002005** Usage: sqlite3_step STMT
2006**
2007** Advance the statement to the next row.
2008*/
danielk197717240fd2004-05-26 00:07:25 +00002009static int test_step(
danielk1977106bb232004-05-21 10:08:53 +00002010 void * clientData,
2011 Tcl_Interp *interp,
2012 int objc,
2013 Tcl_Obj *CONST objv[]
2014){
2015 sqlite3_stmt *pStmt;
2016 int rc;
2017
danielk1977e1cd9872004-05-22 10:33:04 +00002018 if( objc!=2 ){
danielk1977106bb232004-05-21 10:08:53 +00002019 Tcl_AppendResult(interp, "wrong # args: should be \"",
2020 Tcl_GetString(objv[0]), " STMT", 0);
2021 return TCL_ERROR;
2022 }
2023
2024 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
danielk197717240fd2004-05-26 00:07:25 +00002025 rc = sqlite3_step(pStmt);
danielk1977106bb232004-05-21 10:08:53 +00002026
danielk1977fbcd5852004-06-15 02:44:18 +00002027 /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */
danielk197765904932004-05-26 06:18:37 +00002028 Tcl_SetResult(interp, (char *)errorName(rc), 0);
danielk1977e1cd9872004-05-22 10:33:04 +00002029 return TCL_OK;
2030}
2031
2032/*
danielk197717240fd2004-05-26 00:07:25 +00002033** Usage: sqlite3_column_count STMT
2034**
2035** Return the number of columns returned by the sql statement STMT.
2036*/
2037static int test_column_count(
2038 void * clientData,
2039 Tcl_Interp *interp,
2040 int objc,
2041 Tcl_Obj *CONST objv[]
2042){
2043 sqlite3_stmt *pStmt;
2044
2045 if( objc!=2 ){
2046 Tcl_AppendResult(interp, "wrong # args: should be \"",
2047 Tcl_GetString(objv[0]), " STMT column", 0);
2048 return TCL_ERROR;
2049 }
2050
2051 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2052
2053 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt)));
2054 return TCL_OK;
2055}
2056
2057/*
danielk19773cf86062004-05-26 10:11:05 +00002058** Usage: sqlite3_column_type STMT column
2059**
2060** Return the type of the data in column 'column' of the current row.
2061*/
2062static int test_column_type(
2063 void * clientData,
2064 Tcl_Interp *interp,
2065 int objc,
2066 Tcl_Obj *CONST objv[]
2067){
2068 sqlite3_stmt *pStmt;
2069 int col;
2070 int tp;
2071
2072 if( objc!=3 ){
2073 Tcl_AppendResult(interp, "wrong # args: should be \"",
2074 Tcl_GetString(objv[0]), " STMT column", 0);
2075 return TCL_ERROR;
2076 }
2077
2078 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2079 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2080
2081 tp = sqlite3_column_type(pStmt, col);
2082 switch( tp ){
drh9c054832004-05-31 18:51:57 +00002083 case SQLITE_INTEGER:
danielk19773cf86062004-05-26 10:11:05 +00002084 Tcl_SetResult(interp, "INTEGER", TCL_STATIC);
2085 break;
drh9c054832004-05-31 18:51:57 +00002086 case SQLITE_NULL:
danielk19773cf86062004-05-26 10:11:05 +00002087 Tcl_SetResult(interp, "NULL", TCL_STATIC);
2088 break;
drh9c054832004-05-31 18:51:57 +00002089 case SQLITE_FLOAT:
danielk19773cf86062004-05-26 10:11:05 +00002090 Tcl_SetResult(interp, "FLOAT", TCL_STATIC);
2091 break;
drh9c054832004-05-31 18:51:57 +00002092 case SQLITE_TEXT:
danielk19773cf86062004-05-26 10:11:05 +00002093 Tcl_SetResult(interp, "TEXT", TCL_STATIC);
2094 break;
drh9c054832004-05-31 18:51:57 +00002095 case SQLITE_BLOB:
danielk19773cf86062004-05-26 10:11:05 +00002096 Tcl_SetResult(interp, "BLOB", TCL_STATIC);
2097 break;
2098 default:
2099 assert(0);
2100 }
2101
2102 return TCL_OK;
2103}
2104
2105/*
danielk197704f2e682004-05-27 01:04:07 +00002106** Usage: sqlite3_column_int64 STMT column
danielk19773cf86062004-05-26 10:11:05 +00002107**
2108** Return the data in column 'column' of the current row cast as an
danielk197704f2e682004-05-27 01:04:07 +00002109** wide (64-bit) integer.
danielk19773cf86062004-05-26 10:11:05 +00002110*/
danielk197704f2e682004-05-27 01:04:07 +00002111static int test_column_int64(
danielk19773cf86062004-05-26 10:11:05 +00002112 void * clientData,
2113 Tcl_Interp *interp,
2114 int objc,
2115 Tcl_Obj *CONST objv[]
2116){
2117 sqlite3_stmt *pStmt;
2118 int col;
danielk197704f2e682004-05-27 01:04:07 +00002119 i64 iVal;
danielk19773cf86062004-05-26 10:11:05 +00002120
2121 if( objc!=3 ){
2122 Tcl_AppendResult(interp, "wrong # args: should be \"",
2123 Tcl_GetString(objv[0]), " STMT column", 0);
2124 return TCL_ERROR;
2125 }
2126
2127 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2128 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2129
danielk197704f2e682004-05-27 01:04:07 +00002130 iVal = sqlite3_column_int64(pStmt, col);
2131 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal));
2132 return TCL_OK;
2133}
2134
2135/*
danielk1977ea61b2c2004-05-27 01:49:51 +00002136** Usage: sqlite3_column_blob STMT column
2137*/
2138static int test_column_blob(
2139 void * clientData,
2140 Tcl_Interp *interp,
2141 int objc,
2142 Tcl_Obj *CONST objv[]
2143){
2144 sqlite3_stmt *pStmt;
2145 int col;
2146
2147 int len;
danielk1977c572ef72004-05-27 09:28:41 +00002148 const void *pBlob;
danielk1977ea61b2c2004-05-27 01:49:51 +00002149
2150 if( objc!=3 ){
2151 Tcl_AppendResult(interp, "wrong # args: should be \"",
2152 Tcl_GetString(objv[0]), " STMT column", 0);
2153 return TCL_ERROR;
2154 }
2155
2156 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2157 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2158
2159 pBlob = sqlite3_column_blob(pStmt, col);
2160 len = sqlite3_column_bytes(pStmt, col);
2161 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len));
2162 return TCL_OK;
2163}
2164
2165/*
danielk197704f2e682004-05-27 01:04:07 +00002166** Usage: sqlite3_column_double STMT column
2167**
2168** Return the data in column 'column' of the current row cast as a double.
2169*/
2170static int test_column_double(
2171 void * clientData,
2172 Tcl_Interp *interp,
2173 int objc,
2174 Tcl_Obj *CONST objv[]
2175){
2176 sqlite3_stmt *pStmt;
2177 int col;
2178 double rVal;
2179
2180 if( objc!=3 ){
2181 Tcl_AppendResult(interp, "wrong # args: should be \"",
2182 Tcl_GetString(objv[0]), " STMT column", 0);
2183 return TCL_ERROR;
2184 }
2185
2186 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2187 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2188
2189 rVal = sqlite3_column_double(pStmt, col);
danielk1977c572ef72004-05-27 09:28:41 +00002190 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal));
danielk19773cf86062004-05-26 10:11:05 +00002191 return TCL_OK;
2192}
2193
2194/*
danielk197717240fd2004-05-26 00:07:25 +00002195** Usage: sqlite3_data_count STMT
2196**
2197** Return the number of columns returned by the sql statement STMT.
2198*/
2199static int test_data_count(
2200 void * clientData,
2201 Tcl_Interp *interp,
2202 int objc,
2203 Tcl_Obj *CONST objv[]
2204){
2205 sqlite3_stmt *pStmt;
2206
2207 if( objc!=2 ){
2208 Tcl_AppendResult(interp, "wrong # args: should be \"",
2209 Tcl_GetString(objv[0]), " STMT column", 0);
2210 return TCL_ERROR;
2211 }
2212
2213 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2214
2215 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt)));
2216 return TCL_OK;
2217}
2218
2219/*
danielk197704f2e682004-05-27 01:04:07 +00002220** Usage: sqlite3_column_text STMT column
2221**
2222** Usage: sqlite3_column_decltype STMT column
2223**
2224** Usage: sqlite3_column_name STMT column
2225*/
2226static int test_stmt_utf8(
drh241db312004-06-22 12:46:53 +00002227 void * clientData, /* Pointer to SQLite API function to be invoke */
danielk197704f2e682004-05-27 01:04:07 +00002228 Tcl_Interp *interp,
2229 int objc,
2230 Tcl_Obj *CONST objv[]
2231){
2232 sqlite3_stmt *pStmt;
2233 int col;
danielk1977c572ef72004-05-27 09:28:41 +00002234 const char *(*xFunc)(sqlite3_stmt*, int) = clientData;
danielk1977f93bbbe2004-05-27 10:30:52 +00002235 const char *zRet;
danielk197704f2e682004-05-27 01:04:07 +00002236
2237 if( objc!=3 ){
2238 Tcl_AppendResult(interp, "wrong # args: should be \"",
2239 Tcl_GetString(objv[0]), " STMT column", 0);
2240 return TCL_ERROR;
2241 }
2242
2243 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2244 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
danielk1977f93bbbe2004-05-27 10:30:52 +00002245 zRet = xFunc(pStmt, col);
2246 if( zRet ){
2247 Tcl_SetResult(interp, (char *)zRet, 0);
2248 }
danielk197704f2e682004-05-27 01:04:07 +00002249 return TCL_OK;
2250}
2251
2252/*
2253** Usage: sqlite3_column_text STMT column
2254**
2255** Usage: sqlite3_column_decltype STMT column
2256**
2257** Usage: sqlite3_column_name STMT column
2258*/
2259static int test_stmt_utf16(
drh241db312004-06-22 12:46:53 +00002260 void * clientData, /* Pointer to SQLite API function to be invoked */
danielk197704f2e682004-05-27 01:04:07 +00002261 Tcl_Interp *interp,
2262 int objc,
2263 Tcl_Obj *CONST objv[]
2264){
drh5436dc22004-11-14 04:04:17 +00002265#ifndef SQLITE_OMIT_UTF16
danielk197704f2e682004-05-27 01:04:07 +00002266 sqlite3_stmt *pStmt;
2267 int col;
2268 Tcl_Obj *pRet;
2269 const void *zName16;
danielk1977c572ef72004-05-27 09:28:41 +00002270 const void *(*xFunc)(sqlite3_stmt*, int) = clientData;
danielk197704f2e682004-05-27 01:04:07 +00002271
2272 if( objc!=3 ){
2273 Tcl_AppendResult(interp, "wrong # args: should be \"",
2274 Tcl_GetString(objv[0]), " STMT column", 0);
2275 return TCL_ERROR;
2276 }
2277
2278 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2279 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2280
2281 zName16 = xFunc(pStmt, col);
danielk1977f93bbbe2004-05-27 10:30:52 +00002282 if( zName16 ){
2283 pRet = Tcl_NewByteArrayObj(zName16, sqlite3utf16ByteLen(zName16, -1)+2);
2284 Tcl_SetObjResult(interp, pRet);
2285 }
drh5436dc22004-11-14 04:04:17 +00002286#endif /* SQLITE_OMIT_UTF16 */
danielk197704f2e682004-05-27 01:04:07 +00002287
2288 return TCL_OK;
2289}
2290
2291/*
2292** Usage: sqlite3_column_int STMT column
2293**
2294** Usage: sqlite3_column_bytes STMT column
2295**
2296** Usage: sqlite3_column_bytes16 STMT column
2297**
2298*/
2299static int test_stmt_int(
drh241db312004-06-22 12:46:53 +00002300 void * clientData, /* Pointer to SQLite API function to be invoked */
danielk197704f2e682004-05-27 01:04:07 +00002301 Tcl_Interp *interp,
2302 int objc,
2303 Tcl_Obj *CONST objv[]
2304){
2305 sqlite3_stmt *pStmt;
2306 int col;
danielk1977c572ef72004-05-27 09:28:41 +00002307 int (*xFunc)(sqlite3_stmt*, int) = clientData;
danielk197704f2e682004-05-27 01:04:07 +00002308
2309 if( objc!=3 ){
2310 Tcl_AppendResult(interp, "wrong # args: should be \"",
2311 Tcl_GetString(objv[0]), " STMT column", 0);
2312 return TCL_ERROR;
2313 }
2314
2315 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
2316 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
2317
2318 Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col)));
2319 return TCL_OK;
2320}
2321
danielk19779a1d0ab2004-06-01 14:09:28 +00002322/*
2323** Usage: sqlite3OsOpenReadWrite <filename>
2324*/
2325static int test_sqlite3OsOpenReadWrite(
2326 void * clientData,
2327 Tcl_Interp *interp,
2328 int objc,
2329 Tcl_Obj *CONST objv[]
2330){
2331 OsFile * pFile;
2332 int rc;
2333 int dummy;
2334 char zBuf[100];
danielk197704f2e682004-05-27 01:04:07 +00002335
danielk19779a1d0ab2004-06-01 14:09:28 +00002336 if( objc!=2 ){
2337 Tcl_AppendResult(interp, "wrong # args: should be \"",
2338 Tcl_GetString(objv[0]), " filename", 0);
2339 return TCL_ERROR;
2340 }
2341
2342 pFile = sqliteMalloc(sizeof(OsFile));
2343 rc = sqlite3OsOpenReadWrite(Tcl_GetString(objv[1]), pFile, &dummy);
2344 if( rc!=SQLITE_OK ){
2345 sqliteFree(pFile);
2346 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2347 return TCL_ERROR;
2348 }
2349 makePointerStr(interp, zBuf, pFile);
2350 Tcl_SetResult(interp, zBuf, 0);
2351 return TCL_ERROR;
2352}
2353
2354/*
2355** Usage: sqlite3OsClose <file handle>
2356*/
2357static int test_sqlite3OsClose(
2358 void * clientData,
2359 Tcl_Interp *interp,
2360 int objc,
2361 Tcl_Obj *CONST objv[]
2362){
2363 OsFile * pFile;
2364 int rc;
2365
2366 if( objc!=2 ){
2367 Tcl_AppendResult(interp, "wrong # args: should be \"",
2368 Tcl_GetString(objv[0]), " filehandle", 0);
2369 return TCL_ERROR;
2370 }
2371
2372 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
2373 return TCL_ERROR;
2374 }
2375 rc = sqlite3OsClose(pFile);
2376 if( rc!=SQLITE_OK ){
2377 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2378 return TCL_ERROR;
2379 }
2380 sqliteFree(pFile);
2381 return TCL_OK;
2382}
2383
2384/*
2385** Usage: sqlite3OsLock <file handle> <locktype>
2386*/
2387static int test_sqlite3OsLock(
2388 void * clientData,
2389 Tcl_Interp *interp,
2390 int objc,
2391 Tcl_Obj *CONST objv[]
2392){
2393 OsFile * pFile;
2394 int rc;
2395
2396 if( objc!=3 ){
2397 Tcl_AppendResult(interp, "wrong # args: should be \"",
2398 Tcl_GetString(objv[0]),
2399 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
2400 return TCL_ERROR;
2401 }
2402
2403 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
2404 return TCL_ERROR;
2405 }
2406
2407 if( 0==strcmp("SHARED", Tcl_GetString(objv[2])) ){
2408 rc = sqlite3OsLock(pFile, SHARED_LOCK);
2409 }
2410 else if( 0==strcmp("RESERVED", Tcl_GetString(objv[2])) ){
2411 rc = sqlite3OsLock(pFile, RESERVED_LOCK);
2412 }
2413 else if( 0==strcmp("PENDING", Tcl_GetString(objv[2])) ){
2414 rc = sqlite3OsLock(pFile, PENDING_LOCK);
2415 }
2416 else if( 0==strcmp("EXCLUSIVE", Tcl_GetString(objv[2])) ){
2417 rc = sqlite3OsLock(pFile, EXCLUSIVE_LOCK);
2418 }else{
2419 Tcl_AppendResult(interp, "wrong # args: should be \"",
2420 Tcl_GetString(objv[0]),
2421 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
2422 return TCL_ERROR;
2423 }
2424
2425 if( rc!=SQLITE_OK ){
2426 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2427 return TCL_ERROR;
2428 }
2429 return TCL_OK;
2430}
2431
2432/*
2433** Usage: sqlite3OsUnlock <file handle>
2434*/
2435static int test_sqlite3OsUnlock(
2436 void * clientData,
2437 Tcl_Interp *interp,
2438 int objc,
2439 Tcl_Obj *CONST objv[]
2440){
2441 OsFile * pFile;
2442 int rc;
2443
2444 if( objc!=2 ){
2445 Tcl_AppendResult(interp, "wrong # args: should be \"",
2446 Tcl_GetString(objv[0]), " filehandle", 0);
2447 return TCL_ERROR;
2448 }
2449
2450 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
2451 return TCL_ERROR;
2452 }
drha6abd042004-06-09 17:37:22 +00002453 rc = sqlite3OsUnlock(pFile, NO_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00002454 if( rc!=SQLITE_OK ){
2455 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2456 return TCL_ERROR;
2457 }
2458 return TCL_OK;
2459}
drhd3d39e92004-05-20 22:16:29 +00002460
drhab3f9fe2004-08-14 17:10:10 +00002461/*
2462** Usage: sqlite3OsTempFileName
2463*/
2464static int test_sqlite3OsTempFileName(
2465 void * clientData,
2466 Tcl_Interp *interp,
2467 int objc,
2468 Tcl_Obj *CONST objv[]
2469){
2470 char zFile[SQLITE_TEMPNAME_SIZE];
2471 int rc;
2472
2473 rc = sqlite3OsTempFileName(zFile);
2474 if( rc!=SQLITE_OK ){
2475 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2476 return TCL_ERROR;
2477 }
2478 Tcl_AppendResult(interp, zFile, 0);
2479 return TCL_OK;
2480}
danielk1977d8123362004-06-12 09:25:12 +00002481
danielk19776622cce2004-05-20 11:00:52 +00002482/*
drhcacb2082005-01-11 15:28:33 +00002483** Usage: sqlite_set_magic DB MAGIC-NUMBER
2484**
2485** Set the db->magic value. This is used to test error recovery logic.
2486*/
2487static int sqlite_set_magic(
2488 void * clientData,
2489 Tcl_Interp *interp,
2490 int argc,
2491 char **argv
2492){
2493 sqlite3 *db;
2494 if( argc!=3 ){
2495 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
2496 " DB MAGIC", 0);
2497 return TCL_ERROR;
2498 }
2499 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2500 if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){
2501 db->magic = SQLITE_MAGIC_OPEN;
2502 }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){
2503 db->magic = SQLITE_MAGIC_CLOSED;
2504 }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){
2505 db->magic = SQLITE_MAGIC_BUSY;
2506 }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){
2507 db->magic = SQLITE_MAGIC_ERROR;
2508 }else if( Tcl_GetInt(interp, argv[2], &db->magic) ){
2509 return TCL_ERROR;
2510 }
2511 return TCL_OK;
2512}
2513
2514/*
drhc5cdca62005-01-11 16:54:14 +00002515** Usage: sqlite3_interrupt DB
2516**
2517** Trigger an interrupt on DB
2518*/
2519static int test_interrupt(
2520 void * clientData,
2521 Tcl_Interp *interp,
2522 int argc,
2523 char **argv
2524){
2525 sqlite3 *db;
2526 if( argc!=2 ){
2527 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
2528 return TCL_ERROR;
2529 }
2530 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
2531 sqlite3_interrupt(db);
2532 return TCL_OK;
2533}
2534
2535/*
drh92febd92004-08-20 18:34:20 +00002536** Usage: tcl_variable_type VARIABLENAME
2537**
2538** Return the name of the internal representation for the
2539** value of the given variable.
2540*/
2541static int tcl_variable_type(
2542 void * clientData,
2543 Tcl_Interp *interp,
2544 int objc,
2545 Tcl_Obj *CONST objv[]
2546){
2547 Tcl_Obj *pVar;
2548 if( objc!=2 ){
2549 Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE");
2550 return TCL_ERROR;
2551 }
2552 pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG);
2553 if( pVar==0 ) return TCL_ERROR;
2554 if( pVar->typePtr ){
2555 Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1));
2556 }
2557 return TCL_OK;
2558}
2559
2560/*
drh27d258a2004-10-30 20:23:09 +00002561** This routine sets entries in the global ::sqlite_options() array variable
2562** according to the compile-time configuration of the database. Test
2563** procedures use this to determine when tests should be omitted.
2564*/
2565static void set_options(Tcl_Interp *interp){
danielk19771c8c23c2004-11-12 15:53:37 +00002566#ifdef SQLITE_OMIT_ALTERTABLE
2567 Tcl_SetVar2(interp, "sqlite_options", "altertable", "0", TCL_GLOBAL_ONLY);
2568#else
2569 Tcl_SetVar2(interp, "sqlite_options", "altertable", "1", TCL_GLOBAL_ONLY);
2570#endif
drh13d70422004-11-13 15:59:14 +00002571
2572#ifdef SQLITE_OMIT_AUTHORIZATION
2573 Tcl_SetVar2(interp, "sqlite_options", "auth", "0", TCL_GLOBAL_ONLY);
2574#else
2575 Tcl_SetVar2(interp, "sqlite_options", "auth", "1", TCL_GLOBAL_ONLY);
2576#endif
2577
drhf3388142004-11-13 03:48:06 +00002578#ifdef SQLITE_OMIT_AUTOINCREMENT
2579 Tcl_SetVar2(interp, "sqlite_options", "autoinc", "0", TCL_GLOBAL_ONLY);
2580#else
2581 Tcl_SetVar2(interp, "sqlite_options", "autoinc", "1", TCL_GLOBAL_ONLY);
2582#endif
2583
danielk197745901d62004-11-10 15:27:38 +00002584#ifdef SQLITE_OMIT_AUTOVACUUM
2585 Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "0", TCL_GLOBAL_ONLY);
2586#else
2587 Tcl_SetVar2(interp, "sqlite_options", "autovacuum", "1", TCL_GLOBAL_ONLY);
drhf3388142004-11-13 03:48:06 +00002588#endif /* SQLITE_OMIT_AUTOVACUUM */
danielk19774d36b812004-11-19 07:07:30 +00002589#if !defined(SQLITE_DEFAULT_AUTOVACUUM) || SQLITE_DEFAULT_AUTOVACUUM==0
danielk197745901d62004-11-10 15:27:38 +00002590 Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","0",TCL_GLOBAL_ONLY);
2591#else
2592 Tcl_SetVar2(interp,"sqlite_options","default_autovacuum","1",TCL_GLOBAL_ONLY);
2593#endif
drh13d70422004-11-13 15:59:14 +00002594
2595#ifdef SQLITE_OMIT_BLOB_LITERAL
2596 Tcl_SetVar2(interp, "sqlite_options", "bloblit", "0", TCL_GLOBAL_ONLY);
2597#else
2598 Tcl_SetVar2(interp, "sqlite_options", "bloblit", "1", TCL_GLOBAL_ONLY);
2599#endif
2600
2601#ifdef SQLITE_OMIT_COMPOUND_SELECT
2602 Tcl_SetVar2(interp, "sqlite_options", "compound", "0", TCL_GLOBAL_ONLY);
2603#else
2604 Tcl_SetVar2(interp, "sqlite_options", "compound", "1", TCL_GLOBAL_ONLY);
2605#endif
2606
2607#ifdef SQLITE_OMIT_CONFLICT_CLAUSE
2608 Tcl_SetVar2(interp, "sqlite_options", "conflict", "0", TCL_GLOBAL_ONLY);
2609#else
2610 Tcl_SetVar2(interp, "sqlite_options", "conflict", "1", TCL_GLOBAL_ONLY);
2611#endif
2612
drhb6c29892004-11-22 19:12:19 +00002613#ifdef SQLITE_OMIT_CURSOR
2614 Tcl_SetVar2(interp, "sqlite_options", "cursor", "0", TCL_GLOBAL_ONLY);
2615#else
2616 Tcl_SetVar2(interp, "sqlite_options", "cursor", "1", TCL_GLOBAL_ONLY);
2617#endif
2618
drh13d70422004-11-13 15:59:14 +00002619#ifdef SQLITE_OMIT_DATETIME_FUNCS
2620 Tcl_SetVar2(interp, "sqlite_options", "datetime", "0", TCL_GLOBAL_ONLY);
2621#else
2622 Tcl_SetVar2(interp, "sqlite_options", "datetime", "1", TCL_GLOBAL_ONLY);
2623#endif
2624
2625#ifdef SQLITE_OMIT_EXPLAIN
2626 Tcl_SetVar2(interp, "sqlite_options", "explain", "0", TCL_GLOBAL_ONLY);
2627#else
2628 Tcl_SetVar2(interp, "sqlite_options", "explain", "1", TCL_GLOBAL_ONLY);
2629#endif
2630
2631#ifdef SQLITE_OMIT_FLOATING_POINT
2632 Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "0", TCL_GLOBAL_ONLY);
2633#else
2634 Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "1", TCL_GLOBAL_ONLY);
2635#endif
2636
2637#ifdef SQLITE_OMIT_FOREIGN_KEY
2638 Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "0", TCL_GLOBAL_ONLY);
2639#else
2640 Tcl_SetVar2(interp, "sqlite_options", "foreignkey", "1", TCL_GLOBAL_ONLY);
2641#endif
2642
2643#ifdef SQLITE_OMIT_INTEGRITY_CHECK
2644 Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
2645#else
2646 Tcl_SetVar2(interp, "sqlite_options", "integrityck", "1", TCL_GLOBAL_ONLY);
2647#endif
2648
2649#ifdef SQLITE_OMIT_MEMORYDB
2650 Tcl_SetVar2(interp, "sqlite_options", "memorydb", "0", TCL_GLOBAL_ONLY);
2651#else
2652 Tcl_SetVar2(interp, "sqlite_options", "memorydb", "1", TCL_GLOBAL_ONLY);
2653#endif
2654
2655#ifdef SQLITE_OMIT_PAGER_PRAGMAS
2656 Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "0", TCL_GLOBAL_ONLY);
2657#else
2658 Tcl_SetVar2(interp, "sqlite_options", "pager_pragmas", "1", TCL_GLOBAL_ONLY);
2659#endif
2660
2661#ifdef SQLITE_OMIT_PRAGMA
2662 Tcl_SetVar2(interp, "sqlite_options", "pragma", "0", TCL_GLOBAL_ONLY);
2663 Tcl_SetVar2(interp, "sqlite_options", "integrityck", "0", TCL_GLOBAL_ONLY);
2664#else
2665 Tcl_SetVar2(interp, "sqlite_options", "pragma", "1", TCL_GLOBAL_ONLY);
2666#endif
2667
2668#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
2669 Tcl_SetVar2(interp, "sqlite_options", "progress", "0", TCL_GLOBAL_ONLY);
2670#else
2671 Tcl_SetVar2(interp, "sqlite_options", "progress", "1", TCL_GLOBAL_ONLY);
2672#endif
2673
2674#ifdef SQLITE_OMIT_REINDEX
2675 Tcl_SetVar2(interp, "sqlite_options", "reindex", "0", TCL_GLOBAL_ONLY);
2676#else
2677 Tcl_SetVar2(interp, "sqlite_options", "reindex", "1", TCL_GLOBAL_ONLY);
2678#endif
2679
2680#ifdef SQLITE_OMIT_SCHEMA_PRAGMAS
2681 Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "0", TCL_GLOBAL_ONLY);
2682#else
2683 Tcl_SetVar2(interp, "sqlite_options", "schema_pragmas", "1", TCL_GLOBAL_ONLY);
2684#endif
2685
2686#ifdef SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
2687 Tcl_SetVar2(interp, "sqlite_options", "schema_version", "0", TCL_GLOBAL_ONLY);
2688#else
2689 Tcl_SetVar2(interp, "sqlite_options", "schema_version", "1", TCL_GLOBAL_ONLY);
2690#endif
2691
2692#ifdef SQLITE_OMIT_TCL_VARIABLE
2693 Tcl_SetVar2(interp, "sqlite_options", "tclvar", "0", TCL_GLOBAL_ONLY);
2694#else
2695 Tcl_SetVar2(interp, "sqlite_options", "tclvar", "1", TCL_GLOBAL_ONLY);
2696#endif
2697
2698#if defined(THREADSAFE) && THREADSAFE
2699 Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "1", TCL_GLOBAL_ONLY);
2700#else
2701 Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "0", TCL_GLOBAL_ONLY);
2702#endif
2703
2704#ifdef SQLITE_OMIT_TRIGGER
2705 Tcl_SetVar2(interp, "sqlite_options", "trigger", "0", TCL_GLOBAL_ONLY);
2706#else
2707 Tcl_SetVar2(interp, "sqlite_options", "trigger", "1", TCL_GLOBAL_ONLY);
2708#endif
2709
2710#ifdef SQLITE_OMIT_UTF16
2711 Tcl_SetVar2(interp, "sqlite_options", "utf16", "0", TCL_GLOBAL_ONLY);
2712#else
2713 Tcl_SetVar2(interp, "sqlite_options", "utf16", "1", TCL_GLOBAL_ONLY);
2714#endif
2715
2716#ifdef SQLITE_OMIT_VACUUM
2717 Tcl_SetVar2(interp, "sqlite_options", "vacuum", "0", TCL_GLOBAL_ONLY);
2718#else
2719 Tcl_SetVar2(interp, "sqlite_options", "vacuum", "1", TCL_GLOBAL_ONLY);
2720#endif
2721
2722#ifdef SQLITE_OMIT_VIEW
2723 Tcl_SetVar2(interp, "sqlite_options", "view", "0", TCL_GLOBAL_ONLY);
2724#else
2725 Tcl_SetVar2(interp, "sqlite_options", "view", "1", TCL_GLOBAL_ONLY);
2726#endif
drh27d258a2004-10-30 20:23:09 +00002727}
2728
2729/*
drhd1bf3512001-04-07 15:24:33 +00002730** Register commands with the TCL interpreter.
2731*/
2732int Sqlitetest1_Init(Tcl_Interp *interp){
danielk19776f8a5032004-05-10 10:34:51 +00002733 extern int sqlite3_search_count;
2734 extern int sqlite3_interrupt_count;
2735 extern int sqlite3_open_file_count;
drh6bf89572004-11-03 16:27:01 +00002736 extern int sqlite3_sort_count;
danielk19776f8a5032004-05-10 10:34:51 +00002737 extern int sqlite3_current_time;
drhc2eef3b2002-08-31 18:53:06 +00002738 static struct {
2739 char *zName;
2740 Tcl_CmdProc *xProc;
2741 } aCmd[] = {
drhd3d39e92004-05-20 22:16:29 +00002742 { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int },
drhe9707672004-06-25 01:10:48 +00002743 { "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 },
drhd3d39e92004-05-20 22:16:29 +00002744 { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str },
drhe29b1a02004-07-17 21:56:09 +00002745 { "sqlite3_mprintf_stronly", (Tcl_CmdProc*)sqlite3_mprintf_stronly},
drhd3d39e92004-05-20 22:16:29 +00002746 { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double },
2747 { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled },
2748 { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z },
drhd3d39e92004-05-20 22:16:29 +00002749 { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid },
2750 { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf },
2751 { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf },
2752 { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close },
2753 { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function },
2754 { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate },
2755 { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func },
2756 { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort },
danielk19772c336542005-01-13 02:14:23 +00002757#ifdef SQLITE_MEMDEBUG
drhd3d39e92004-05-20 22:16:29 +00002758 { "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail },
2759 { "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat },
drhc2eef3b2002-08-31 18:53:06 +00002760#endif
drh25d65432004-07-22 15:02:25 +00002761 { "sqlite_bind", (Tcl_CmdProc*)test_bind },
2762 { "breakpoint", (Tcl_CmdProc*)test_breakpoint },
2763 { "sqlite3_key", (Tcl_CmdProc*)test_key },
2764 { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey },
drhcacb2082005-01-11 15:28:33 +00002765 { "sqlite_set_magic", (Tcl_CmdProc*)sqlite_set_magic },
drhc5cdca62005-01-11 16:54:14 +00002766 { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt },
drhc2eef3b2002-08-31 18:53:06 +00002767 };
danielk197751e3d8e2004-05-20 01:12:34 +00002768 static struct {
2769 char *zName;
2770 Tcl_ObjCmdProc *xProc;
danielk197704f2e682004-05-27 01:04:07 +00002771 void *clientData;
danielk197751e3d8e2004-05-20 01:12:34 +00002772 } aObjCmd[] = {
drh241db312004-06-22 12:46:53 +00002773 { "sqlite3_bind_int", test_bind_int, 0 },
2774 { "sqlite3_bind_int64", test_bind_int64, 0 },
2775 { "sqlite3_bind_double", test_bind_double, 0 },
danielk197704f2e682004-05-27 01:04:07 +00002776 { "sqlite3_bind_null", test_bind_null ,0 },
2777 { "sqlite3_bind_text", test_bind_text ,0 },
2778 { "sqlite3_bind_text16", test_bind_text16 ,0 },
2779 { "sqlite3_bind_blob", test_bind_blob ,0 },
drh75f6a032004-07-15 14:15:00 +00002780 { "sqlite3_bind_parameter_count", test_bind_parameter_count, 0},
drh895d7472004-08-20 16:02:39 +00002781 { "sqlite3_bind_parameter_name", test_bind_parameter_name, 0},
drhfa6bc002004-09-07 16:19:52 +00002782 { "sqlite3_bind_parameter_index", test_bind_parameter_index, 0},
danielk197704f2e682004-05-27 01:04:07 +00002783 { "sqlite3_errcode", test_errcode ,0 },
2784 { "sqlite3_errmsg", test_errmsg ,0 },
2785 { "sqlite3_errmsg16", test_errmsg16 ,0 },
2786 { "sqlite3_open", test_open ,0 },
2787 { "sqlite3_open16", test_open16 ,0 },
danielk1977bc6ada42004-06-30 08:20:16 +00002788 { "sqlite3_complete16", test_complete16 ,0 },
danielk197704f2e682004-05-27 01:04:07 +00002789
2790 { "sqlite3_prepare", test_prepare ,0 },
2791 { "sqlite3_prepare16", test_prepare16 ,0 },
2792 { "sqlite3_finalize", test_finalize ,0 },
2793 { "sqlite3_reset", test_reset ,0 },
danielk1977fbcd5852004-06-15 02:44:18 +00002794 { "sqlite3_changes", test_changes ,0 },
2795 { "sqlite3_step", test_step ,0 },
danielk197704f2e682004-05-27 01:04:07 +00002796
2797 /* sqlite3_column_*() API */
2798 { "sqlite3_column_count", test_column_count ,0 },
2799 { "sqlite3_data_count", test_data_count ,0 },
2800 { "sqlite3_column_type", test_column_type ,0 },
danielk1977ea61b2c2004-05-27 01:49:51 +00002801 { "sqlite3_column_blob", test_column_blob ,0 },
danielk197704f2e682004-05-27 01:04:07 +00002802 { "sqlite3_column_double", test_column_double ,0 },
2803 { "sqlite3_column_int64", test_column_int64 ,0 },
drh241db312004-06-22 12:46:53 +00002804 { "sqlite3_column_text", test_stmt_utf8, sqlite3_column_text },
2805 { "sqlite3_column_decltype", test_stmt_utf8, sqlite3_column_decltype },
2806 { "sqlite3_column_name", test_stmt_utf8, sqlite3_column_name },
drh6c626082004-11-14 21:56:29 +00002807 { "sqlite3_column_int", test_stmt_int, sqlite3_column_int },
2808 { "sqlite3_column_bytes", test_stmt_int, sqlite3_column_bytes },
2809#ifndef SQLITE_OMIT_UTF16
2810 { "sqlite3_column_bytes16", test_stmt_int, sqlite3_column_bytes16 },
drh241db312004-06-22 12:46:53 +00002811 { "sqlite3_column_text16", test_stmt_utf16, sqlite3_column_text16 },
2812 { "sqlite3_column_decltype16", test_stmt_utf16, sqlite3_column_decltype16},
2813 { "sqlite3_column_name16", test_stmt_utf16, sqlite3_column_name16 },
drh6c626082004-11-14 21:56:29 +00002814#endif
danielk197704f2e682004-05-27 01:04:07 +00002815
danielk19779a1d0ab2004-06-01 14:09:28 +00002816 /* Functions from os.h */
2817 { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 },
2818 { "sqlite3OsClose", test_sqlite3OsClose, 0 },
2819 { "sqlite3OsLock", test_sqlite3OsLock, 0 },
drhab3f9fe2004-08-14 17:10:10 +00002820 { "sqlite3OsTempFileName", test_sqlite3OsTempFileName, 0 },
danielk1977312d6b32004-06-29 13:18:23 +00002821
2822 /* Custom test interfaces */
2823 { "sqlite3OsUnlock", test_sqlite3OsUnlock, 0 },
drh5436dc22004-11-14 04:04:17 +00002824#ifndef SQLITE_OMIT_UTF16
danielk1977312d6b32004-06-29 13:18:23 +00002825 { "add_test_collate", test_collate, 0 },
2826 { "add_test_collate_needed", test_collate_needed, 0 },
2827 { "add_test_function", test_function, 0 },
drh5436dc22004-11-14 04:04:17 +00002828#endif
danielk1977312d6b32004-06-29 13:18:23 +00002829 { "sqlite3_crashparams", sqlite3_crashparams, 0 },
2830 { "sqlite3_test_errstr", test_errstr, 0 },
drh92febd92004-08-20 18:34:20 +00002831 { "tcl_variable_type", tcl_variable_type, 0 },
danielk197751e3d8e2004-05-20 01:12:34 +00002832 };
drhc2eef3b2002-08-31 18:53:06 +00002833 int i;
drh2ac3ee92004-06-07 16:27:46 +00002834 extern int sqlite3_os_trace;
drhc2eef3b2002-08-31 18:53:06 +00002835
2836 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
2837 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
2838 }
danielk197751e3d8e2004-05-20 01:12:34 +00002839 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
danielk1977c572ef72004-05-27 09:28:41 +00002840 Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
2841 aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
danielk197751e3d8e2004-05-20 01:12:34 +00002842 }
danielk19776490beb2004-05-11 06:17:21 +00002843 Tcl_LinkVar(interp, "sqlite_search_count",
danielk19776f8a5032004-05-10 10:34:51 +00002844 (char*)&sqlite3_search_count, TCL_LINK_INT);
drh6bf89572004-11-03 16:27:01 +00002845 Tcl_LinkVar(interp, "sqlite_sort_count",
2846 (char*)&sqlite3_sort_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00002847 Tcl_LinkVar(interp, "sqlite_interrupt_count",
danielk19776f8a5032004-05-10 10:34:51 +00002848 (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00002849 Tcl_LinkVar(interp, "sqlite_open_file_count",
danielk19776f8a5032004-05-10 10:34:51 +00002850 (char*)&sqlite3_open_file_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00002851 Tcl_LinkVar(interp, "sqlite_current_time",
danielk19776f8a5032004-05-10 10:34:51 +00002852 (char*)&sqlite3_current_time, TCL_LINK_INT);
drh2ac3ee92004-06-07 16:27:46 +00002853 Tcl_LinkVar(interp, "sqlite_os_trace",
2854 (char*)&sqlite3_os_trace, TCL_LINK_INT);
drh7c972de2003-09-06 22:18:07 +00002855 Tcl_LinkVar(interp, "sqlite_static_bind_value",
2856 (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
drhab3f9fe2004-08-14 17:10:10 +00002857 Tcl_LinkVar(interp, "sqlite_temp_directory",
drheffd02b2004-08-29 23:42:13 +00002858 (char*)&sqlite3_temp_directory, TCL_LINK_STRING);
drh27d258a2004-10-30 20:23:09 +00002859 set_options(interp);
drhd1bf3512001-04-07 15:24:33 +00002860 return TCL_OK;
2861}