blob: d5dcfa2a20d66f8a61010ee4bf72061398082230 [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**
danielk1977e35ee192004-06-26 09:50:11 +000016** $Id: test1.c,v 1.89 2004/06/26 09:50:12 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
drh94e92032003-02-16 22:21:32 +000024#if OS_WIN
25# define PTR_FMT "%x"
26#else
27# define PTR_FMT "%p"
28#endif
29
danielk1977c572ef72004-05-27 09:28:41 +000030int sqlite3_exec_printf(
31 sqlite *db, /* An open database */
32 const char *sqlFormat, /* printf-style format string for the SQL */
33 sqlite_callback xCallback, /* Callback function */
34 void *pArg, /* 1st argument to callback function */
35 char **errmsg, /* Error msg written here */
36 ... /* Arguments to the format string. */
37);
danielk1977c572ef72004-05-27 09:28:41 +000038int sqlite3_get_table_printf(
39 sqlite *db, /* An open database */
40 const char *sqlFormat, /* printf-style format string for the SQL */
41 char ***resultp, /* Result written to a char *[] that this points to */
42 int *nrow, /* Number of result rows written here */
43 int *ncol, /* Number of result columns written here */
44 char **errmsg, /* Error msg written here */
45 ... /* Arguments to the format string */
46);
47
danielk19776622cce2004-05-20 11:00:52 +000048static const char * errorName(int rc){
49 const char *zName = 0;
50 switch( rc ){
51 case SQLITE_OK: zName = "SQLITE_OK"; break;
52 case SQLITE_ERROR: zName = "SQLITE_ERROR"; break;
53 case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break;
54 case SQLITE_PERM: zName = "SQLITE_PERM"; break;
55 case SQLITE_ABORT: zName = "SQLITE_ABORT"; break;
56 case SQLITE_BUSY: zName = "SQLITE_BUSY"; break;
57 case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break;
58 case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break;
59 case SQLITE_READONLY: zName = "SQLITE_READONLY"; break;
60 case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break;
61 case SQLITE_IOERR: zName = "SQLITE_IOERR"; break;
62 case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break;
63 case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break;
64 case SQLITE_FULL: zName = "SQLITE_FULL"; break;
65 case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break;
66 case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
67 case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break;
68 case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break;
69 case SQLITE_TOOBIG: zName = "SQLITE_TOOBIG"; break;
70 case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break;
71 case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break;
72 case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break;
73 case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break;
74 case SQLITE_AUTH: zName = "SQLITE_AUTH"; break;
75 case SQLITE_FORMAT: zName = "SQLITE_FORMAT"; break;
76 case SQLITE_RANGE: zName = "SQLITE_RANGE"; break;
77 case SQLITE_ROW: zName = "SQLITE_ROW"; break;
78 case SQLITE_DONE: zName = "SQLITE_DONE"; break;
79 default: zName = "SQLITE_Unknown"; break;
80 }
81 return zName;
82}
83
drhd1bf3512001-04-07 15:24:33 +000084/*
drhb86ccfb2003-01-28 23:13:10 +000085** Decode a pointer to an sqlite object.
86*/
drh90f405e2003-12-23 03:06:23 +000087static int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite **ppDb){
88 if( sscanf(zA, PTR_FMT, (void**)ppDb)!=1 &&
89 (zA[0]!='0' || zA[1]!='x' || sscanf(&zA[2], PTR_FMT, (void**)ppDb)!=1)
90 ){
91 Tcl_AppendResult(interp, "\"", zA, "\" is not a valid pointer value", 0);
drhb86ccfb2003-01-28 23:13:10 +000092 return TCL_ERROR;
93 }
94 return TCL_OK;
95}
96
97/*
danielk197751e3d8e2004-05-20 01:12:34 +000098** Decode a pointer to an sqlite3_stmt object.
99*/
100static int getStmtPointer(
101 Tcl_Interp *interp,
102 const char *zArg,
103 sqlite3_stmt **ppStmt
104){
105 if( sscanf(zArg, PTR_FMT, (void**)ppStmt)!=1 ){
106 Tcl_AppendResult(interp, "\"", zArg, "\" is not a valid pointer value", 0);
107 return TCL_ERROR;
108 }
109 return TCL_OK;
110}
111
112/*
danielk19779a1d0ab2004-06-01 14:09:28 +0000113** Decode a pointer to an sqlite3_stmt object.
114*/
115static int getFilePointer(
116 Tcl_Interp *interp,
117 const char *zArg,
118 OsFile **ppFile
119){
120 if( sscanf(zArg, PTR_FMT, (void**)ppFile)!=1 ){
121 Tcl_AppendResult(interp, "\"", zArg, "\" is not a valid pointer value", 0);
122 return TCL_ERROR;
123 }
124 return TCL_OK;
125}
126
127/*
drh7d8085a2003-04-26 13:19:38 +0000128** Generate a text representation of a pointer that can be understood
129** by the getDbPointer and getVmPointer routines above.
130**
131** The problem is, on some machines (Solaris) if you do a printf with
132** "%p" you cannot turn around and do a scanf with the same "%p" and
133** get your pointer back. You have to prepend a "0x" before it will
134** work. Or at least that is what is reported to me (drh). But this
135** behavior varies from machine to machine. The solution used her is
136** to test the string right after it is generated to see if it can be
137** understood by scanf, and if not, try prepending an "0x" to see if
138** that helps. If nothing works, a fatal error is generated.
139*/
140static int makePointerStr(Tcl_Interp *interp, char *zPtr, void *p){
141 void *p2;
142 sprintf(zPtr, PTR_FMT, p);
143 if( sscanf(zPtr, PTR_FMT, &p2)!=1 || p2!=p ){
144 sprintf(zPtr, "0x" PTR_FMT, p);
145 if( sscanf(zPtr, PTR_FMT, &p2)!=1 || p2!=p ){
146 Tcl_AppendResult(interp, "unable to convert a pointer to a string "
147 "in the file " __FILE__ " in function makePointerStr(). Please "
148 "report this problem to the SQLite mailing list or as a new but "
149 "report. Please provide detailed information about how you compiled "
150 "SQLite and what computer you are running on.", 0);
151 return TCL_ERROR;
152 }
153 }
154 return TCL_OK;
155}
156
157/*
danielk19776f8a5032004-05-10 10:34:51 +0000158** The callback routine for sqlite3_exec_printf().
drhd1bf3512001-04-07 15:24:33 +0000159*/
160static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){
161 Tcl_DString *str = (Tcl_DString*)pArg;
162 int i;
163
164 if( Tcl_DStringLength(str)==0 ){
165 for(i=0; i<argc; i++){
166 Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL");
167 }
168 }
169 for(i=0; i<argc; i++){
170 Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL");
171 }
172 return 0;
173}
174
175/*
danielk19776f8a5032004-05-10 10:34:51 +0000176** Usage: sqlite3_exec_printf DB FORMAT STRING
drhd1bf3512001-04-07 15:24:33 +0000177**
danielk19776f8a5032004-05-10 10:34:51 +0000178** Invoke the sqlite3_exec_printf() interface using the open database
drhd1bf3512001-04-07 15:24:33 +0000179** DB. The SQL is the string FORMAT. The format string should contain
180** one %s or %q. STRING is the value inserted into %s or %q.
181*/
182static int test_exec_printf(
183 void *NotUsed,
184 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
185 int argc, /* Number of arguments */
186 char **argv /* Text of each argument */
187){
188 sqlite *db;
189 Tcl_DString str;
190 int rc;
191 char *zErr = 0;
192 char zBuf[30];
193 if( argc!=4 ){
194 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
195 " DB FORMAT STRING", 0);
196 return TCL_ERROR;
197 }
drhb86ccfb2003-01-28 23:13:10 +0000198 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000199 Tcl_DStringInit(&str);
danielk19776f8a5032004-05-10 10:34:51 +0000200 rc = sqlite3_exec_printf(db, argv[2], exec_printf_cb, &str, &zErr, argv[3]);
drhd1bf3512001-04-07 15:24:33 +0000201 sprintf(zBuf, "%d", rc);
202 Tcl_AppendElement(interp, zBuf);
203 Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
204 Tcl_DStringFree(&str);
205 if( zErr ) free(zErr);
206 return TCL_OK;
207}
208
209/*
danielk19776f8a5032004-05-10 10:34:51 +0000210** Usage: sqlite3_mprintf_z_test SEPARATOR ARG0 ARG1 ...
drhd93d8a82003-06-16 03:08:18 +0000211**
212** Test the %z format of mprintf(). Use multiple mprintf() calls to
213** concatenate arg0 through argn using separator as the separator.
214** Return the result.
215*/
216static int test_mprintf_z(
217 void *NotUsed,
218 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
219 int argc, /* Number of arguments */
220 char **argv /* Text of each argument */
221){
222 char *zResult = 0;
223 int i;
224
225 for(i=2; i<argc; i++){
danielk19774adee202004-05-08 08:23:19 +0000226 zResult = sqlite3MPrintf("%z%s%s", zResult, argv[1], argv[i]);
drhd93d8a82003-06-16 03:08:18 +0000227 }
228 Tcl_AppendResult(interp, zResult, 0);
drh5f968432004-02-21 19:02:30 +0000229 sqliteFree(zResult);
drhd93d8a82003-06-16 03:08:18 +0000230 return TCL_OK;
231}
232
233/*
danielk19776f8a5032004-05-10 10:34:51 +0000234** Usage: sqlite3_get_table_printf DB FORMAT STRING
drhd1bf3512001-04-07 15:24:33 +0000235**
danielk19776f8a5032004-05-10 10:34:51 +0000236** Invoke the sqlite3_get_table_printf() interface using the open database
drhd1bf3512001-04-07 15:24:33 +0000237** DB. The SQL is the string FORMAT. The format string should contain
238** one %s or %q. STRING is the value inserted into %s or %q.
239*/
240static int test_get_table_printf(
241 void *NotUsed,
242 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
243 int argc, /* Number of arguments */
244 char **argv /* Text of each argument */
245){
246 sqlite *db;
247 Tcl_DString str;
248 int rc;
249 char *zErr = 0;
250 int nRow, nCol;
251 char **aResult;
252 int i;
253 char zBuf[30];
254 if( argc!=4 ){
255 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
256 " DB FORMAT STRING", 0);
257 return TCL_ERROR;
258 }
drhb86ccfb2003-01-28 23:13:10 +0000259 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
drhd1bf3512001-04-07 15:24:33 +0000260 Tcl_DStringInit(&str);
danielk19776f8a5032004-05-10 10:34:51 +0000261 rc = sqlite3_get_table_printf(db, argv[2], &aResult, &nRow, &nCol,
drhd1bf3512001-04-07 15:24:33 +0000262 &zErr, argv[3]);
263 sprintf(zBuf, "%d", rc);
264 Tcl_AppendElement(interp, zBuf);
265 if( rc==SQLITE_OK ){
266 sprintf(zBuf, "%d", nRow);
267 Tcl_AppendElement(interp, zBuf);
268 sprintf(zBuf, "%d", nCol);
269 Tcl_AppendElement(interp, zBuf);
270 for(i=0; i<(nRow+1)*nCol; i++){
271 Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL");
272 }
273 }else{
274 Tcl_AppendElement(interp, zErr);
275 }
danielk19776f8a5032004-05-10 10:34:51 +0000276 sqlite3_free_table(aResult);
drhd1bf3512001-04-07 15:24:33 +0000277 if( zErr ) free(zErr);
278 return TCL_OK;
279}
280
drhaf9ff332002-01-16 21:00:27 +0000281
282/*
danielk19776f8a5032004-05-10 10:34:51 +0000283** Usage: sqlite3_last_insert_rowid DB
drhaf9ff332002-01-16 21:00:27 +0000284**
285** Returns the integer ROWID of the most recent insert.
286*/
287static int test_last_rowid(
288 void *NotUsed,
289 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
290 int argc, /* Number of arguments */
291 char **argv /* Text of each argument */
292){
293 sqlite *db;
294 char zBuf[30];
295
296 if( argc!=2 ){
297 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0);
298 return TCL_ERROR;
299 }
drhb86ccfb2003-01-28 23:13:10 +0000300 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk1977c572ef72004-05-27 09:28:41 +0000301 sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db));
drhaf9ff332002-01-16 21:00:27 +0000302 Tcl_AppendResult(interp, zBuf, 0);
303 return SQLITE_OK;
304}
305
drhd1bf3512001-04-07 15:24:33 +0000306/*
danielk19776f8a5032004-05-10 10:34:51 +0000307** Usage: sqlite3_close DB
drhd1bf3512001-04-07 15:24:33 +0000308**
danielk19776f8a5032004-05-10 10:34:51 +0000309** Closes the database opened by sqlite3_open.
drhd1bf3512001-04-07 15:24:33 +0000310*/
311static int sqlite_test_close(
312 void *NotUsed,
313 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
314 int argc, /* Number of arguments */
315 char **argv /* Text of each argument */
316){
317 sqlite *db;
danielk197796d81f92004-06-19 03:33:57 +0000318 int rc;
drhd1bf3512001-04-07 15:24:33 +0000319 if( argc!=2 ){
320 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
321 " FILENAME\"", 0);
322 return TCL_ERROR;
323 }
drhb86ccfb2003-01-28 23:13:10 +0000324 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk197796d81f92004-06-19 03:33:57 +0000325 rc = sqlite3_close(db);
danielk1977f9d64d22004-06-19 08:18:07 +0000326 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
drhd1bf3512001-04-07 15:24:33 +0000327 return TCL_OK;
328}
329
330/*
drhc22bd472002-05-10 13:14:07 +0000331** Implementation of the x_coalesce() function.
332** Return the first argument non-NULL argument.
333*/
danielk19770ae8b832004-05-25 12:05:56 +0000334static void ifnullFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
drhc22bd472002-05-10 13:14:07 +0000335 int i;
336 for(i=0; i<argc; i++){
drh9c054832004-05-31 18:51:57 +0000337 if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
danielk1977d8123362004-06-12 09:25:12 +0000338 sqlite3_result_text(context, sqlite3_value_text(argv[i]), -1,
339 SQLITE_TRANSIENT);
drhc22bd472002-05-10 13:14:07 +0000340 break;
341 }
342 }
343}
344
345/*
drhd1d9fc32004-01-07 19:24:48 +0000346** A structure into which to accumulate text.
347*/
348struct dstr {
349 int nAlloc; /* Space allocated */
350 int nUsed; /* Space used */
351 char *z; /* The space */
352};
353
354/*
355** Append text to a dstr
356*/
357static void dstrAppend(struct dstr *p, const char *z, int divider){
358 int n = strlen(z);
359 if( p->nUsed + n + 2 > p->nAlloc ){
360 char *zNew;
361 p->nAlloc = p->nAlloc*2 + n + 200;
362 zNew = sqliteRealloc(p->z, p->nAlloc);
363 if( zNew==0 ){
364 sqliteFree(p->z);
365 memset(p, 0, sizeof(*p));
366 return;
367 }
368 p->z = zNew;
369 }
370 if( divider && p->nUsed>0 ){
371 p->z[p->nUsed++] = divider;
372 }
373 memcpy(&p->z[p->nUsed], z, n+1);
374 p->nUsed += n;
375}
376
377/*
danielk19774adee202004-05-08 08:23:19 +0000378** Invoked for each callback from sqlite3ExecFunc
drhd1d9fc32004-01-07 19:24:48 +0000379*/
380static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){
381 struct dstr *p = (struct dstr*)pData;
382 int i;
383 for(i=0; i<argc; i++){
384 if( argv[i]==0 ){
385 dstrAppend(p, "NULL", ' ');
386 }else{
387 dstrAppend(p, argv[i], ' ');
388 }
389 }
390 return 0;
391}
392
393/*
danielk1977e35ee192004-06-26 09:50:11 +0000394** Implementation of the x_sqlite_exec() function. This function takes
drhc22bd472002-05-10 13:14:07 +0000395** a single argument and attempts to execute that argument as SQL code.
drh6cbe1f12002-07-01 00:31:36 +0000396** This is illegal and should set the SQLITE_MISUSE flag on the database.
drhd1d9fc32004-01-07 19:24:48 +0000397**
danielk19776f8a5032004-05-10 10:34:51 +0000398** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec()
drhd1d9fc32004-01-07 19:24:48 +0000399** from within a function call.
drhc22bd472002-05-10 13:14:07 +0000400**
401** This routine simulates the effect of having two threads attempt to
402** use the same database at the same time.
403*/
danielk197751ad0ec2004-05-24 12:39:02 +0000404static void sqlite3ExecFunc(
danielk19770ae8b832004-05-25 12:05:56 +0000405 sqlite3_context *context,
danielk197751ad0ec2004-05-24 12:39:02 +0000406 int argc,
407 sqlite3_value **argv
408){
drhd1d9fc32004-01-07 19:24:48 +0000409 struct dstr x;
410 memset(&x, 0, sizeof(x));
danielk197751ad0ec2004-05-24 12:39:02 +0000411 sqlite3_exec((sqlite*)sqlite3_user_data(context),
drh4f26d6c2004-05-26 23:25:30 +0000412 sqlite3_value_text(argv[0]),
drhd1d9fc32004-01-07 19:24:48 +0000413 execFuncCallback, &x, 0);
danielk1977d8123362004-06-12 09:25:12 +0000414 sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT);
drhd1d9fc32004-01-07 19:24:48 +0000415 sqliteFree(x.z);
drhc22bd472002-05-10 13:14:07 +0000416}
417
418/*
419** Usage: sqlite_test_create_function DB
420**
danielk19776f8a5032004-05-10 10:34:51 +0000421** Call the sqlite3_create_function API on the given database in order
drhc22bd472002-05-10 13:14:07 +0000422** to create a function named "x_coalesce". This function does the same thing
423** as the "coalesce" function. This function also registers an SQL function
danielk1977e35ee192004-06-26 09:50:11 +0000424** named "x_sqlite_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec()
drhc22bd472002-05-10 13:14:07 +0000425** in this way is illegal recursion and should raise an SQLITE_MISUSE error.
426** The effect is similar to trying to use the same database connection from
427** two threads at the same time.
428**
429** The original motivation for this routine was to be able to call the
danielk19776f8a5032004-05-10 10:34:51 +0000430** sqlite3_create_function function while a query is in progress in order
drhc22bd472002-05-10 13:14:07 +0000431** to test the SQLITE_MISUSE detection logic.
432*/
drhc2eef3b2002-08-31 18:53:06 +0000433static int test_create_function(
drhc22bd472002-05-10 13:14:07 +0000434 void *NotUsed,
435 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
436 int argc, /* Number of arguments */
437 char **argv /* Text of each argument */
438){
439 sqlite *db;
440 extern void Md5_Register(sqlite*);
441 if( argc!=2 ){
442 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
443 " FILENAME\"", 0);
444 return TCL_ERROR;
445 }
drhb86ccfb2003-01-28 23:13:10 +0000446 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk1977f9d64d22004-06-19 08:18:07 +0000447 sqlite3_create_function(db, "x_coalesce", -1, SQLITE_UTF8, 0,
danielk1977d8123362004-06-12 09:25:12 +0000448 ifnullFunc, 0, 0);
danielk1977e35ee192004-06-26 09:50:11 +0000449 sqlite3_create_function(db, "x_sqlite_exec", 1, SQLITE_UTF8, db,
danielk197765904932004-05-26 06:18:37 +0000450 sqlite3ExecFunc, 0, 0);
drhc22bd472002-05-10 13:14:07 +0000451 return TCL_OK;
452}
453
454/*
455** Routines to implement the x_count() aggregate function.
456*/
457typedef struct CountCtx CountCtx;
458struct CountCtx {
459 int n;
460};
danielk19770ae8b832004-05-25 12:05:56 +0000461static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
drhc22bd472002-05-10 13:14:07 +0000462 CountCtx *p;
drh4f26d6c2004-05-26 23:25:30 +0000463 p = sqlite3_aggregate_context(context, sizeof(*p));
drh9c054832004-05-31 18:51:57 +0000464 if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){
drhc22bd472002-05-10 13:14:07 +0000465 p->n++;
466 }
467}
danielk19770ae8b832004-05-25 12:05:56 +0000468static void countFinalize(sqlite3_context *context){
drhc22bd472002-05-10 13:14:07 +0000469 CountCtx *p;
drh4f26d6c2004-05-26 23:25:30 +0000470 p = sqlite3_aggregate_context(context, sizeof(*p));
danielk1977c572ef72004-05-27 09:28:41 +0000471 sqlite3_result_int(context, p ? p->n : 0);
drhc22bd472002-05-10 13:14:07 +0000472}
473
474/*
475** Usage: sqlite_test_create_aggregate DB
476**
danielk19776f8a5032004-05-10 10:34:51 +0000477** Call the sqlite3_create_function API on the given database in order
drhc22bd472002-05-10 13:14:07 +0000478** to create a function named "x_count". This function does the same thing
479** as the "md5sum" function.
480**
481** The original motivation for this routine was to be able to call the
danielk19776f8a5032004-05-10 10:34:51 +0000482** sqlite3_create_aggregate function while a query is in progress in order
drhc22bd472002-05-10 13:14:07 +0000483** to test the SQLITE_MISUSE detection logic.
484*/
drhc2eef3b2002-08-31 18:53:06 +0000485static int test_create_aggregate(
drhc22bd472002-05-10 13:14:07 +0000486 void *NotUsed,
487 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
488 int argc, /* Number of arguments */
489 char **argv /* Text of each argument */
490){
491 sqlite *db;
492 if( argc!=2 ){
493 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
494 " FILENAME\"", 0);
495 return TCL_ERROR;
496 }
drhb86ccfb2003-01-28 23:13:10 +0000497 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk1977f9d64d22004-06-19 08:18:07 +0000498 sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0,
danielk1977d8123362004-06-12 09:25:12 +0000499 countStep,countFinalize);
danielk1977f9d64d22004-06-19 08:18:07 +0000500 sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0,
danielk1977d8123362004-06-12 09:25:12 +0000501 countStep,countFinalize);
drhc22bd472002-05-10 13:14:07 +0000502 return TCL_OK;
503}
504
505
506
507/*
danielk19776f8a5032004-05-10 10:34:51 +0000508** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER
drhd1bf3512001-04-07 15:24:33 +0000509**
510** Call mprintf with three integer arguments
511*/
danielk19776f8a5032004-05-10 10:34:51 +0000512static int sqlite3_mprintf_int(
drhd1bf3512001-04-07 15:24:33 +0000513 void *NotUsed,
514 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
515 int argc, /* Number of arguments */
516 char **argv /* Text of each argument */
517){
518 int a[3], i;
519 char *z;
520 if( argc!=5 ){
521 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
522 " FORMAT INT INT INT\"", 0);
523 return TCL_ERROR;
524 }
525 for(i=2; i<5; i++){
526 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
527 }
danielk19776f8a5032004-05-10 10:34:51 +0000528 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
drhd1bf3512001-04-07 15:24:33 +0000529 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000530 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +0000531 return TCL_OK;
532}
533
534/*
drhe9707672004-06-25 01:10:48 +0000535** Usage: sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER
536**
537** Call mprintf with three 64-bit integer arguments
538*/
539static int sqlite3_mprintf_int64(
540 void *NotUsed,
541 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
542 int argc, /* Number of arguments */
543 char **argv /* Text of each argument */
544){
545 int i;
546 sqlite_int64 a[3];
547 char *z;
548 if( argc!=5 ){
549 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
550 " FORMAT INT INT INT\"", 0);
551 return TCL_ERROR;
552 }
553 for(i=2; i<5; i++){
554 if( !sqlite3GetInt64(argv[i], &a[i-2]) ){
555 Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0);
556 return TCL_ERROR;
557 }
558 }
559 z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
560 Tcl_AppendResult(interp, z, 0);
561 sqlite3_free(z);
562 return TCL_OK;
563}
564
565/*
danielk19776f8a5032004-05-10 10:34:51 +0000566** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING
drhd1bf3512001-04-07 15:24:33 +0000567**
568** Call mprintf with two integer arguments and one string argument
569*/
danielk19776f8a5032004-05-10 10:34:51 +0000570static int sqlite3_mprintf_str(
drhd1bf3512001-04-07 15:24:33 +0000571 void *NotUsed,
572 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
573 int argc, /* Number of arguments */
574 char **argv /* Text of each argument */
575){
576 int a[3], i;
577 char *z;
chwf220b242002-06-16 04:54:28 +0000578 if( argc<4 || argc>5 ){
drhd1bf3512001-04-07 15:24:33 +0000579 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
chwf220b242002-06-16 04:54:28 +0000580 " FORMAT INT INT ?STRING?\"", 0);
drhd1bf3512001-04-07 15:24:33 +0000581 return TCL_ERROR;
582 }
583 for(i=2; i<4; i++){
584 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
585 }
danielk19776f8a5032004-05-10 10:34:51 +0000586 z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL);
drhd1bf3512001-04-07 15:24:33 +0000587 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000588 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +0000589 return TCL_OK;
590}
591
592/*
danielk19776f8a5032004-05-10 10:34:51 +0000593** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER DOUBLE
drhd1bf3512001-04-07 15:24:33 +0000594**
595** Call mprintf with two integer arguments and one double argument
596*/
danielk19776f8a5032004-05-10 10:34:51 +0000597static int sqlite3_mprintf_double(
drhd1bf3512001-04-07 15:24:33 +0000598 void *NotUsed,
599 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
600 int argc, /* Number of arguments */
601 char **argv /* Text of each argument */
602){
603 int a[3], i;
604 double r;
605 char *z;
606 if( argc!=5 ){
607 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
608 " FORMAT INT INT STRING\"", 0);
609 return TCL_ERROR;
610 }
611 for(i=2; i<4; i++){
612 if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
613 }
614 if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
danielk19776f8a5032004-05-10 10:34:51 +0000615 z = sqlite3_mprintf(argv[1], a[0], a[1], r);
drhd1bf3512001-04-07 15:24:33 +0000616 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000617 sqlite3_free(z);
drhd1bf3512001-04-07 15:24:33 +0000618 return TCL_OK;
619}
620
621/*
danielk19776f8a5032004-05-10 10:34:51 +0000622** Usage: sqlite3_mprintf_str FORMAT DOUBLE DOUBLE
drhb621c232004-02-21 19:41:04 +0000623**
624** Call mprintf with a single double argument which is the product of the
625** two arguments given above. This is used to generate overflow and underflow
626** doubles to test that they are converted properly.
627*/
danielk19776f8a5032004-05-10 10:34:51 +0000628static int sqlite3_mprintf_scaled(
drhb621c232004-02-21 19:41:04 +0000629 void *NotUsed,
630 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
631 int argc, /* Number of arguments */
632 char **argv /* Text of each argument */
633){
634 int i;
635 double r[2];
636 char *z;
637 if( argc!=4 ){
638 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
639 " FORMAT DOUBLE DOUBLE\"", 0);
640 return TCL_ERROR;
641 }
642 for(i=2; i<4; i++){
643 if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR;
644 }
danielk19776f8a5032004-05-10 10:34:51 +0000645 z = sqlite3_mprintf(argv[1], r[0]*r[1]);
drhb621c232004-02-21 19:41:04 +0000646 Tcl_AppendResult(interp, z, 0);
drh3f4fedb2004-05-31 19:34:33 +0000647 sqlite3_free(z);
drhb621c232004-02-21 19:41:04 +0000648 return TCL_OK;
649}
650
651/*
drhdaffd0e2001-04-11 14:28:42 +0000652** Usage: sqlite_malloc_fail N
653**
drhafa4a022001-09-24 03:12:39 +0000654** Rig sqliteMalloc() to fail on the N-th call. Turn off this mechanism
danielk19776f8a5032004-05-10 10:34:51 +0000655** and reset the sqlite3_malloc_failed variable is N==0.
drhdaffd0e2001-04-11 14:28:42 +0000656*/
drhfaa57ac2004-06-09 14:01:51 +0000657#ifdef SQLITE_DEBUG
drhdaffd0e2001-04-11 14:28:42 +0000658static int sqlite_malloc_fail(
659 void *NotUsed,
660 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
661 int argc, /* Number of arguments */
662 char **argv /* Text of each argument */
663){
664 int n;
665 if( argc!=2 ){
666 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " N\"", 0);
667 return TCL_ERROR;
668 }
669 if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
danielk19776f8a5032004-05-10 10:34:51 +0000670 sqlite3_iMallocFail = n;
671 sqlite3_malloc_failed = 0;
drhdaffd0e2001-04-11 14:28:42 +0000672 return TCL_OK;
673}
674#endif
675
676/*
677** Usage: sqlite_malloc_stat
678**
679** Return the number of prior calls to sqliteMalloc() and sqliteFree().
680*/
drhfaa57ac2004-06-09 14:01:51 +0000681#ifdef SQLITE_DEBUG
drhdaffd0e2001-04-11 14:28:42 +0000682static int sqlite_malloc_stat(
683 void *NotUsed,
684 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
685 int argc, /* Number of arguments */
686 char **argv /* Text of each argument */
687){
688 char zBuf[200];
danielk19776f8a5032004-05-10 10:34:51 +0000689 sprintf(zBuf, "%d %d %d", sqlite3_nMalloc, sqlite3_nFree, sqlite3_iMallocFail);
drhdaffd0e2001-04-11 14:28:42 +0000690 Tcl_AppendResult(interp, zBuf, 0);
691 return TCL_OK;
692}
693#endif
694
695/*
drh28b4e482002-03-11 02:06:13 +0000696** Usage: sqlite_abort
697**
698** Shutdown the process immediately. This is not a clean shutdown.
699** This command is used to test the recoverability of a database in
700** the event of a program crash.
701*/
702static int sqlite_abort(
703 void *NotUsed,
704 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
705 int argc, /* Number of arguments */
706 char **argv /* Text of each argument */
707){
708 assert( interp==0 ); /* This will always fail */
709 return TCL_OK;
710}
711
712/*
drh6cbe1f12002-07-01 00:31:36 +0000713** The following routine is a user-defined SQL function whose purpose
714** is to test the sqlite_set_result() API.
715*/
danielk19770ae8b832004-05-25 12:05:56 +0000716static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
drh6cbe1f12002-07-01 00:31:36 +0000717 while( argc>=2 ){
drh4f26d6c2004-05-26 23:25:30 +0000718 const char *zArg0 = sqlite3_value_text(argv[0]);
danielk19776d88bad2004-05-27 14:23:36 +0000719 if( zArg0 ){
720 if( 0==sqlite3StrICmp(zArg0, "int") ){
721 sqlite3_result_int(context, sqlite3_value_int(argv[1]));
722 }else if( sqlite3StrICmp(zArg0,"int64")==0 ){
723 sqlite3_result_int64(context, sqlite3_value_int64(argv[1]));
724 }else if( sqlite3StrICmp(zArg0,"string")==0 ){
danielk1977d8123362004-06-12 09:25:12 +0000725 sqlite3_result_text(context, sqlite3_value_text(argv[1]), -1,
726 SQLITE_TRANSIENT);
danielk19776d88bad2004-05-27 14:23:36 +0000727 }else if( sqlite3StrICmp(zArg0,"double")==0 ){
728 sqlite3_result_double(context, sqlite3_value_double(argv[1]));
729 }else if( sqlite3StrICmp(zArg0,"null")==0 ){
730 sqlite3_result_null(context);
731 }else if( sqlite3StrICmp(zArg0,"value")==0 ){
732 sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]);
733 }else{
734 goto error_out;
735 }
drh6cbe1f12002-07-01 00:31:36 +0000736 }else{
danielk19776d88bad2004-05-27 14:23:36 +0000737 goto error_out;
drh6cbe1f12002-07-01 00:31:36 +0000738 }
739 argc -= 2;
740 argv += 2;
741 }
danielk19776d88bad2004-05-27 14:23:36 +0000742 return;
743
744error_out:
745 sqlite3_result_error(context,"first argument should be one of: "
746 "int int64 string double null value", -1);
drh6cbe1f12002-07-01 00:31:36 +0000747}
748
749/*
750** Usage: sqlite_register_test_function DB NAME
751**
752** Register the test SQL function on the database DB under the name NAME.
753*/
drhc2eef3b2002-08-31 18:53:06 +0000754static int test_register_func(
drh6cbe1f12002-07-01 00:31:36 +0000755 void *NotUsed,
756 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
757 int argc, /* Number of arguments */
758 char **argv /* Text of each argument */
759){
760 sqlite *db;
761 int rc;
762 if( argc!=3 ){
763 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
764 " DB FUNCTION-NAME", 0);
765 return TCL_ERROR;
766 }
drhb86ccfb2003-01-28 23:13:10 +0000767 if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
danielk1977f9d64d22004-06-19 08:18:07 +0000768 rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0,
danielk1977d8123362004-06-12 09:25:12 +0000769 testFunc, 0, 0);
drh6cbe1f12002-07-01 00:31:36 +0000770 if( rc!=0 ){
danielk1977f20b21c2004-05-31 23:56:42 +0000771 Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);
drh6cbe1f12002-07-01 00:31:36 +0000772 return TCL_ERROR;
773 }
774 return TCL_OK;
775}
776
777/*
danielk1977106bb232004-05-21 10:08:53 +0000778** Usage: sqlite3_finalize STMT
drhb86ccfb2003-01-28 23:13:10 +0000779**
danielk1977106bb232004-05-21 10:08:53 +0000780** Finalize a statement handle.
drhb86ccfb2003-01-28 23:13:10 +0000781*/
782static int test_finalize(
danielk1977106bb232004-05-21 10:08:53 +0000783 void * clientData,
784 Tcl_Interp *interp,
785 int objc,
786 Tcl_Obj *CONST objv[]
drhb86ccfb2003-01-28 23:13:10 +0000787){
danielk1977106bb232004-05-21 10:08:53 +0000788 sqlite3_stmt *pStmt;
drhb86ccfb2003-01-28 23:13:10 +0000789 int rc;
danielk1977106bb232004-05-21 10:08:53 +0000790
791 if( objc!=2 ){
792 Tcl_AppendResult(interp, "wrong # args: should be \"",
793 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
drhb86ccfb2003-01-28 23:13:10 +0000794 return TCL_ERROR;
795 }
danielk1977106bb232004-05-21 10:08:53 +0000796
797 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
798
danielk1977fc57d7b2004-05-26 02:04:57 +0000799 rc = sqlite3_finalize(pStmt);
danielk1977b77f5da2004-05-26 13:27:00 +0000800 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
danielk1977106bb232004-05-21 10:08:53 +0000801 return TCL_OK;
802}
803
804/*
805** Usage: sqlite3_reset STMT
806**
807** Finalize a statement handle.
808*/
809static int test_reset(
810 void * clientData,
811 Tcl_Interp *interp,
812 int objc,
813 Tcl_Obj *CONST objv[]
814){
815 sqlite3_stmt *pStmt;
816 int rc;
817
818 if( objc!=2 ){
819 Tcl_AppendResult(interp, "wrong # args: should be \"",
820 Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
821 return TCL_ERROR;
822 }
823
824 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
825
danielk1977fc57d7b2004-05-26 02:04:57 +0000826 rc = sqlite3_reset(pStmt);
danielk1977106bb232004-05-21 10:08:53 +0000827 if( rc ){
drhb86ccfb2003-01-28 23:13:10 +0000828 return TCL_ERROR;
829 }
830 return TCL_OK;
831}
832
drh5a387052003-01-11 14:19:51 +0000833/*
danielk1977fbcd5852004-06-15 02:44:18 +0000834** Usage: sqlite3_changes DB
drh50457892003-09-06 01:10:47 +0000835**
danielk1977fbcd5852004-06-15 02:44:18 +0000836** Return the number of changes made to the database by the last SQL
837** execution.
drh50457892003-09-06 01:10:47 +0000838*/
danielk1977fbcd5852004-06-15 02:44:18 +0000839static int test_changes(
840 void * clientData,
841 Tcl_Interp *interp,
842 int objc,
843 Tcl_Obj *CONST objv[]
844){
845 sqlite3 *db;
846 if( objc!=2 ){
847 Tcl_AppendResult(interp, "wrong # args: should be \"",
848 Tcl_GetString(objv[0]), " DB", 0);
849 return TCL_ERROR;
850 }
851 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
852 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db)));
853 return TCL_OK;
854}
drh50457892003-09-06 01:10:47 +0000855
856/*
drh7c972de2003-09-06 22:18:07 +0000857** This is the "static_bind_value" that variables are bound to when
danielk19776f8a5032004-05-10 10:34:51 +0000858** the FLAG option of sqlite3_bind is "static"
drh50457892003-09-06 01:10:47 +0000859*/
drh7c972de2003-09-06 22:18:07 +0000860static char *sqlite_static_bind_value = 0;
861
862/*
danielk19776f8a5032004-05-10 10:34:51 +0000863** Usage: sqlite3_bind VM IDX VALUE FLAGS
drh7c972de2003-09-06 22:18:07 +0000864**
865** Sets the value of the IDX-th occurance of "?" in the original SQL
866** string. VALUE is the new value. If FLAGS=="null" then VALUE is
867** ignored and the value is set to NULL. If FLAGS=="static" then
868** the value is set to the value of a static variable named
869** "sqlite_static_bind_value". If FLAGS=="normal" then a copy
870** of the VALUE is made.
871*/
872static int test_bind(
drh50457892003-09-06 01:10:47 +0000873 void *NotUsed,
874 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
875 int argc, /* Number of arguments */
876 char **argv /* Text of each argument */
877){
danielk1977fc57d7b2004-05-26 02:04:57 +0000878 sqlite3_stmt *pStmt;
drh50457892003-09-06 01:10:47 +0000879 int rc;
drh7c972de2003-09-06 22:18:07 +0000880 int idx;
881 if( argc!=5 ){
drh50457892003-09-06 01:10:47 +0000882 Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
drh7c972de2003-09-06 22:18:07 +0000883 " VM IDX VALUE (null|static|normal)\"", 0);
drh50457892003-09-06 01:10:47 +0000884 return TCL_ERROR;
885 }
danielk1977fc57d7b2004-05-26 02:04:57 +0000886 if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR;
drh7c972de2003-09-06 22:18:07 +0000887 if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR;
888 if( strcmp(argv[4],"null")==0 ){
danielk1977fc57d7b2004-05-26 02:04:57 +0000889 rc = sqlite3_bind_null(pStmt, idx);
drh7c972de2003-09-06 22:18:07 +0000890 }else if( strcmp(argv[4],"static")==0 ){
danielk1977fc57d7b2004-05-26 02:04:57 +0000891 rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0);
drh7c972de2003-09-06 22:18:07 +0000892 }else if( strcmp(argv[4],"normal")==0 ){
danielk1977d8123362004-06-12 09:25:12 +0000893 rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT);
drh7c972de2003-09-06 22:18:07 +0000894 }else{
895 Tcl_AppendResult(interp, "4th argument should be "
896 "\"null\" or \"static\" or \"normal\"", 0);
897 return TCL_ERROR;
898 }
drh50457892003-09-06 01:10:47 +0000899 if( rc ){
900 char zBuf[50];
901 sprintf(zBuf, "(%d) ", rc);
danielk1977f20b21c2004-05-31 23:56:42 +0000902 Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0);
drh50457892003-09-06 01:10:47 +0000903 return TCL_ERROR;
904 }
905 return TCL_OK;
906}
907
danielk19774e6af132004-06-10 14:01:08 +0000908
909/*
910** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be>
911**
912** This function is used to test that SQLite selects the correct collation
913** sequence callback when multiple versions (for different text encodings)
914** are available.
915**
916** Calling this routine registers the collation sequence "test_collate"
917** with database handle <db>. The second argument must be a list of three
918** boolean values. If the first is true, then a version of test_collate is
919** registered for UTF-8, if the second is true, a version is registered for
920** UTF-16le, if the third is true, a UTF-16be version is available.
921** Previous versions of test_collate are deleted.
922**
923** The collation sequence test_collate is implemented by calling the
924** following TCL script:
925**
926** "test_collate <enc> <lhs> <rhs>"
927**
928** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8.
929** The <enc> parameter is the encoding of the collation function that
930** SQLite selected to call. The TCL test script implements the
931** "test_collate" proc.
932**
933** Note that this will only work with one intepreter at a time, as the
934** interp pointer to use when evaluating the TCL script is stored in
935** pTestCollateInterp.
936*/
937static Tcl_Interp* pTestCollateInterp;
938static int test_collate_func(
939 void *pCtx,
940 int nA, const void *zA,
941 int nB, const void *zB
942){
943 Tcl_Interp *i = pTestCollateInterp;
944 int encin = (int)pCtx;
945 int res;
946
947 sqlite3_value *pVal;
948 Tcl_Obj *pX;
949
950 pX = Tcl_NewStringObj("test_collate", -1);
951 Tcl_IncrRefCount(pX);
952
953 switch( encin ){
954 case SQLITE_UTF8:
955 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1));
956 break;
957 case SQLITE_UTF16LE:
958 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1));
959 break;
960 case SQLITE_UTF16BE:
961 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1));
962 break;
963 default:
964 assert(0);
965 }
966
967 pVal = sqlite3ValueNew();
danielk1977bfd6cce2004-06-18 04:24:54 +0000968 sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC);
danielk19774e6af132004-06-10 14:01:08 +0000969 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),-1));
danielk1977bfd6cce2004-06-18 04:24:54 +0000970 sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC);
danielk19774e6af132004-06-10 14:01:08 +0000971 Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj(sqlite3_value_text(pVal),-1));
972 sqlite3ValueFree(pVal);
973
974 Tcl_EvalObjEx(i, pX, 0);
975 Tcl_DecrRefCount(pX);
976 Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res);
977 return res;
978}
979static int test_collate(
980 void * clientData,
981 Tcl_Interp *interp,
982 int objc,
983 Tcl_Obj *CONST objv[]
984){
985 sqlite3 *db;
986 int val;
987
988 if( objc!=5 ) goto bad_args;
989 pTestCollateInterp = interp;
990 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
991
992 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
993 sqlite3_create_collation(db, "test_collate", SQLITE_UTF8,
994 (void *)SQLITE_UTF8, val?test_collate_func:0);
995 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
996 sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE,
997 (void *)SQLITE_UTF16LE, val?test_collate_func:0);
998 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
999 sqlite3_create_collation(db, "test_collate", SQLITE_UTF16BE,
1000 (void *)SQLITE_UTF16BE, val?test_collate_func:0);
1001
1002 return TCL_OK;
1003
1004bad_args:
1005 Tcl_AppendResult(interp, "wrong # args: should be \"",
1006 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
1007 return TCL_ERROR;
1008}
1009
danielk1977c8e9a2d2004-06-25 12:08:46 +00001010/*
1011** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
1012**
1013** This function is used to test that SQLite selects the correct user
1014** function callback when multiple versions (for different text encodings)
1015** are available.
1016**
1017** Calling this routine registers up to three versions of the user function
1018** "test_function" with database handle <db>. If the second argument is
1019** true, then a version of test_function is registered for UTF-8, if the
1020** third is true, a version is registered for UTF-16le, if the fourth is
1021** true, a UTF-16be version is available. Previous versions of
1022** test_function are deleted.
1023**
1024** The user function is implemented by calling the following TCL script:
1025**
1026** "test_function <enc> <arg>"
1027**
1028** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the
1029** single argument passed to the SQL function. The value returned by
1030** the TCL script is used as the return value of the SQL function. It
1031** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8
1032** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
1033** prefers UTF-16BE.
1034*/
1035static void test_function_utf8(
1036 sqlite3_context *pCtx,
1037 int nArg,
1038 sqlite3_value **argv
1039){
1040 Tcl_Interp *interp;
1041 Tcl_Obj *pX;
1042 sqlite3_value *pVal;
1043 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1044 pX = Tcl_NewStringObj("test_function", -1);
1045 Tcl_IncrRefCount(pX);
1046 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1));
1047 Tcl_ListObjAppendElement(interp, pX,
1048 Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1));
1049 Tcl_EvalObjEx(interp, pX, 0);
1050 Tcl_DecrRefCount(pX);
1051 sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT);
1052 pVal = sqlite3ValueNew();
1053 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1054 SQLITE_UTF8, SQLITE_STATIC);
1055 sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal),
1056 -1, SQLITE_TRANSIENT);
1057 sqlite3ValueFree(pVal);
1058}
1059static void test_function_utf16le(
1060 sqlite3_context *pCtx,
1061 int nArg,
1062 sqlite3_value **argv
1063){
1064 Tcl_Interp *interp;
1065 Tcl_Obj *pX;
1066 sqlite3_value *pVal;
1067 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1068 pX = Tcl_NewStringObj("test_function", -1);
1069 Tcl_IncrRefCount(pX);
1070 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1));
1071 Tcl_ListObjAppendElement(interp, pX,
1072 Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1));
1073 Tcl_EvalObjEx(interp, pX, 0);
1074 Tcl_DecrRefCount(pX);
1075 pVal = sqlite3ValueNew();
1076 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1077 SQLITE_UTF8, SQLITE_STATIC);
1078 sqlite3_result_text(pCtx,sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT);
1079 sqlite3ValueFree(pVal);
1080}
1081static void test_function_utf16be(
1082 sqlite3_context *pCtx,
1083 int nArg,
1084 sqlite3_value **argv
1085){
1086 Tcl_Interp *interp;
1087 Tcl_Obj *pX;
1088 sqlite3_value *pVal;
1089 interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
1090 pX = Tcl_NewStringObj("test_function", -1);
1091 Tcl_IncrRefCount(pX);
1092 Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1));
1093 Tcl_ListObjAppendElement(interp, pX,
1094 Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1));
1095 Tcl_EvalObjEx(interp, pX, 0);
1096 Tcl_DecrRefCount(pX);
1097 pVal = sqlite3ValueNew();
1098 sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
1099 SQLITE_UTF8, SQLITE_STATIC);
1100 sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal),
1101 -1, SQLITE_TRANSIENT);
1102 sqlite3ValueFree(pVal);
1103}
1104static int test_function(
1105 void * clientData,
1106 Tcl_Interp *interp,
1107 int objc,
1108 Tcl_Obj *CONST objv[]
1109){
1110 sqlite3 *db;
1111 int val;
1112
1113 if( objc!=5 ) goto bad_args;
1114 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1115
1116 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
1117 if( val ){
1118 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8,
1119 interp, test_function_utf8, 0, 0);
1120 }
1121 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
1122 if( val ){
1123 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE,
1124 interp, test_function_utf16le, 0, 0);
1125 }
1126 if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
1127 if( val ){
1128 sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE,
1129 interp, test_function_utf16be, 0, 0);
1130 }
1131
1132 return TCL_OK;
1133bad_args:
1134 Tcl_AppendResult(interp, "wrong # args: should be \"",
1135 Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
1136 return TCL_ERROR;
1137}
1138
1139static int sqlite3_crashparams(
danielk19778a6c5502004-06-22 12:18:32 +00001140 void * clientData,
1141 Tcl_Interp *interp,
1142 int objc,
1143 Tcl_Obj *CONST objv[]
1144){
1145#ifdef OS_TEST
danielk1977c8e9a2d2004-06-25 12:08:46 +00001146 int delay;
1147 if( objc!=3 ) goto bad_args;
1148 if( Tcl_GetIntFromObj(interp, objv[1], &delay) ) return TCL_ERROR;
1149 sqlite3SetCrashParams(delay, Tcl_GetString(objv[2]));
danielk19778a6c5502004-06-22 12:18:32 +00001150#endif
1151 return TCL_OK;
1152
drh241db312004-06-22 12:46:53 +00001153#ifdef OS_TEST
danielk19778a6c5502004-06-22 12:18:32 +00001154bad_args:
1155 Tcl_AppendResult(interp, "wrong # args: should be \"",
danielk1977c8e9a2d2004-06-25 12:08:46 +00001156 Tcl_GetStringFromObj(objv[0], 0), "<delay> <filename>", 0);
danielk19778a6c5502004-06-22 12:18:32 +00001157 return TCL_ERROR;
drh241db312004-06-22 12:46:53 +00001158#endif
danielk19778a6c5502004-06-22 12:18:32 +00001159}
1160
1161
drh50457892003-09-06 01:10:47 +00001162/*
drh99ee3602003-02-16 19:13:36 +00001163** Usage: breakpoint
1164**
1165** This routine exists for one purpose - to provide a place to put a
1166** breakpoint with GDB that can be triggered using TCL code. The use
1167** for this is when a particular test fails on (say) the 1485th iteration.
1168** In the TCL test script, we can add code like this:
1169**
1170** if {$i==1485} breakpoint
1171**
1172** Then run testfixture in the debugger and wait for the breakpoint to
1173** fire. Then additional breakpoints can be set to trace down the bug.
1174*/
1175static int test_breakpoint(
1176 void *NotUsed,
1177 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
1178 int argc, /* Number of arguments */
1179 char **argv /* Text of each argument */
1180){
1181 return TCL_OK; /* Do nothing */
1182}
1183
drh241db312004-06-22 12:46:53 +00001184/*
1185** Usage: sqlite3_bind_int STMT N VALUE
1186**
1187** Test the sqlite3_bind_int interface. STMT is a prepared statement.
1188** N is the index of a wildcard in the prepared statement. This command
1189** binds a 32-bit integer VALUE to that wildcard.
1190*/
1191static int test_bind_int(
danielk197751e3d8e2004-05-20 01:12:34 +00001192 void * clientData,
1193 Tcl_Interp *interp,
1194 int objc,
1195 Tcl_Obj *CONST objv[]
1196){
1197 sqlite3_stmt *pStmt;
1198 int idx;
1199 int value;
1200 int rc;
1201
1202 if( objc!=4 ){
1203 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001204 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001205 return TCL_ERROR;
1206 }
1207
1208 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1209 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1210 if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
1211
danielk1977c572ef72004-05-27 09:28:41 +00001212 rc = sqlite3_bind_int(pStmt, idx, value);
danielk197751e3d8e2004-05-20 01:12:34 +00001213 if( rc!=SQLITE_OK ){
1214 return TCL_ERROR;
1215 }
1216
1217 return TCL_OK;
1218}
1219
drh241db312004-06-22 12:46:53 +00001220
1221/*
1222** Usage: sqlite3_bind_int64 STMT N VALUE
1223**
1224** Test the sqlite3_bind_int64 interface. STMT is a prepared statement.
1225** N is the index of a wildcard in the prepared statement. This command
1226** binds a 64-bit integer VALUE to that wildcard.
1227*/
danielk197751e3d8e2004-05-20 01:12:34 +00001228static int test_bind_int64(
1229 void * clientData,
1230 Tcl_Interp *interp,
1231 int objc,
1232 Tcl_Obj *CONST objv[]
1233){
1234 sqlite3_stmt *pStmt;
1235 int idx;
1236 i64 value;
1237 int rc;
1238
1239 if( objc!=4 ){
1240 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001241 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001242 return TCL_ERROR;
1243 }
1244
1245 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1246 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1247 if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
1248
1249 rc = sqlite3_bind_int64(pStmt, idx, value);
1250 if( rc!=SQLITE_OK ){
1251 return TCL_ERROR;
1252 }
1253
1254 return TCL_OK;
1255}
1256
drh241db312004-06-22 12:46:53 +00001257
1258/*
1259** Usage: sqlite3_bind_double STMT N VALUE
1260**
1261** Test the sqlite3_bind_double interface. STMT is a prepared statement.
1262** N is the index of a wildcard in the prepared statement. This command
1263** binds a 64-bit integer VALUE to that wildcard.
1264*/
danielk197751e3d8e2004-05-20 01:12:34 +00001265static int test_bind_double(
1266 void * clientData,
1267 Tcl_Interp *interp,
1268 int objc,
1269 Tcl_Obj *CONST objv[]
1270){
1271 sqlite3_stmt *pStmt;
1272 int idx;
1273 double value;
1274 int rc;
1275
1276 if( objc!=4 ){
1277 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001278 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001279 return TCL_ERROR;
1280 }
1281
1282 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1283 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1284 if( Tcl_GetDoubleFromObj(interp, objv[3], &value) ) return TCL_ERROR;
1285
1286 rc = sqlite3_bind_double(pStmt, idx, value);
1287 if( rc!=SQLITE_OK ){
1288 return TCL_ERROR;
1289 }
1290
1291 return TCL_OK;
1292}
1293
drh241db312004-06-22 12:46:53 +00001294/*
1295** Usage: sqlite3_bind_null STMT N
1296**
1297** Test the sqlite3_bind_null interface. STMT is a prepared statement.
1298** N is the index of a wildcard in the prepared statement. This command
1299** binds a NULL to the wildcard.
1300*/
danielk197751e3d8e2004-05-20 01:12:34 +00001301static int test_bind_null(
1302 void * clientData,
1303 Tcl_Interp *interp,
1304 int objc,
1305 Tcl_Obj *CONST objv[]
1306){
1307 sqlite3_stmt *pStmt;
1308 int idx;
1309 int rc;
1310
1311 if( objc!=3 ){
1312 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001313 Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001314 return TCL_ERROR;
1315 }
1316
1317 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1318 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1319
1320 rc = sqlite3_bind_null(pStmt, idx);
1321 if( rc!=SQLITE_OK ){
1322 return TCL_ERROR;
1323 }
1324
1325 return TCL_OK;
1326}
1327
drh241db312004-06-22 12:46:53 +00001328/*
1329** Usage: sqlite3_bind_text STMT N STRING BYTES
1330**
1331** Test the sqlite3_bind_text interface. STMT is a prepared statement.
1332** N is the index of a wildcard in the prepared statement. This command
1333** binds a UTF-8 string STRING to the wildcard. The string is BYTES bytes
1334** long.
1335*/
danielk197751e3d8e2004-05-20 01:12:34 +00001336static int test_bind_text(
1337 void * clientData,
1338 Tcl_Interp *interp,
1339 int objc,
1340 Tcl_Obj *CONST objv[]
1341){
1342 sqlite3_stmt *pStmt;
1343 int idx;
1344 int bytes;
1345 char *value;
1346 int rc;
1347
1348 if( objc!=5 ){
1349 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001350 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001351 return TCL_ERROR;
1352 }
1353
1354 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1355 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1356 value = Tcl_GetString(objv[3]);
1357 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
1358
danielk1977d8123362004-06-12 09:25:12 +00001359 rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
danielk197751e3d8e2004-05-20 01:12:34 +00001360 if( rc!=SQLITE_OK ){
1361 return TCL_ERROR;
1362 }
1363
1364 return TCL_OK;
1365}
1366
drh241db312004-06-22 12:46:53 +00001367/*
1368** Usage: sqlite3_bind_text16 STMT N STRING BYTES
1369**
1370** Test the sqlite3_bind_text16 interface. STMT is a prepared statement.
1371** N is the index of a wildcard in the prepared statement. This command
1372** binds a UTF-16 string STRING to the wildcard. The string is BYTES bytes
1373** long.
1374*/
danielk197751e3d8e2004-05-20 01:12:34 +00001375static int test_bind_text16(
1376 void * clientData,
1377 Tcl_Interp *interp,
1378 int objc,
1379 Tcl_Obj *CONST objv[]
1380){
1381 sqlite3_stmt *pStmt;
1382 int idx;
1383 int bytes;
1384 char *value;
1385 int rc;
1386
1387 if( objc!=5 ){
1388 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001389 Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001390 return TCL_ERROR;
1391 }
1392
1393 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1394 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1395 value = Tcl_GetByteArrayFromObj(objv[3], 0);
1396 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
1397
danielk1977d8123362004-06-12 09:25:12 +00001398 rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, SQLITE_TRANSIENT);
danielk197751e3d8e2004-05-20 01:12:34 +00001399 if( rc!=SQLITE_OK ){
1400 return TCL_ERROR;
1401 }
1402
1403 return TCL_OK;
1404}
1405
drh241db312004-06-22 12:46:53 +00001406/*
1407** Usage: sqlite3_bind_blob STMT N DATA BYTES
1408**
1409** Test the sqlite3_bind_blob interface. STMT is a prepared statement.
1410** N is the index of a wildcard in the prepared statement. This command
1411** binds a BLOB to the wildcard. The BLOB is BYTES bytes in size.
1412*/
danielk197751e3d8e2004-05-20 01:12:34 +00001413static int test_bind_blob(
1414 void * clientData,
1415 Tcl_Interp *interp,
1416 int objc,
1417 Tcl_Obj *CONST objv[]
1418){
1419 sqlite3_stmt *pStmt;
1420 int idx;
1421 int bytes;
1422 char *value;
1423 int rc;
1424
1425 if( objc!=5 ){
1426 Tcl_AppendResult(interp, "wrong # args: should be \"",
drh241db312004-06-22 12:46:53 +00001427 Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0);
danielk197751e3d8e2004-05-20 01:12:34 +00001428 return TCL_ERROR;
1429 }
1430
1431 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1432 if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
1433 value = Tcl_GetString(objv[3]);
danielk197749e46432004-05-27 13:55:27 +00001434 if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
danielk197751e3d8e2004-05-20 01:12:34 +00001435
danielk1977d8123362004-06-12 09:25:12 +00001436 rc = sqlite3_bind_blob(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
danielk197751e3d8e2004-05-20 01:12:34 +00001437 if( rc!=SQLITE_OK ){
1438 return TCL_ERROR;
1439 }
1440
1441 return TCL_OK;
1442}
1443
drh99ee3602003-02-16 19:13:36 +00001444/*
danielk19776622cce2004-05-20 11:00:52 +00001445** Usage: sqlite3_errcode DB
1446**
1447** Return the string representation of the most recent sqlite3_* API
1448** error code. e.g. "SQLITE_ERROR".
1449*/
1450static int test_errcode(
1451 void * clientData,
1452 Tcl_Interp *interp,
1453 int objc,
1454 Tcl_Obj *CONST objv[]
1455){
1456 sqlite3 *db;
1457
1458 if( objc!=2 ){
1459 Tcl_AppendResult(interp, "wrong # args: should be \"",
1460 Tcl_GetString(objv[0]), " DB", 0);
1461 return TCL_ERROR;
1462 }
1463 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1464 Tcl_SetResult(interp, (char *)errorName(sqlite3_errcode(db)), 0);
1465 return TCL_OK;
1466}
1467
1468/*
1469** Usage: test_errmsg DB
1470**
1471** Returns the UTF-8 representation of the error message string for the
1472** most recent sqlite3_* API call.
1473*/
1474static int test_errmsg(
1475 void * clientData,
1476 Tcl_Interp *interp,
1477 int objc,
1478 Tcl_Obj *CONST objv[]
1479){
1480 sqlite *db;
1481 const char *zErr;
1482
1483 if( objc!=2 ){
1484 Tcl_AppendResult(interp, "wrong # args: should be \"",
1485 Tcl_GetString(objv[0]), " DB", 0);
1486 return TCL_ERROR;
1487 }
1488 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1489
1490 zErr = sqlite3_errmsg(db);
1491 Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
1492 return TCL_OK;
1493}
1494
1495/*
1496** Usage: test_errmsg16 DB
1497**
1498** Returns the UTF-16 representation of the error message string for the
1499** most recent sqlite3_* API call. This is a byte array object at the TCL
1500** level, and it includes the 0x00 0x00 terminator bytes at the end of the
1501** UTF-16 string.
1502*/
1503static int test_errmsg16(
1504 void * clientData,
1505 Tcl_Interp *interp,
1506 int objc,
1507 Tcl_Obj *CONST objv[]
1508){
1509 sqlite *db;
1510 const void *zErr;
1511 int bytes;
1512
1513 if( objc!=2 ){
1514 Tcl_AppendResult(interp, "wrong # args: should be \"",
1515 Tcl_GetString(objv[0]), " DB", 0);
1516 return TCL_ERROR;
1517 }
1518 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1519
1520 zErr = sqlite3_errmsg16(db);
1521 bytes = sqlite3utf16ByteLen(zErr, -1);
1522 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes));
1523 return TCL_OK;
1524}
1525
1526/*
1527** Usage: sqlite3_prepare DB sql bytes tailvar
1528**
1529** Compile up to <bytes> bytes of the supplied SQL string <sql> using
1530** database handle <DB>. The parameter <tailval> is the name of a global
1531** variable that is set to the unused portion of <sql> (if any). A
1532** STMT handle is returned.
1533*/
1534static int test_prepare(
1535 void * clientData,
1536 Tcl_Interp *interp,
1537 int objc,
1538 Tcl_Obj *CONST objv[]
1539){
1540 sqlite3 *db;
1541 const char *zSql;
1542 int bytes;
1543 const char *zTail = 0;
1544 sqlite3_stmt *pStmt = 0;
1545 char zBuf[50];
danielk19774ad17132004-05-21 01:47:26 +00001546 int rc;
danielk19776622cce2004-05-20 11:00:52 +00001547
1548 if( objc!=5 ){
1549 Tcl_AppendResult(interp, "wrong # args: should be \"",
1550 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
1551 return TCL_ERROR;
1552 }
1553 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1554 zSql = Tcl_GetString(objv[2]);
1555 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
1556
danielk19774ad17132004-05-21 01:47:26 +00001557 rc = sqlite3_prepare(db, zSql, bytes, &pStmt, &zTail);
danielk19776622cce2004-05-20 11:00:52 +00001558 if( zTail ){
1559 if( bytes>=0 ){
1560 bytes = bytes - (zTail-zSql);
1561 }
1562 Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
1563 }
danielk19774ad17132004-05-21 01:47:26 +00001564 if( rc!=SQLITE_OK ){
1565 assert( pStmt==0 );
1566 sprintf(zBuf, "(%d) ", rc);
1567 Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
1568 return TCL_ERROR;
1569 }
danielk19776622cce2004-05-20 11:00:52 +00001570
danielk19774ad17132004-05-21 01:47:26 +00001571 if( pStmt ){
1572 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
1573 Tcl_AppendResult(interp, zBuf, 0);
1574 }
danielk19776622cce2004-05-20 11:00:52 +00001575 return TCL_OK;
1576}
1577
1578/*
1579** Usage: sqlite3_prepare DB sql bytes tailvar
1580**
1581** Compile up to <bytes> bytes of the supplied SQL string <sql> using
1582** database handle <DB>. The parameter <tailval> is the name of a global
1583** variable that is set to the unused portion of <sql> (if any). A
1584** STMT handle is returned.
1585*/
1586static int test_prepare16(
1587 void * clientData,
1588 Tcl_Interp *interp,
1589 int objc,
1590 Tcl_Obj *CONST objv[]
1591){
1592 sqlite3 *db;
1593 const void *zSql;
1594 const void *zTail = 0;
1595 Tcl_Obj *pTail = 0;
1596 sqlite3_stmt *pStmt = 0;
1597 char zBuf[50];
1598 int bytes; /* The integer specified as arg 3 */
1599 int objlen; /* The byte-array length of arg 2 */
1600
1601 if( objc!=5 ){
1602 Tcl_AppendResult(interp, "wrong # args: should be \"",
1603 Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
1604 return TCL_ERROR;
1605 }
1606 if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
1607 zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
1608 if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
1609
1610 if( SQLITE_OK!=sqlite3_prepare16(db, zSql, bytes, &pStmt, &zTail) ){
1611 return TCL_ERROR;
1612 }
1613
1614 if( zTail ){
1615 objlen = objlen - ((u8 *)zTail-(u8 *)zSql);
1616 }else{
1617 objlen = 0;
1618 }
1619 pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
1620 Tcl_IncrRefCount(pTail);
1621 Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
danielk19774ad17132004-05-21 01:47:26 +00001622 Tcl_DecrRefCount(pTail);
danielk19776622cce2004-05-20 11:00:52 +00001623
danielk19774ad17132004-05-21 01:47:26 +00001624 if( pStmt ){
1625 if( makePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
1626 }
danielk19776622cce2004-05-20 11:00:52 +00001627 Tcl_AppendResult(interp, zBuf, 0);
1628 return TCL_OK;
1629}
1630
danielk19774ad17132004-05-21 01:47:26 +00001631/*
1632** Usage: sqlite3_open filename ?options-list?
1633*/
1634static int test_open(
1635 void * clientData,
1636 Tcl_Interp *interp,
1637 int objc,
1638 Tcl_Obj *CONST objv[]
1639){
1640 const char *zFilename;
1641 sqlite3 *db;
1642 int rc;
1643 char zBuf[100];
1644
1645 if( objc!=3 && objc!=2 ){
1646 Tcl_AppendResult(interp, "wrong # args: should be \"",
1647 Tcl_GetString(objv[0]), " filename options-list", 0);
1648 return TCL_ERROR;
1649 }
1650
1651 zFilename = Tcl_GetString(objv[1]);
danielk19774f057f92004-06-08 00:02:33 +00001652 rc = sqlite3_open(zFilename, &db);
danielk19774ad17132004-05-21 01:47:26 +00001653
1654 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR;
1655 Tcl_AppendResult(interp, zBuf, 0);
1656 return TCL_OK;
1657}
1658
1659/*
1660** Usage: sqlite3_open16 filename options
1661*/
1662static int test_open16(
1663 void * clientData,
1664 Tcl_Interp *interp,
1665 int objc,
1666 Tcl_Obj *CONST objv[]
1667){
1668 const void *zFilename;
1669 sqlite3 *db;
1670 int rc;
1671 char zBuf[100];
1672
1673 if( objc!=3 ){
1674 Tcl_AppendResult(interp, "wrong # args: should be \"",
1675 Tcl_GetString(objv[0]), " filename options-list", 0);
1676 return TCL_ERROR;
1677 }
1678
1679 zFilename = Tcl_GetByteArrayFromObj(objv[1], 0);
danielk19774f057f92004-06-08 00:02:33 +00001680 rc = sqlite3_open16(zFilename, &db);
danielk19774ad17132004-05-21 01:47:26 +00001681
1682 if( makePointerStr(interp, zBuf, db) ) return TCL_ERROR;
1683 Tcl_AppendResult(interp, zBuf, 0);
1684 return TCL_OK;
1685}
drhd3d39e92004-05-20 22:16:29 +00001686
1687/*
danielk1977106bb232004-05-21 10:08:53 +00001688** Usage: sqlite3_step STMT
1689**
1690** Advance the statement to the next row.
1691*/
danielk197717240fd2004-05-26 00:07:25 +00001692static int test_step(
danielk1977106bb232004-05-21 10:08:53 +00001693 void * clientData,
1694 Tcl_Interp *interp,
1695 int objc,
1696 Tcl_Obj *CONST objv[]
1697){
1698 sqlite3_stmt *pStmt;
1699 int rc;
1700
danielk1977e1cd9872004-05-22 10:33:04 +00001701 if( objc!=2 ){
danielk1977106bb232004-05-21 10:08:53 +00001702 Tcl_AppendResult(interp, "wrong # args: should be \"",
1703 Tcl_GetString(objv[0]), " STMT", 0);
1704 return TCL_ERROR;
1705 }
1706
1707 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
danielk197717240fd2004-05-26 00:07:25 +00001708 rc = sqlite3_step(pStmt);
danielk1977106bb232004-05-21 10:08:53 +00001709
danielk1977fbcd5852004-06-15 02:44:18 +00001710 /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */
danielk197765904932004-05-26 06:18:37 +00001711 Tcl_SetResult(interp, (char *)errorName(rc), 0);
danielk1977e1cd9872004-05-22 10:33:04 +00001712 return TCL_OK;
1713}
1714
1715/*
danielk197717240fd2004-05-26 00:07:25 +00001716** Usage: sqlite3_column_count STMT
1717**
1718** Return the number of columns returned by the sql statement STMT.
1719*/
1720static int test_column_count(
1721 void * clientData,
1722 Tcl_Interp *interp,
1723 int objc,
1724 Tcl_Obj *CONST objv[]
1725){
1726 sqlite3_stmt *pStmt;
1727
1728 if( objc!=2 ){
1729 Tcl_AppendResult(interp, "wrong # args: should be \"",
1730 Tcl_GetString(objv[0]), " STMT column", 0);
1731 return TCL_ERROR;
1732 }
1733
1734 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1735
1736 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt)));
1737 return TCL_OK;
1738}
1739
1740/*
danielk19773cf86062004-05-26 10:11:05 +00001741** Usage: sqlite3_column_type STMT column
1742**
1743** Return the type of the data in column 'column' of the current row.
1744*/
1745static int test_column_type(
1746 void * clientData,
1747 Tcl_Interp *interp,
1748 int objc,
1749 Tcl_Obj *CONST objv[]
1750){
1751 sqlite3_stmt *pStmt;
1752 int col;
1753 int tp;
1754
1755 if( objc!=3 ){
1756 Tcl_AppendResult(interp, "wrong # args: should be \"",
1757 Tcl_GetString(objv[0]), " STMT column", 0);
1758 return TCL_ERROR;
1759 }
1760
1761 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1762 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
1763
1764 tp = sqlite3_column_type(pStmt, col);
1765 switch( tp ){
drh9c054832004-05-31 18:51:57 +00001766 case SQLITE_INTEGER:
danielk19773cf86062004-05-26 10:11:05 +00001767 Tcl_SetResult(interp, "INTEGER", TCL_STATIC);
1768 break;
drh9c054832004-05-31 18:51:57 +00001769 case SQLITE_NULL:
danielk19773cf86062004-05-26 10:11:05 +00001770 Tcl_SetResult(interp, "NULL", TCL_STATIC);
1771 break;
drh9c054832004-05-31 18:51:57 +00001772 case SQLITE_FLOAT:
danielk19773cf86062004-05-26 10:11:05 +00001773 Tcl_SetResult(interp, "FLOAT", TCL_STATIC);
1774 break;
drh9c054832004-05-31 18:51:57 +00001775 case SQLITE_TEXT:
danielk19773cf86062004-05-26 10:11:05 +00001776 Tcl_SetResult(interp, "TEXT", TCL_STATIC);
1777 break;
drh9c054832004-05-31 18:51:57 +00001778 case SQLITE_BLOB:
danielk19773cf86062004-05-26 10:11:05 +00001779 Tcl_SetResult(interp, "BLOB", TCL_STATIC);
1780 break;
1781 default:
1782 assert(0);
1783 }
1784
1785 return TCL_OK;
1786}
1787
1788/*
danielk197704f2e682004-05-27 01:04:07 +00001789** Usage: sqlite3_column_int64 STMT column
danielk19773cf86062004-05-26 10:11:05 +00001790**
1791** Return the data in column 'column' of the current row cast as an
danielk197704f2e682004-05-27 01:04:07 +00001792** wide (64-bit) integer.
danielk19773cf86062004-05-26 10:11:05 +00001793*/
danielk197704f2e682004-05-27 01:04:07 +00001794static int test_column_int64(
danielk19773cf86062004-05-26 10:11:05 +00001795 void * clientData,
1796 Tcl_Interp *interp,
1797 int objc,
1798 Tcl_Obj *CONST objv[]
1799){
1800 sqlite3_stmt *pStmt;
1801 int col;
danielk197704f2e682004-05-27 01:04:07 +00001802 i64 iVal;
danielk19773cf86062004-05-26 10:11:05 +00001803
1804 if( objc!=3 ){
1805 Tcl_AppendResult(interp, "wrong # args: should be \"",
1806 Tcl_GetString(objv[0]), " STMT column", 0);
1807 return TCL_ERROR;
1808 }
1809
1810 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1811 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
1812
danielk197704f2e682004-05-27 01:04:07 +00001813 iVal = sqlite3_column_int64(pStmt, col);
1814 Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal));
1815 return TCL_OK;
1816}
1817
1818/*
danielk1977ea61b2c2004-05-27 01:49:51 +00001819** Usage: sqlite3_column_blob STMT column
1820*/
1821static int test_column_blob(
1822 void * clientData,
1823 Tcl_Interp *interp,
1824 int objc,
1825 Tcl_Obj *CONST objv[]
1826){
1827 sqlite3_stmt *pStmt;
1828 int col;
1829
1830 int len;
danielk1977c572ef72004-05-27 09:28:41 +00001831 const void *pBlob;
danielk1977ea61b2c2004-05-27 01:49:51 +00001832
1833 if( objc!=3 ){
1834 Tcl_AppendResult(interp, "wrong # args: should be \"",
1835 Tcl_GetString(objv[0]), " STMT column", 0);
1836 return TCL_ERROR;
1837 }
1838
1839 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1840 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
1841
1842 pBlob = sqlite3_column_blob(pStmt, col);
1843 len = sqlite3_column_bytes(pStmt, col);
1844 Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len));
1845 return TCL_OK;
1846}
1847
1848/*
danielk197704f2e682004-05-27 01:04:07 +00001849** Usage: sqlite3_column_double STMT column
1850**
1851** Return the data in column 'column' of the current row cast as a double.
1852*/
1853static int test_column_double(
1854 void * clientData,
1855 Tcl_Interp *interp,
1856 int objc,
1857 Tcl_Obj *CONST objv[]
1858){
1859 sqlite3_stmt *pStmt;
1860 int col;
1861 double rVal;
1862
1863 if( objc!=3 ){
1864 Tcl_AppendResult(interp, "wrong # args: should be \"",
1865 Tcl_GetString(objv[0]), " STMT column", 0);
1866 return TCL_ERROR;
1867 }
1868
1869 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1870 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
1871
1872 rVal = sqlite3_column_double(pStmt, col);
danielk1977c572ef72004-05-27 09:28:41 +00001873 Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal));
danielk19773cf86062004-05-26 10:11:05 +00001874 return TCL_OK;
1875}
1876
1877/*
danielk197717240fd2004-05-26 00:07:25 +00001878** Usage: sqlite3_data_count STMT
1879**
1880** Return the number of columns returned by the sql statement STMT.
1881*/
1882static int test_data_count(
1883 void * clientData,
1884 Tcl_Interp *interp,
1885 int objc,
1886 Tcl_Obj *CONST objv[]
1887){
1888 sqlite3_stmt *pStmt;
1889
1890 if( objc!=2 ){
1891 Tcl_AppendResult(interp, "wrong # args: should be \"",
1892 Tcl_GetString(objv[0]), " STMT column", 0);
1893 return TCL_ERROR;
1894 }
1895
1896 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1897
1898 Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt)));
1899 return TCL_OK;
1900}
1901
1902/*
danielk197704f2e682004-05-27 01:04:07 +00001903** Usage: sqlite3_column_text STMT column
1904**
1905** Usage: sqlite3_column_decltype STMT column
1906**
1907** Usage: sqlite3_column_name STMT column
1908*/
1909static int test_stmt_utf8(
drh241db312004-06-22 12:46:53 +00001910 void * clientData, /* Pointer to SQLite API function to be invoke */
danielk197704f2e682004-05-27 01:04:07 +00001911 Tcl_Interp *interp,
1912 int objc,
1913 Tcl_Obj *CONST objv[]
1914){
1915 sqlite3_stmt *pStmt;
1916 int col;
danielk1977c572ef72004-05-27 09:28:41 +00001917 const char *(*xFunc)(sqlite3_stmt*, int) = clientData;
danielk1977f93bbbe2004-05-27 10:30:52 +00001918 const char *zRet;
danielk197704f2e682004-05-27 01:04:07 +00001919
1920 if( objc!=3 ){
1921 Tcl_AppendResult(interp, "wrong # args: should be \"",
1922 Tcl_GetString(objv[0]), " STMT column", 0);
1923 return TCL_ERROR;
1924 }
1925
1926 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1927 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
danielk1977f93bbbe2004-05-27 10:30:52 +00001928 zRet = xFunc(pStmt, col);
1929 if( zRet ){
1930 Tcl_SetResult(interp, (char *)zRet, 0);
1931 }
danielk197704f2e682004-05-27 01:04:07 +00001932 return TCL_OK;
1933}
1934
1935/*
1936** Usage: sqlite3_column_text STMT column
1937**
1938** Usage: sqlite3_column_decltype STMT column
1939**
1940** Usage: sqlite3_column_name STMT column
1941*/
1942static int test_stmt_utf16(
drh241db312004-06-22 12:46:53 +00001943 void * clientData, /* Pointer to SQLite API function to be invoked */
danielk197704f2e682004-05-27 01:04:07 +00001944 Tcl_Interp *interp,
1945 int objc,
1946 Tcl_Obj *CONST objv[]
1947){
1948 sqlite3_stmt *pStmt;
1949 int col;
1950 Tcl_Obj *pRet;
1951 const void *zName16;
danielk1977c572ef72004-05-27 09:28:41 +00001952 const void *(*xFunc)(sqlite3_stmt*, int) = clientData;
danielk197704f2e682004-05-27 01:04:07 +00001953
1954 if( objc!=3 ){
1955 Tcl_AppendResult(interp, "wrong # args: should be \"",
1956 Tcl_GetString(objv[0]), " STMT column", 0);
1957 return TCL_ERROR;
1958 }
1959
1960 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1961 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
1962
1963 zName16 = xFunc(pStmt, col);
danielk1977f93bbbe2004-05-27 10:30:52 +00001964 if( zName16 ){
1965 pRet = Tcl_NewByteArrayObj(zName16, sqlite3utf16ByteLen(zName16, -1)+2);
1966 Tcl_SetObjResult(interp, pRet);
1967 }
danielk197704f2e682004-05-27 01:04:07 +00001968
1969 return TCL_OK;
1970}
1971
1972/*
1973** Usage: sqlite3_column_int STMT column
1974**
1975** Usage: sqlite3_column_bytes STMT column
1976**
1977** Usage: sqlite3_column_bytes16 STMT column
1978**
1979*/
1980static int test_stmt_int(
drh241db312004-06-22 12:46:53 +00001981 void * clientData, /* Pointer to SQLite API function to be invoked */
danielk197704f2e682004-05-27 01:04:07 +00001982 Tcl_Interp *interp,
1983 int objc,
1984 Tcl_Obj *CONST objv[]
1985){
1986 sqlite3_stmt *pStmt;
1987 int col;
danielk1977c572ef72004-05-27 09:28:41 +00001988 int (*xFunc)(sqlite3_stmt*, int) = clientData;
danielk197704f2e682004-05-27 01:04:07 +00001989
1990 if( objc!=3 ){
1991 Tcl_AppendResult(interp, "wrong # args: should be \"",
1992 Tcl_GetString(objv[0]), " STMT column", 0);
1993 return TCL_ERROR;
1994 }
1995
1996 if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
1997 if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
1998
1999 Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col)));
2000 return TCL_OK;
2001}
2002
danielk19779a1d0ab2004-06-01 14:09:28 +00002003/*
2004** Usage: sqlite3OsOpenReadWrite <filename>
2005*/
2006static int test_sqlite3OsOpenReadWrite(
2007 void * clientData,
2008 Tcl_Interp *interp,
2009 int objc,
2010 Tcl_Obj *CONST objv[]
2011){
2012 OsFile * pFile;
2013 int rc;
2014 int dummy;
2015 char zBuf[100];
danielk197704f2e682004-05-27 01:04:07 +00002016
danielk19779a1d0ab2004-06-01 14:09:28 +00002017 if( objc!=2 ){
2018 Tcl_AppendResult(interp, "wrong # args: should be \"",
2019 Tcl_GetString(objv[0]), " filename", 0);
2020 return TCL_ERROR;
2021 }
2022
2023 pFile = sqliteMalloc(sizeof(OsFile));
2024 rc = sqlite3OsOpenReadWrite(Tcl_GetString(objv[1]), pFile, &dummy);
2025 if( rc!=SQLITE_OK ){
2026 sqliteFree(pFile);
2027 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2028 return TCL_ERROR;
2029 }
2030 makePointerStr(interp, zBuf, pFile);
2031 Tcl_SetResult(interp, zBuf, 0);
2032 return TCL_ERROR;
2033}
2034
2035/*
2036** Usage: sqlite3OsClose <file handle>
2037*/
2038static int test_sqlite3OsClose(
2039 void * clientData,
2040 Tcl_Interp *interp,
2041 int objc,
2042 Tcl_Obj *CONST objv[]
2043){
2044 OsFile * pFile;
2045 int rc;
2046
2047 if( objc!=2 ){
2048 Tcl_AppendResult(interp, "wrong # args: should be \"",
2049 Tcl_GetString(objv[0]), " filehandle", 0);
2050 return TCL_ERROR;
2051 }
2052
2053 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
2054 return TCL_ERROR;
2055 }
2056 rc = sqlite3OsClose(pFile);
2057 if( rc!=SQLITE_OK ){
2058 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2059 return TCL_ERROR;
2060 }
2061 sqliteFree(pFile);
2062 return TCL_OK;
2063}
2064
2065/*
2066** Usage: sqlite3OsLock <file handle> <locktype>
2067*/
2068static int test_sqlite3OsLock(
2069 void * clientData,
2070 Tcl_Interp *interp,
2071 int objc,
2072 Tcl_Obj *CONST objv[]
2073){
2074 OsFile * pFile;
2075 int rc;
2076
2077 if( objc!=3 ){
2078 Tcl_AppendResult(interp, "wrong # args: should be \"",
2079 Tcl_GetString(objv[0]),
2080 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
2081 return TCL_ERROR;
2082 }
2083
2084 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
2085 return TCL_ERROR;
2086 }
2087
2088 if( 0==strcmp("SHARED", Tcl_GetString(objv[2])) ){
2089 rc = sqlite3OsLock(pFile, SHARED_LOCK);
2090 }
2091 else if( 0==strcmp("RESERVED", Tcl_GetString(objv[2])) ){
2092 rc = sqlite3OsLock(pFile, RESERVED_LOCK);
2093 }
2094 else if( 0==strcmp("PENDING", Tcl_GetString(objv[2])) ){
2095 rc = sqlite3OsLock(pFile, PENDING_LOCK);
2096 }
2097 else if( 0==strcmp("EXCLUSIVE", Tcl_GetString(objv[2])) ){
2098 rc = sqlite3OsLock(pFile, EXCLUSIVE_LOCK);
2099 }else{
2100 Tcl_AppendResult(interp, "wrong # args: should be \"",
2101 Tcl_GetString(objv[0]),
2102 " filehandle (SHARED|RESERVED|PENDING|EXCLUSIVE)", 0);
2103 return TCL_ERROR;
2104 }
2105
2106 if( rc!=SQLITE_OK ){
2107 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2108 return TCL_ERROR;
2109 }
2110 return TCL_OK;
2111}
2112
2113/*
2114** Usage: sqlite3OsUnlock <file handle>
2115*/
2116static int test_sqlite3OsUnlock(
2117 void * clientData,
2118 Tcl_Interp *interp,
2119 int objc,
2120 Tcl_Obj *CONST objv[]
2121){
2122 OsFile * pFile;
2123 int rc;
2124
2125 if( objc!=2 ){
2126 Tcl_AppendResult(interp, "wrong # args: should be \"",
2127 Tcl_GetString(objv[0]), " filehandle", 0);
2128 return TCL_ERROR;
2129 }
2130
2131 if( getFilePointer(interp, Tcl_GetString(objv[1]), &pFile) ){
2132 return TCL_ERROR;
2133 }
drha6abd042004-06-09 17:37:22 +00002134 rc = sqlite3OsUnlock(pFile, NO_LOCK);
danielk19779a1d0ab2004-06-01 14:09:28 +00002135 if( rc!=SQLITE_OK ){
2136 Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
2137 return TCL_ERROR;
2138 }
2139 return TCL_OK;
2140}
drhd3d39e92004-05-20 22:16:29 +00002141
danielk1977d8123362004-06-12 09:25:12 +00002142
danielk19776622cce2004-05-20 11:00:52 +00002143/*
drhd1bf3512001-04-07 15:24:33 +00002144** Register commands with the TCL interpreter.
2145*/
2146int Sqlitetest1_Init(Tcl_Interp *interp){
danielk19776f8a5032004-05-10 10:34:51 +00002147 extern int sqlite3_search_count;
2148 extern int sqlite3_interrupt_count;
2149 extern int sqlite3_open_file_count;
2150 extern int sqlite3_current_time;
drhc2eef3b2002-08-31 18:53:06 +00002151 static struct {
2152 char *zName;
2153 Tcl_CmdProc *xProc;
2154 } aCmd[] = {
drhd3d39e92004-05-20 22:16:29 +00002155 { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int },
drhe9707672004-06-25 01:10:48 +00002156 { "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 },
drhd3d39e92004-05-20 22:16:29 +00002157 { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str },
2158 { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double },
2159 { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled },
2160 { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z },
drhd3d39e92004-05-20 22:16:29 +00002161 { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid },
2162 { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf },
2163 { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf },
2164 { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close },
2165 { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function },
2166 { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate },
2167 { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func },
2168 { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort },
drhfaa57ac2004-06-09 14:01:51 +00002169#ifdef SQLITE_DEBUG
drhd3d39e92004-05-20 22:16:29 +00002170 { "sqlite_malloc_fail", (Tcl_CmdProc*)sqlite_malloc_fail },
2171 { "sqlite_malloc_stat", (Tcl_CmdProc*)sqlite_malloc_stat },
drhc2eef3b2002-08-31 18:53:06 +00002172#endif
danielk19774ad17132004-05-21 01:47:26 +00002173 { "sqlite_bind", (Tcl_CmdProc*)test_bind },
danielk19774ad17132004-05-21 01:47:26 +00002174 { "breakpoint", (Tcl_CmdProc*)test_breakpoint },
drhc2eef3b2002-08-31 18:53:06 +00002175 };
danielk197751e3d8e2004-05-20 01:12:34 +00002176 static struct {
2177 char *zName;
2178 Tcl_ObjCmdProc *xProc;
danielk197704f2e682004-05-27 01:04:07 +00002179 void *clientData;
danielk197751e3d8e2004-05-20 01:12:34 +00002180 } aObjCmd[] = {
drh241db312004-06-22 12:46:53 +00002181 { "sqlite3_bind_int", test_bind_int, 0 },
2182 { "sqlite3_bind_int64", test_bind_int64, 0 },
2183 { "sqlite3_bind_double", test_bind_double, 0 },
danielk197704f2e682004-05-27 01:04:07 +00002184 { "sqlite3_bind_null", test_bind_null ,0 },
2185 { "sqlite3_bind_text", test_bind_text ,0 },
2186 { "sqlite3_bind_text16", test_bind_text16 ,0 },
2187 { "sqlite3_bind_blob", test_bind_blob ,0 },
2188 { "sqlite3_errcode", test_errcode ,0 },
2189 { "sqlite3_errmsg", test_errmsg ,0 },
2190 { "sqlite3_errmsg16", test_errmsg16 ,0 },
2191 { "sqlite3_open", test_open ,0 },
2192 { "sqlite3_open16", test_open16 ,0 },
danielk197704f2e682004-05-27 01:04:07 +00002193
2194 { "sqlite3_prepare", test_prepare ,0 },
2195 { "sqlite3_prepare16", test_prepare16 ,0 },
2196 { "sqlite3_finalize", test_finalize ,0 },
2197 { "sqlite3_reset", test_reset ,0 },
danielk1977fbcd5852004-06-15 02:44:18 +00002198 { "sqlite3_changes", test_changes ,0 },
2199 { "sqlite3_step", test_step ,0 },
danielk197704f2e682004-05-27 01:04:07 +00002200
2201 /* sqlite3_column_*() API */
2202 { "sqlite3_column_count", test_column_count ,0 },
2203 { "sqlite3_data_count", test_data_count ,0 },
2204 { "sqlite3_column_type", test_column_type ,0 },
danielk1977ea61b2c2004-05-27 01:49:51 +00002205 { "sqlite3_column_blob", test_column_blob ,0 },
danielk197704f2e682004-05-27 01:04:07 +00002206 { "sqlite3_column_double", test_column_double ,0 },
2207 { "sqlite3_column_int64", test_column_int64 ,0 },
drh241db312004-06-22 12:46:53 +00002208 { "sqlite3_column_int", test_stmt_int, sqlite3_column_int },
2209 { "sqlite3_column_bytes", test_stmt_int, sqlite3_column_bytes },
2210 { "sqlite3_column_bytes16", test_stmt_int, sqlite3_column_bytes16 },
2211 { "sqlite3_column_text", test_stmt_utf8, sqlite3_column_text },
2212 { "sqlite3_column_decltype", test_stmt_utf8, sqlite3_column_decltype },
2213 { "sqlite3_column_name", test_stmt_utf8, sqlite3_column_name },
2214 { "sqlite3_column_text16", test_stmt_utf16, sqlite3_column_text16 },
2215 { "sqlite3_column_decltype16", test_stmt_utf16, sqlite3_column_decltype16},
2216 { "sqlite3_column_name16", test_stmt_utf16, sqlite3_column_name16 },
danielk197704f2e682004-05-27 01:04:07 +00002217
danielk19779a1d0ab2004-06-01 14:09:28 +00002218 /* Functions from os.h */
2219 { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 },
2220 { "sqlite3OsClose", test_sqlite3OsClose, 0 },
2221 { "sqlite3OsLock", test_sqlite3OsLock, 0 },
2222 { "sqlite3OsUnlock", test_sqlite3OsUnlock, 0 },
danielk19774e6af132004-06-10 14:01:08 +00002223 { "add_test_collate", test_collate, 0 },
danielk1977c8e9a2d2004-06-25 12:08:46 +00002224 { "add_test_function", test_function, 0 },
2225 { "sqlite3_crashparams", sqlite3_crashparams, 0 },
danielk19779a1d0ab2004-06-01 14:09:28 +00002226
danielk197751e3d8e2004-05-20 01:12:34 +00002227 };
drhc2eef3b2002-08-31 18:53:06 +00002228 int i;
drh2ac3ee92004-06-07 16:27:46 +00002229 extern int sqlite3_os_trace;
drhc2eef3b2002-08-31 18:53:06 +00002230
2231 for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
2232 Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
2233 }
danielk197751e3d8e2004-05-20 01:12:34 +00002234 for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
danielk1977c572ef72004-05-27 09:28:41 +00002235 Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
2236 aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
danielk197751e3d8e2004-05-20 01:12:34 +00002237 }
danielk19776490beb2004-05-11 06:17:21 +00002238 Tcl_LinkVar(interp, "sqlite_search_count",
danielk19776f8a5032004-05-10 10:34:51 +00002239 (char*)&sqlite3_search_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00002240 Tcl_LinkVar(interp, "sqlite_interrupt_count",
danielk19776f8a5032004-05-10 10:34:51 +00002241 (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00002242 Tcl_LinkVar(interp, "sqlite_open_file_count",
danielk19776f8a5032004-05-10 10:34:51 +00002243 (char*)&sqlite3_open_file_count, TCL_LINK_INT);
danielk19776490beb2004-05-11 06:17:21 +00002244 Tcl_LinkVar(interp, "sqlite_current_time",
danielk19776f8a5032004-05-10 10:34:51 +00002245 (char*)&sqlite3_current_time, TCL_LINK_INT);
drh2ac3ee92004-06-07 16:27:46 +00002246 Tcl_LinkVar(interp, "sqlite_os_trace",
2247 (char*)&sqlite3_os_trace, TCL_LINK_INT);
drh7c972de2003-09-06 22:18:07 +00002248 Tcl_LinkVar(interp, "sqlite_static_bind_value",
2249 (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
drhd1bf3512001-04-07 15:24:33 +00002250 return TCL_OK;
2251}